policyTriggerInteractive method
Runs user flow interactively.
Once the user finishes with the flow, an access-token and an id-token containing user's claims are stored in the sessionStorage or localStorage respectively as specified in the configuration file.
The tag
argument is used to distinguish which invocation of this
function generated the return callback. The policyName
permits to
select which authority (user-flow) trigger from the ones specified in the
configuration file. It must be indicated just the name of the policy
without the host and tenat part. It is possible to indicate user's
scopes
for the request (i.e it is also possible to indicate default
scopes in the configuration file that can be then accessed from
B2CConfiguration.defaultScopes). A loginHint
may be passed to directly
fill the email/username/phone-number field in the policy flow.
Based on the specified field <interaction_mode>: popup|redirect
in the
configuration file, the policy will be triggered via redirect or with a
popup respectively if B2CInteractionMode.REDIRECT or
B2CInteractionMode.POPUP is selected.
In B2CInteractionMode.REDIRECT mode the policy state hash
parameter must be intercepted during app startup as specified in the
plugin implementation.
Returns a Future callable from the AzureB2C plugin.
It emits a B2COperationResult from B2COperationSource.POLICY_TRIGGER_INTERACTIVE with possible results:
- B2COperationState.SUCCESS if successful,
- B2COperationState.CLIENT_ERROR if an error occurred,
- B2COperationState.PASSWORD_RESET if user requested a password reset,
- B2COperationState.USER_CANCELLED_OPERATION if the user cancelled the operation (only in B2CInteractionMode.POPUP),
- B2COperationState.SERVICE_ERROR if there is a configuration error with respect to the authority setting or if the authentication provider is down for some reasons.
Implementation
Future policyTriggerInteractive(String tag, String policyName,
List<String> scopes, String? loginHint) async {
try {
if (_interactionMode == B2CInteractionMode.REDIRECT) {
await _b2cApp!.acquireTokenRedirect(RedirectRequest()
..scopes = scopes
..authority = _getAuthorityFromPolicyName(policyName)
..loginHint = loginHint);
return; //redirect flow will restart the app
} else {
var result = await _b2cApp!.acquireTokenPopup(PopupRequest()
..scopes = scopes
..authority = _getAuthorityFromPolicyName(policyName)
..loginHint = loginHint);
_users[result.uniqueId] = result.account!;
_accessTokens[result.uniqueId] = _accessTokenFromAuthResult(result);
}
_emitCallback(B2COperationResult(
tag,
B2COperationSource.POLICY_TRIGGER_INTERACTIVE,
B2COperationState.SUCCESS));
} on AuthException catch (exception) {
if (exception.errorMessage.contains(_B2C_PASSWORD_CHANGE)) {
_emitCallback(B2COperationResult(
tag,
B2COperationSource.POLICY_TRIGGER_INTERACTIVE,
B2COperationState.PASSWORD_RESET));
} else {
/* Failed to acquireToken */
log("Authentication failed: $exception", name: tag);
if (exception is ClientAuthException) {
/* Exception inside MSAL, more info inside MsalError.java */
_emitCallback(B2COperationResult(
tag,
B2COperationSource.POLICY_TRIGGER_INTERACTIVE,
B2COperationState.CLIENT_ERROR));
} else if (exception is ServerException) {
/* Exception when communicating with the STS, likely config issue */
_emitCallback(B2COperationResult(
tag,
B2COperationSource.POLICY_TRIGGER_INTERACTIVE,
B2COperationState.SERVICE_ERROR));
} else if (exception is BrowserAuthException) {
if (exception.errorCode.contains(_B2C_USER_CANCELLED)) {
/* User closed popup */
_emitCallback(B2COperationResult(
tag,
B2COperationSource.POLICY_TRIGGER_INTERACTIVE,
B2COperationState.USER_CANCELLED_OPERATION));
return;
}
_emitCallback(B2COperationResult(
tag,
B2COperationSource.POLICY_TRIGGER_INTERACTIVE,
B2COperationState.CLIENT_ERROR));
}
}
}
}