Skip to content

Commit cbf2064

Browse files
committed
added sso login
1 parent 84843d9 commit cbf2064

File tree

16 files changed

+336
-49
lines changed

16 files changed

+336
-49
lines changed

Cidaas.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
Pod::Spec.new do |s|
1010
s.name = 'Cidaas'
11-
s.version = '1.0.11'
11+
s.version = '1.1.0'
1212
s.summary = 'Native SDK for iOS providing login, registration and verification functionalities'
1313
s.homepage = 'https://github.com/Cidaas/cidaas-sdk-ios-v2'
1414
s.license = { :type => 'MIT', :file => 'LICENSE' }

Cidaas/Classes/Core/Controllers/Repository/Login/LoginController.swift

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,87 @@
77
//
88

99
import Foundation
10+
import SafariServices
1011

1112
public class LoginController {
1213

1314
// shared instance
1415
public static var shared : LoginController = LoginController()
16+
public var delegate: UIViewController = UIViewController()
17+
public var storage: TransactionStore = TransactionStore.shared
1518

1619
// constructor
1720
public init() {
1821

1922
}
2023

24+
// login With browser
25+
public func loginWithBrowser(delegate: UIViewController, properties: Dictionary<String, String>, callback: @escaping(Result<LoginResponseEntity>) -> Void) {
26+
// null check
27+
if properties["DomainURL"] == "" || properties["DomainURL"] == nil || properties["ClientId"] == "" || properties["ClientId"] == nil || properties["RedirectURL"] == "" || properties["RedirectURL"] == nil {
28+
let error = WebAuthError.shared.propertyMissingException()
29+
// log error
30+
let loggerMessage = "Read properties failure : " + "Error Code - " + String(describing: error.errorCode) + ", Error Message - " + error.errorMessage + ", Status Code - " + String(describing: error.statusCode)
31+
logw(loggerMessage, cname: "cidaas-sdk-error-log")
32+
33+
DispatchQueue.main.async {
34+
callback(Result.failure(error: error))
35+
}
36+
return
37+
}
38+
39+
self.delegate = delegate
40+
41+
// construct url
42+
let loginURL = constructURL(properties: properties)
43+
let redirectURL = URL(string: properties["RedirectURL"] ?? "")!
44+
45+
if #available(iOS 11.0, *) {
46+
47+
// initiate safari session with the constructed url performing single sign on
48+
let session = SafariAuthenticationSession(loginURL: loginURL, redirectURL: redirectURL, callback: callback)
49+
50+
// save the session
51+
self.storage.store(session)
52+
}
53+
else {
54+
55+
// call open safari method
56+
openSafari(loginURL : loginURL)
57+
}
58+
59+
60+
}
61+
62+
// open safari browser. This method opens the Safari browser to display the login page. This method should be called internally and only for lower versions of ios (below 11.0)
63+
private func openSafari(loginURL : URL) {
64+
65+
// assign url to safari controller
66+
let vc = SFSafariViewController(url: loginURL)
67+
68+
// present the safari controller
69+
self.delegate.present(vc, animated: true, completion: nil)
70+
}
71+
72+
private func constructURL(properties: Dictionary<String, String>) -> URL {
73+
74+
var urlParams = Dictionary<String, String>()
75+
urlParams["redirect_uri"] = properties["RedirectURL"] ?? ""
76+
urlParams["response_type"] = "code"
77+
urlParams["client_id"] = properties["ClientId"] ?? ""
78+
urlParams["view_type"] = properties["ViewType"] ?? "login"
79+
urlParams["code_challenge"] = properties["Challenge"]
80+
urlParams["code_challenge_method"] = properties["Method"]
81+
82+
var urlComponents = URLComponents(string : properties["AuthorizationURL"] ?? "")
83+
urlComponents?.queryItems = []
84+
for (key, value) in urlParams {
85+
urlComponents?.queryItems?.append(URLQueryItem(name: key, value: value))
86+
}
87+
88+
return (urlComponents?.url)!
89+
}
90+
2191
// login With Credentials
2292
public func loginWithCredentials(requestId: String, loginEntity: LoginEntity, properties: Dictionary<String, String>, callback: @escaping(Result<LoginResponseEntity>) -> Void) {
2393
// null check

Cidaas/Classes/Core/Controllers/Repository/Verification/Settings/VerificationSettingsController.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class VerificationSettingsController {
1818
}
1919

2020
// configure email from properties
21-
public func getMFAList(sub: String, properties: Dictionary<String, String>, callback: @escaping(Result<MFAListResponseEntity>) -> Void) {
21+
public func getMFAList(sub: String, common_config: Bool, properties: Dictionary<String, String>, callback: @escaping(Result<MFAListResponseEntity>) -> Void) {
2222
// null check
2323
if properties["DomainURL"] == "" || properties["DomainURL"] == nil {
2424
let error = WebAuthError.shared.propertyMissingException()
@@ -46,7 +46,7 @@ public class VerificationSettingsController {
4646
let userDeviceId = DBHelper.shared.getUserDeviceId(key: properties["DomainURL"] ?? "OAuthUserDeviceId")
4747

4848
// call getMFAList service
49-
VerificationSettingsService.shared.getMFAList(sub: sub, userDeviceId: userDeviceId, properties: properties) {
49+
VerificationSettingsService.shared.getMFAList(sub: sub, userDeviceId: userDeviceId, common_config: common_config, properties: properties) {
5050
switch $0 {
5151
case .failure(let error):
5252
// log error
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// URLExtensions.swift
3+
// Cidaas
4+
//
5+
// Created by ganesh on 04/12/18.
6+
//
7+
8+
import Foundation
9+
10+
public extension URL {
11+
func valueOf(_ queryParamaterName: String) -> String? {
12+
guard let url = URLComponents(string: self.absoluteString) else { return nil }
13+
return url.queryItems?.first(where: { $0.name == queryParamaterName })?.value
14+
}
15+
}

Cidaas/Classes/Core/Helpers/General/URLHelper.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,12 @@ public class URLHelper {
179179
return acceptConsentURL
180180
}
181181

182-
public func getMFAListURL(sub: String, userDeviceId: String) -> String {
183-
return "\(mfaListURL)?sub=\(sub)&userDeviceId=\(userDeviceId)&common_configs=true"
182+
public func getMFAListURL(sub: String, userDeviceId: String, common_config: Bool) -> String {
183+
184+
if (common_config == false) {
185+
return "\(mfaListURL)?sub=\(sub)&userDeviceId=\(userDeviceId)"
186+
}
187+
return "\(mfaListURL)?sub=\(sub)&userDeviceId=\(userDeviceId)&common_configs=\(common_config)"
184188
}
185189

186190
public func getSetupEmailURL() -> String {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//
2+
// AuthSession.swift
3+
// Cidaas
4+
//
5+
// Created by ganesh on 04/12/18.
6+
//
7+
8+
import Foundation
9+
10+
public class AuthSession: NSObject, OAuthTransactionDelegate {
11+
12+
public var state: String?
13+
var redirectURL : URL
14+
let callback : (Result<LoginResponseEntity>) -> ()
15+
16+
public init(redirectURL: URL, state: String? = nil, callback: @escaping (Result<LoginResponseEntity>) -> ()) {
17+
self.state = state
18+
self.redirectURL = redirectURL
19+
self.callback = callback
20+
super.init()
21+
}
22+
23+
public func resume(_ url: URL, options: [UIApplicationOpenURLOptionsKey: Any] = [:]) -> Bool {
24+
return true
25+
}
26+
27+
public func cancel() {
28+
// return error
29+
}
30+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//
2+
// SafariAuthenticationSession.swift
3+
// Cidaas
4+
//
5+
// Created by ganesh on 04/12/18.
6+
//
7+
8+
import Foundation
9+
import SafariServices
10+
11+
@available(iOS 11.0, *)
12+
public class SafariAuthenticationSession : AuthSession {
13+
14+
var authSession: SFAuthenticationSession?
15+
var loginURL: URL
16+
17+
public init(loginURL : URL, redirectURL : URL, callback: @escaping (Result<LoginResponseEntity>) -> ()) {
18+
self.loginURL = loginURL
19+
super.init(redirectURL: redirectURL, callback: callback)
20+
self.authSession = SFAuthenticationSession(url: self.loginURL, callbackURLScheme: self.redirectURL.absoluteString, completionHandler: { (resultURL, resultError) in
21+
guard resultError == nil, let callbackURL = resultURL else {
22+
if case SFAuthenticationError.canceledLogin = resultError! {
23+
// return error
24+
} else {
25+
// return error
26+
}
27+
return TransactionStore.shared.clear()
28+
}
29+
_ = TransactionStore.shared.resume(callbackURL, options: [:])
30+
})
31+
self.authSession?.start()
32+
}
33+
}

Cidaas/Classes/Core/Services/Entity/Verification/Settings/MFAListResponseEntity.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class MFAListResponseEntity : Codable {
1313
public var success: Bool = false
1414
public var status: Int16 = 400
1515
public var data: [MFAListResponseDataEntity] = []
16+
public var metaData: NewSub = NewSub()
1617

1718
// Constructors
1819
public init() {
@@ -24,13 +25,15 @@ public class MFAListResponseEntity : Codable {
2425
self.success = try container.decodeIfPresent(Bool.self, forKey: .success) ?? false
2526
self.status = try container.decodeIfPresent(Int16.self, forKey: .status) ?? 400
2627
self.data = try container.decodeIfPresent([MFAListResponseDataEntity].self, forKey: .data) ?? []
28+
self.metaData = try container.decodeIfPresent(NewSub.self, forKey: .metaData) ?? NewSub()
2729
}
2830
}
2931

3032
public class MFAListResponseDataEntity : Codable {
3133
// properties
3234
public var _id: String = ""
3335
public var verificationType: String = ""
36+
public var verifierId: String = ""
3437

3538
// Constructors
3639
public init() {
@@ -41,5 +44,46 @@ public class MFAListResponseDataEntity : Codable {
4144
let container = try decoder.container(keyedBy: CodingKeys.self)
4245
self._id = try container.decodeIfPresent(String.self, forKey: ._id) ?? ""
4346
self.verificationType = try container.decodeIfPresent(String.self, forKey: .verificationType) ?? ""
47+
self.verifierId = try container.decodeIfPresent(String.self, forKey: .verifierId) ?? ""
48+
}
49+
}
50+
51+
public class NewSub : Codable {
52+
53+
public var newSub : String = ""
54+
public var sub: String = ""
55+
public var identityId : String = ""
56+
public var name : String = ""
57+
public var given_name : String = ""
58+
public var family_name : String = ""
59+
public var provider : String = ""
60+
public var email : String = ""
61+
public var mobile : String = ""
62+
public var email_verified : Bool = false
63+
public var mobile_number_verified : Bool = false
64+
public var username : String = ""
65+
public var access_token: String = ""
66+
public var refresh_token: String = ""
67+
public var expires_in: Int64 = 86400
68+
69+
public init() {
70+
71+
}
72+
public required init(from decoder: Decoder) throws {
73+
let container = try decoder.container(keyedBy: CodingKeys.self)
74+
self.newSub = try container.decodeIfPresent(String.self, forKey: .newSub) ?? ""
75+
self.sub = try container.decodeIfPresent(String.self, forKey: .sub) ?? ""
76+
self.identityId = try container.decodeIfPresent(String.self, forKey: .identityId) ?? ""
77+
self.name = try container.decodeIfPresent(String.self, forKey: .name) ?? ""
78+
self.given_name = try container.decodeIfPresent(String.self, forKey: .given_name) ?? ""
79+
self.family_name = try container.decodeIfPresent(String.self, forKey: .family_name) ?? ""
80+
self.provider = try container.decodeIfPresent(String.self, forKey: .provider) ?? ""
81+
self.email = try container.decodeIfPresent(String.self, forKey: .email) ?? ""
82+
self.email_verified = try container.decodeIfPresent(Bool.self, forKey: .email_verified) ?? false
83+
self.mobile_number_verified = try container.decodeIfPresent(Bool.self, forKey: .mobile_number_verified) ?? false
84+
self.username = try container.decodeIfPresent(String.self, forKey: .username) ?? ""
85+
self.access_token = try container.decodeIfPresent(String.self, forKey: .access_token) ?? ""
86+
self.refresh_token = try container.decodeIfPresent(String.self, forKey: .refresh_token) ?? ""
87+
self.expires_in = try container.decodeIfPresent(Int64.self, forKey: .expires_in) ?? 86400
4488
}
4589
}

Cidaas/Classes/Core/Services/Repository/Verification/Settings/VerificationSettingsService.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class VerificationSettingsService {
2020
}
2121

2222
// get MFA List
23-
public func getMFAList(sub: String, userDeviceId: String, properties : Dictionary<String, String>, callback: @escaping(Result<MFAListResponseEntity>) -> Void) {
23+
public func getMFAList(sub: String, userDeviceId: String, common_config: Bool, properties : Dictionary<String, String>, callback: @escaping(Result<MFAListResponseEntity>) -> Void) {
2424
// local variables
2525
var headers : HTTPHeaders
2626
var urlString : String
@@ -54,7 +54,7 @@ public class VerificationSettingsService {
5454
}
5555

5656
// construct url
57-
urlString = baseURL + URLHelper.shared.getMFAListURL(sub: sub, userDeviceId: user_device_id)
57+
urlString = baseURL + URLHelper.shared.getMFAListURL(sub: sub, userDeviceId: user_device_id, common_config: common_config)
5858

5959

6060
// call service

Cidaas/Classes/Core/Views/Cidaas.swift

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//
88

99
import Foundation
10+
import SafariServices
1011

1112
public class Cidaas {
1213

@@ -22,10 +23,9 @@ public class Cidaas {
2223
var enablePkce : Bool = true
2324
var deviceInfo : DeviceInfoModel
2425
var storage: TransactionStore
25-
var loginCallback : ((Result<LoginResponseEntity>) -> Void)?
2626
var timer = Timer()
2727
var trackingManager: TrackingManager!
28-
public var delegate: UIViewController!
28+
public var browserCallback: ((Result<LoginResponseEntity>) -> ())!
2929

3030
// static variables
3131
public static var intermediate_verifiation_id: String = ""
@@ -72,8 +72,6 @@ public class Cidaas {
7272
// set storage in local
7373
self.storage = storage
7474

75-
self.loginCallback = nil
76-
7775
// set enable pkce in local
7876
self.ENABLE_PKCE = true
7977

@@ -165,6 +163,38 @@ public class Cidaas {
165163
}
166164
}
167165

166+
// -------------------------------------------------------------------------------------------------- //
167+
168+
// login with browser
169+
public func loginWithBrowser(delegate: UIViewController, callback: @escaping (Result<LoginResponseEntity>) -> Void) {
170+
let savedProp = DBHelper.shared.getPropertyFile()
171+
if (savedProp != nil) {
172+
self.browserCallback = callback
173+
LoginController.shared.loginWithBrowser(delegate: delegate, properties: savedProp!, callback: callback)
174+
}
175+
else {
176+
// log error
177+
let loggerMessage = "Read properties file failure : " + "Error Code - 10001, Error Message - File not found, Status Code - 404"
178+
logw(loggerMessage, cname: "cidaas-sdk-error-log")
179+
180+
let error = WebAuthError.shared.fileNotFoundException()
181+
182+
// return failure callback
183+
DispatchQueue.main.async {
184+
callback(Result.failure(error: error))
185+
}
186+
return
187+
}
188+
}
189+
190+
// -------------------------------------------------------------------------------------------------- //
191+
192+
// handle token
193+
public func handleToken(url: URL) {
194+
let code = url.valueOf("code") ?? ""
195+
AccessTokenController.shared.getAccessToken(code: code, callback: browserCallback!)
196+
}
197+
168198
// -------------------------------------------------------------------------------------------------- //
169199

170200
// stop session tracking
@@ -175,7 +205,7 @@ public class Cidaas {
175205
// -------------------------------------------------------------------------------------------------- //
176206

177207
// start tracking
178-
public func startTracking(sub: String) {
208+
public func startTracking(delegate: UIViewController, sub: String) {
179209
let savedProp = DBHelper.shared.getPropertyFile()
180210
if (savedProp != nil) {
181211
self.trackingManager.delegate = delegate
@@ -2253,11 +2283,11 @@ public class Cidaas {
22532283
// 2. Call getMFAList method
22542284
// 3. Maintain logs based on flags
22552285

2256-
public func getMFAList(sub: String, callback: @escaping(Result<MFAListResponseEntity>) -> Void) {
2286+
public func getMFAList(sub: String, common_config: Bool = true, callback: @escaping(Result<MFAListResponseEntity>) -> Void) {
22572287

22582288
let savedProp = DBHelper.shared.getPropertyFile()
22592289
if (savedProp != nil) {
2260-
VerificationSettingsController.shared.getMFAList(sub: sub, properties: savedProp!, callback: callback)
2290+
VerificationSettingsController.shared.getMFAList(sub: sub, common_config: common_config, properties: savedProp!, callback: callback)
22612291
}
22622292
else {
22632293
// log error

0 commit comments

Comments
 (0)