Skip to content

Commit

Permalink
Add support for triggering and completing OOB multifactor authenticat…
Browse files Browse the repository at this point in the history
…ion challenges
  • Loading branch information
ejensen committed Feb 11, 2021
1 parent 300b600 commit 0509e0f
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Cartfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
github "auth0/Auth0.swift" ~> 1.0
github "auth0/Auth0.swift" "master" #revert to ~> 1.0 once commit f1059fe is in a release tag
8 changes: 4 additions & 4 deletions Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github "AliSoftware/OHHTTPStubs" "9.0.0"
github "AliSoftware/OHHTTPStubs" "9.1.0"
github "Quick/Nimble" "v9.0.0"
github "Quick/Quick" "v3.0.0"
github "auth0/Auth0.swift" "1.29.0"
github "auth0/JWTDecode.swift" "2.5.0"
github "Quick/Quick" "v3.1.2"
github "auth0/Auth0.swift" "96e153847a1774129abf4b25695170aee92b1a55"
github "auth0/JWTDecode.swift" "2.6.0"
github "auth0/SimpleKeychain" "0.12.1"
github "emaloney/CleanroomLogger" "7.0.0"
34 changes: 29 additions & 5 deletions Lock/MultifactorInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import Foundation
import Auth0

struct MultifactorInteractor: MultifactorAuthenticatable, Loggable {
class MultifactorInteractor: MultifactorAuthenticatable, Loggable {

private var connection: DatabaseConnection
private var user: DatabaseUser
Expand All @@ -32,6 +32,7 @@ struct MultifactorInteractor: MultifactorAuthenticatable, Loggable {
private(set) var code: String?
private(set) var validCode: Bool = false
private(set) var mfaToken: String?
private var challenge: Challenge?
let dispatcher: Dispatcher

private let validator = OneTimePasswordValidator()
Expand All @@ -45,9 +46,13 @@ struct MultifactorInteractor: MultifactorAuthenticatable, Loggable {
self.dispatcher = dispatcher
self.options = options
self.mfaToken = mfaToken

if let mfaToken = mfaToken {
self.startMultifactorChallenge(mfaToken: mfaToken)
}
}

mutating func setMultifactorCode(_ code: String?) throws {
func setMultifactorCode(_ code: String?) throws {
self.validCode = false
self.code = code?.trimmingCharacters(in: CharacterSet.whitespaces)
if let error = self.validator.validate(code) {
Expand Down Expand Up @@ -76,9 +81,16 @@ struct MultifactorInteractor: MultifactorAuthenticatable, Loggable {
self.logger.error("Token required for OIDC MFA")
return callback(.couldNotLogin)
}
authentication
.login(withOTP: code, mfaToken: mfaToken)
.start { self.handle(identifier: identifier, result: $0, callback: callback) }

if self.challenge?.challengeType == "oob", let oobCode = self.challenge?.oobCode {
authentication
.login(withOOBCode: oobCode, mfaToken: mfaToken, bindingCode: code)
.start { self.handle(identifier: identifier, result: $0, callback: callback) }
} else {
authentication
.login(withOTP: code, mfaToken: mfaToken)
.start { self.handle(identifier: identifier, result: $0, callback: callback) }
}
} else {
authentication
.login(
Expand All @@ -92,4 +104,16 @@ struct MultifactorInteractor: MultifactorAuthenticatable, Loggable {
.start { self.handle(identifier: identifier, result: $0, callback: callback) }
}
}

private func startMultifactorChallenge(mfaToken: String) {
authentication.multifactorChallenge(mfaToken: mfaToken, types: nil, channel: nil, authenticatorId: nil).start { [weak self] result in
switch result {
case let .success(response):
self?.challenge = response

case let .failure(error):
self?.logger.error("Failed to start MFA challenge \(error)")
}
}
}
}
12 changes: 12 additions & 0 deletions LockTests/Utils/Mocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,18 @@ class MockAuthentication: Authentication {
return self.authentication.login(withOTP: otp, mfaToken: mfaToken)
}

func login(withOOBCode oobCode: String, mfaToken: String, bindingCode: String?) -> Request<Credentials, AuthenticationError> {
return self.authentication.login(withOOBCode: oobCode, mfaToken: mfaToken, bindingCode: bindingCode)
}

func login(withRecoveryCode recoveryCode: String, mfaToken: String) -> Request<Credentials, AuthenticationError> {
return self.authentication.login(withRecoveryCode: recoveryCode, mfaToken: mfaToken)
}

func multifactorChallenge(mfaToken: String, types: [String]?, channel: String?, authenticatorId: String?) -> Request<Challenge, AuthenticationError> {
return self.authentication.multifactorChallenge(mfaToken: mfaToken, types: types, channel: channel, authenticatorId: authenticatorId)
}

func tokenExchange(withCode code: String, codeVerifier: String, redirectURI: String) -> Request<Credentials, AuthenticationError> {
return self.authentication.tokenExchange(withCode: code, codeVerifier: codeVerifier, redirectURI: redirectURI)
}
Expand Down

0 comments on commit 0509e0f

Please sign in to comment.