Triggering non 'success' OktaAuthSdk status
t3ddyK opened this issue · 2 comments
I am trying to understand how the success statuses are triggered and their particular use case.
Say for example I have a method that invokes the below:
OktaAuthSdk.authenticate(
with: instance,
username: username,
password: password,
onStatusChange: { status in self.onStatusChange(status, completion) },
onError: { error in self.onAuthError(error, completion) }
)
The methods called are:
onStatusChange
private func onStatusChange(_ status: OktaAuthStatus, _ completion: @escaping ((Error?) -> Void)) {
switch status.statusType {
case .success:
let state: OktaAuthStatusSuccess = status as! OktaAuthStatusSuccess
handleSuccessStatus(state, completion)
case .passwordWarning:
let state: OktaAuthStatusPasswordWarning = status as! OktaAuthStatusPasswordWarning
handlePasswordWarning(state, completion)
case .passwordExpired:
let state: OktaAuthStatusPasswordExpired = status as! OktaAuthStatusPasswordExpired
handleChangePassword(state, completion)
case .MFAEnroll:
let state: OktaAuthStatusFactorEnroll = status as! OktaAuthStatusFactorEnroll
handleEnrollment(state, completion)
case .MFAEnrollActivate:
let state: OktaAuthStatusFactorEnrollActivate = status as! OktaAuthStatusFactorEnrollActivate
handleActivateEnrollment(state, completion)
case .MFARequired:
let state: OktaAuthStatusFactorRequired = status as! OktaAuthStatusFactorRequired
handleFactorRequired(state, completion)
case .MFAChallenge:
let state: OktaAuthStatusFactorChallenge = status as! OktaAuthStatusFactorChallenge
handleFactorChallenge(state, completion)
case .recovery:
let state: OktaAuthStatusRecovery = status as! OktaAuthStatusRecovery
handleRecovery(state, completion)
case .recoveryChallenge:
let state: OktaAuthStatusRecoveryChallenge = status as! OktaAuthStatusRecoveryChallenge
handleRecoveryChallenge(state, completion)
case .passwordReset:
let state: OktaAuthStatusPasswordReset = status as! OktaAuthStatusPasswordReset
handlePasswordReset(state, completion)
case .lockedOut:
let state: OktaAuthStatusLockedOut = status as! OktaAuthStatusLockedOut
handleLockedOut(state, completion)
case .unauthenticated:
let state: OktaAuthStatusUnauthenticated = status as! OktaAuthStatusUnauthenticated
handleUnauthenticated(state, completion)
case .unknown:
break
}
}
and also onAuthError
private func onAuthError(_ error: OktaError, _ completion: @escaping ((Error?) -> Void)) {
print(error)
print("\(#function) not implemented")
}
If for example I fail login, wrong username and password or my account is suspended, onAuthError
is triggered w/ Authentication failed
However there is no call on the .unauthenticated
flow of my status change switch statement.
In what scenario should these statuses be returned?
Hi @t3ddyK,
Each status class in SDK represents status in authentication state machine on server side. Please take a look on state machine diagram: https://camo.githubusercontent.com/55f77b31bb3e54665186b1aee1c2f4f65f7f8ed7/68747470733a2f2f646576656c6f7065722e6f6b74612e636f6d2f696d672f617574682d73746174652d6d6f64656c2e706e67
Your authentication journey starts with Unauthenticated
status and according to the diagram you can't return to this status from any other statuses. So you don't need handler for this status. State machine doesn't switch states in case of errors. In your example if you fail to login server doesn't move to the next status. It returns error and keeps state machine in current state which is Unauthenticated
state in your case.
Other states are required for different authentication cases. For example if your org wants to use multifactor authentication(MFA), then you have to implement MFAEnroll, MFAEnrollActivate, MFARequired and MFAChallenge. So everything depends on your org and it's current configuration.
For the basic configuration you usually must implement the following status handlers:
.success
- successful login. Retrieve session token and exchange it to access token via Okta OIDC SDK
.passwordReset
- warn customer that password is about to expire. Customer can change password now or skip it
.passwordExpired
- warn customer that password is expired. Customer must change password
More info about statuses you can find in developer documentation: https://developer.okta.com/docs/reference/api/authn/
Also please check our sample application that shows how to handle all available statues: https://github.com/okta/samples-ios/tree/master/custom-sign-in
Please let me know if you have any other questions
Ildar
Amazing, thank you I really appreciates this