diff --git a/.swift-version b/.swift-version index bb576dbde..9f55b2ccb 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -2.3 +3.0 diff --git a/.travis.yml b/.travis.yml index ac0b232e3..101b0b95a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ reference: http://www.objc.io/issue-6/travis-ci.html language: objective-c -osx_image: xcode8.1 +osx_image: xcode8.2 before_install: true install: true script: diff --git a/App/AppDelegate.swift b/App/AppDelegate.swift index eeed2caff..3a5f570be 100644 --- a/App/AppDelegate.swift +++ b/App/AppDelegate.swift @@ -19,9 +19,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return true } - func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { + func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool { return Lock.resumeAuth(url, options: options) } - } diff --git a/Cartfile b/Cartfile index 4689d4508..4b41999d3 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1 @@ -github "auth0/Auth0.swift" ~> 1.0 +github "auth0/Auth0.swift" ~> 1.1 diff --git a/Cartfile.resolved b/Cartfile.resolved index 26296d862..417d03a6e 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,4 +1,4 @@ -github "auth0/Auth0.swift" "1.0.1" +github "auth0/Auth0.swift" "1.1.0" github "emaloney/CleanroomASL" "2.0.0" github "Quick/Nimble" "v5.1.1" github "AliSoftware/OHHTTPStubs" "5.2.2-swift3" diff --git a/Lock/EnterpriseDomainInteractor.swift b/Lock/EnterpriseDomainInteractor.swift index db2d4ff5c..c751700ce 100644 --- a/Lock/EnterpriseDomainInteractor.swift +++ b/Lock/EnterpriseDomainInteractor.swift @@ -33,12 +33,12 @@ struct EnterpriseDomainInteractor: HRDAuthenticatable { let emailValidator: InputValidator = EmailValidator() let authenticator: OAuth2Authenticatable - init(connections: [EnterpriseConnection], authentication: OAuth2Authenticatable) { - self.connections = connections + init(connections: Connections, authentication: OAuth2Authenticatable) { + self.connections = connections.enterprise self.authenticator = authentication // Single Enterprise, defaulting connection - if self.connections.count == 1 { + if self.connections.count == 1 && connections.oauth2.isEmpty && connections.database == nil { self.connection = self.connections.first } } diff --git a/Lock/Router.swift b/Lock/Router.swift index f83321c09..94cde046d 100644 --- a/Lock/Router.swift +++ b/Lock/Router.swift @@ -101,14 +101,14 @@ class Router: Navigable { // Add Enterprise if !connections.enterprise.isEmpty { let authInteractor = Auth0OAuth2Interactor(webAuth: self.lock.webAuth, onCredentials: self.onAuthentication, options: self.lock.options) - let interactor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authInteractor) + let interactor = EnterpriseDomainInteractor(connections: connections, authentication: authInteractor) presenter.enterpriseInteractor = interactor } return presenter } if !connections.enterprise.isEmpty { let authInteractor = Auth0OAuth2Interactor(webAuth: self.lock.webAuth, onCredentials: self.onAuthentication, options: self.lock.options) - let interactor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authInteractor) + let interactor = EnterpriseDomainInteractor(connections: connections, authentication: authInteractor) // Single enterprise in active auth mode if let connection = interactor.connection, self.lock.options.enterpriseConnectionUsingActiveAuth.contains(connection.name) { return EnterpriseActiveAuth(connection) diff --git a/LockTests/Interactors/EnterpriseDomainInteractorSpec.swift b/LockTests/Interactors/EnterpriseDomainInteractorSpec.swift index 89a7b3bd1..013b9cc4b 100644 --- a/LockTests/Interactors/EnterpriseDomainInteractorSpec.swift +++ b/LockTests/Interactors/EnterpriseDomainInteractorSpec.swift @@ -45,7 +45,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { credentials = nil webAuth = MockWebAuth() authentication = Auth0OAuth2Interactor(webAuth: webAuth, onCredentials: {credentials = $0}, options: LockOptions()) - enterprise = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authentication) + enterprise = EnterpriseDomainInteractor(connections: connections, authentication: authentication) } afterEach { @@ -69,7 +69,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { connections = OfflineConnections() connections.enterprise(name: "TestAD", domains: []) - enterprise = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authentication) + enterprise = EnterpriseDomainInteractor(connections: connections, authentication: authentication) } it("connection should not default to single connection") { @@ -87,7 +87,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { beforeEach { connections = OfflineConnections() connections.enterprise(name: "TestAD", domains: []) - enterprise = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authentication) + enterprise = EnterpriseDomainInteractor(connections: connections, authentication: authentication) } it("should raise no error but no connection provided") { @@ -102,7 +102,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { beforeEach { connections = OfflineConnections() connections.enterprise(name: "TestAD", domains: ["test.com"]) - enterprise = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authentication) + enterprise = EnterpriseDomainInteractor(connections: connections, authentication: authentication) } it("should match email domain") { @@ -137,7 +137,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { connections = OfflineConnections() connections.enterprise(name: "TestAD", domains: ["test.com","pepe.com"]) - enterprise = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authentication) + enterprise = EnterpriseDomainInteractor(connections: connections, authentication: authentication) } it("should match first email domain and provide enteprise connection") { @@ -162,7 +162,7 @@ class EnterpriseDomainInteractorSpec: QuickSpec { connections = OfflineConnections() connections.enterprise(name: "TestAD", domains: ["test.com"]) - enterprise = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: authentication) + enterprise = EnterpriseDomainInteractor(connections: connections, authentication: authentication) } it("should fail to launch on no valid connection") { diff --git a/LockTests/Presenters/DatabasePresenterSpec.swift b/LockTests/Presenters/DatabasePresenterSpec.swift index b8b2464c8..cf315dbed 100644 --- a/LockTests/Presenters/DatabasePresenterSpec.swift +++ b/LockTests/Presenters/DatabasePresenterSpec.swift @@ -42,7 +42,7 @@ class DatabasePresenterSpec: QuickSpec { oauth2 = MockOAuth2() connections = OfflineConnections() - enterpriseInteractor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) + enterpriseInteractor = EnterpriseDomainInteractor(connections: connections, authentication: oauth2) authPresenter = MockAuthPresenter(connections: connections, interactor: MockAuthInteractor(), customStyle: [:]) messagePresenter = MockMessagePresenter() interactor = MockDBInteractor() @@ -541,7 +541,7 @@ class DatabasePresenterSpec: QuickSpec { connections = OfflineConnections() connections.enterprise(name: "validAD", domains: ["valid.com"]) - enterpriseInteractor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) + enterpriseInteractor = EnterpriseDomainInteractor(connections: connections, authentication: oauth2) presenter.enterpriseInteractor = enterpriseInteractor view = presenter.view as! DatabaseOnlyView @@ -635,7 +635,7 @@ class DatabasePresenterSpec: QuickSpec { connections.enterprise(name: "validAD", domains: ["valid.com"]) presenter = DatabasePresenter(authenticator: interactor, creator: interactor, connection: DatabaseConnection(name: connection, requiresUsername: true), navigator: navigator, options: options) - enterpriseInteractor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) + enterpriseInteractor = EnterpriseDomainInteractor(connections: connections, authentication: oauth2) presenter.enterpriseInteractor = enterpriseInteractor view = presenter.view as! DatabaseOnlyView diff --git a/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift b/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift index a3fc87e40..6548a05bf 100644 --- a/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift +++ b/LockTests/Presenters/EnterpriseDomainPresenterSpec.swift @@ -52,7 +52,7 @@ class EnterpriseDomainPresenterSpec: QuickSpec { connections.enterprise(name: "TestAD", domains: ["test.com"]) connections.enterprise(name: "ValidAD", domains: ["validad.com"]) - interactor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) + interactor = EnterpriseDomainInteractor(connections: connections, authentication: oauth2) presenter = EnterpriseDomainPresenter(interactor: interactor, navigator: navigator, user: user, options: options) presenter.messagePresenter = messagePresenter view = presenter.view as! EnterpriseDomainView @@ -82,7 +82,7 @@ class EnterpriseDomainPresenterSpec: QuickSpec { connections = OfflineConnections() connections.enterprise(name: "TestAD", domains: ["test.com"]) - interactor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) + interactor = EnterpriseDomainInteractor(connections: connections, authentication: oauth2) presenter = EnterpriseDomainPresenter(interactor: interactor, navigator: navigator, user: user, options: options) presenter.messagePresenter = messagePresenter view = presenter.view as! EnterpriseDomainView @@ -252,7 +252,7 @@ class EnterpriseDomainPresenterSpec: QuickSpec { connections = OfflineConnections() connections.enterprise(name: "TestAD", domains: ["test.com"]) - interactor = EnterpriseDomainInteractor(connections: connections.enterprise, authentication: oauth2) + interactor = EnterpriseDomainInteractor(connections: connections, authentication: oauth2) presenter = EnterpriseDomainPresenter(interactor: interactor, navigator: navigator, user: user, options: options) presenter.messagePresenter = messagePresenter view = presenter.view as! EnterpriseDomainView diff --git a/LockTests/Utils/Mocks.swift b/LockTests/Utils/Mocks.swift index 6677d9c8e..761f4ed30 100644 --- a/LockTests/Utils/Mocks.swift +++ b/LockTests/Utils/Mocks.swift @@ -245,6 +245,18 @@ class MockWebAuth: WebAuth { callback(self.result()) } + func responseType(_ response: [ResponseType]) -> Self { + return self + } + + func nonce(_ nonce: String) -> Self { + return self + } + + func audience(_ audience: String) -> Self { + return self + } + var logger: Auth0.Logger? = nil } diff --git a/README.md b/README.md index be8e453b2..b13e7f7f6 100644 --- a/README.md +++ b/README.md @@ -18,37 +18,37 @@ Lock makes it easy to integrate SSO in your app. You won't have to worry about: - iOS 9 or later - Xcode 8 -- Swift 2.3 +- Swift 3.0 ## Install ### Carthage -In your cartfile add +In your `Cartfile` add ``` -github "auth0/Lock.iOS-OSX" "2.0.0-beta.2" +github "auth0/Lock.iOS-OSX" "2.0.0-beta.3" ``` ## Usage -First to import **Lock.swift** +First import **Lock.swift** ```swift import Lock ``` -then in your `AppDelegate.swift` add the following +Next in your `AppDelegate.swift` add the following: ```swift -func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool { - return Lock.resumeAuth(url, options: options) +func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool { + return Lock.resumeAuth(url, options: options) } ``` ### Configuration -In order to use Lock you need to provide your Auth0 Client Id and Domain, either with a *Property List* file +In order to use Lock you need to provide your Auth0 Client Id and Domain. > Auth0 ClientId & Domain can be found in your [Auth0 Dashboard](https://manage.auth0.com) @@ -69,30 +69,25 @@ In your application bundle you can add a `plist` file named `Auth0.plist` with t ``` -### Classic +### Classic Lock Classic handles authentication using Database, Social & Enterprise connections. -> Currenty Lock.swift only supports Database & Social authentication and you need to tell Lock what connections it should use - To show **Lock.swift**, add the following snippet in any of your `UIViewController` ```swift Lock .classic() - .connections { - $0.database(name: "Username-Password-Authentication", requiresUsername: true) - } - .options { + .withOptions { $0.closable = false } .on { result in switch result { - case .Success(let credentials): + case .success(let credentials): print("Obtained credentials \(credentials)") - case .Failure(let cause): + case .failure(let cause): print("Failed with \(cause)") - case .Cancelled: + case .cancelled: print("User cancelled") } } @@ -101,26 +96,29 @@ Lock #### Specify Connections -> Eventually **Lock.swift** will be able to load your client configuration automatically, but until then you should describe what connections it should use. +**Lock.swift** will automatically load your client configuration automatically, if you wish to override this you can manually specify which of your connections to use. + +Before presenting **Lock.swift** you can tell it what connections it should display and use to authenticate an user. You can do that by calling the method and supply a closure that can specify the connections. -Before presenting **Lock.swift** you can tell it what connections it should display and use to authenticate an user. You can do that by calling the method and supply a closure that can specify the connections +Adding a database connection: ```swift -.connections { connections in - // Your connections +.withConnections { + $0.database(name: "Username-Password-Authentication", requiresUsername: true) } ``` -So if you need a database connection you can call +Adding multiple social connections: ```swift connections.database(name: "{CONNECTION_NAME}", requiresUsername: true) ``` -Or a social connection - ```swift -connections.social(name: "{CONNECTION_NAME}", style: .Facebook) +.withConnections { connections in + connections.social(name: "facebook", style: .Facebook) + connections.social(name: "google-oauth2", style: .Google) +} ``` ### Logging @@ -130,7 +128,7 @@ In **Lock.swift** options you can turn on/off logging capabilities ```swift Lock .classic() - .options { + .withOptions { $0.logLevel = .All $0.logHttpRequest = true } diff --git a/script/.env b/script/.env index 2739b916a..f88cc5ba3 100644 --- a/script/.env +++ b/script/.env @@ -1,6 +1,6 @@ REQUIRED_CARTHAGE_VERSION=0.18.1 -REQUIRED_SWIFTLINT_VERSION=0.13.0 +REQUIRED_SWIFTLINT_VERSION=0.13.2 CARTHAGE_BUILD_PLATFORM=${CARTHAGE_BUILD_PLATFORM:-"iOS"} CARTHAGE_NO_USE_BINARIES=${CARTHAGE_NO_USE_BINARIES:-"true"} PROJECT_NAME=Lock