Skip to content

Commit 1f9b11a

Browse files
authored
Native auth: Update Email OTP MFA to Match EC Implementation, Fixes AB#3351233 (#2379)
This PR updates the SDK to match the latest flow from EC. In this new flow, the developer must always supply an auth Method to the /oauth2/v2.0/challenge endpoint which means once the .mfaRequired error is received from token endpoint, the /oauth2/v2.0/introspect endpoint needs to be called to retrieve the methods which are automatically returned to the external developer. Furthermore, whenever calling the /token endpoint is called with an MFA Email OTP code, the grant type should be mfa_oob Fixes [AB#3351233](https://identitydivision.visualstudio.com/Engineering/_workitems/edit/3351233) MSAL Common PR: AzureAD/microsoft-authentication-library-common-for-android#2760
1 parent 960bc92 commit 1f9b11a

File tree

11 files changed

+74
-943
lines changed

11 files changed

+74
-943
lines changed

common

Submodule common updated 23 files

msal/src/main/java/com/microsoft/identity/client/internal/CommandParametersAdapter.java

Lines changed: 4 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,7 @@
6161
import com.microsoft.identity.common.java.dto.AccountRecord;
6262
import com.microsoft.identity.common.java.exception.ClientException;
6363
import com.microsoft.identity.common.java.nativeauth.authorities.NativeAuthCIAMAuthority;
64-
import com.microsoft.identity.common.java.nativeauth.commands.parameters.GetAuthMethodsCommandParameters;
65-
import com.microsoft.identity.common.java.nativeauth.commands.parameters.MFADefaultChallengeCommandParameters;
66-
import com.microsoft.identity.common.java.nativeauth.commands.parameters.MFASelectedDefaultChallengeCommandParameters;
64+
import com.microsoft.identity.common.java.nativeauth.commands.parameters.MFAChallengeAuthMethodCommandParameters;
6765
import com.microsoft.identity.common.java.nativeauth.commands.parameters.MFASubmitChallengeCommandParameters;
6866
import com.microsoft.identity.common.java.nativeauth.commands.parameters.ResetPasswordResendCodeCommandParameters;
6967
import com.microsoft.identity.common.java.nativeauth.commands.parameters.ResetPasswordStartCommandParameters;
@@ -778,54 +776,6 @@ public static SignInSubmitPasswordCommandParameters createSignInSubmitPasswordCo
778776
return commandParameters;
779777
}
780778

781-
/**
782-
* Creates command parameter for [{@link com.microsoft.identity.common.nativeauth.internal.commands.MFAChallengeCommand}] of Native Auth
783-
* @param configuration PCA configuration
784-
* @param tokenCache token cache for storing results
785-
* @param correlationId correlation ID to use in the API request, taken from the previous request in the flow
786-
* @param continuationToken continuation token
787-
* @param scopes scopes requested during sign in flow
788-
* @return Command parameter object
789-
* @throws ClientException
790-
*/
791-
public static MFADefaultChallengeCommandParameters createMFADefaultChallengeCommandParameters(
792-
@NonNull final NativeAuthPublicClientApplicationConfiguration configuration,
793-
@NonNull final OAuth2TokenCache tokenCache,
794-
@NonNull final String continuationToken,
795-
@NonNull final String correlationId,
796-
final List<String> scopes) throws ClientException {
797-
798-
final NativeAuthCIAMAuthority authority = ((NativeAuthCIAMAuthority) configuration.getDefaultAuthority());
799-
800-
final AbstractAuthenticationScheme authenticationScheme = AuthenticationSchemeFactory.createScheme(
801-
AndroidPlatformComponentsFactory.createFromContext(configuration.getAppContext()),
802-
null
803-
);
804-
805-
final MFADefaultChallengeCommandParameters commandParameters =
806-
MFADefaultChallengeCommandParameters.builder()
807-
.platformComponents(AndroidPlatformComponentsFactory.createFromContext(configuration.getAppContext()))
808-
.applicationName(configuration.getAppContext().getPackageName())
809-
.applicationVersion(getPackageVersion(configuration.getAppContext()))
810-
.clientId(configuration.getClientId())
811-
.isSharedDevice(configuration.getIsSharedDevice())
812-
.redirectUri(configuration.getRedirectUri())
813-
.oAuth2TokenCache(tokenCache)
814-
.requiredBrokerProtocolVersion(configuration.getRequiredBrokerProtocolVersion())
815-
.sdkType(SdkType.MSAL)
816-
.sdkVersion(PublicClientApplication.getSdkVersion())
817-
.powerOptCheckEnabled(configuration.isPowerOptCheckForEnabled())
818-
.authority(authority)
819-
.authenticationScheme(authenticationScheme)
820-
.continuationToken(continuationToken)
821-
.scopes(scopes)
822-
.challengeType(configuration.getChallengeTypes())
823-
.correlationId(correlationId)
824-
.build();
825-
826-
return commandParameters;
827-
}
828-
829779
/**
830780
* Creates command parameter for [{@link com.microsoft.identity.common.nativeauth.internal.commands.MFAChallengeCommand}] of Native Auth
831781
* @param configuration PCA configuration
@@ -836,7 +786,7 @@ public static MFADefaultChallengeCommandParameters createMFADefaultChallengeComm
836786
* @return Command parameter object
837787
* @throws ClientException
838788
*/
839-
public static MFASelectedDefaultChallengeCommandParameters createMFASelectedChallengeCommandParameters(
789+
public static MFAChallengeAuthMethodCommandParameters createMFAChallengeAuthMethodCommandParameters(
840790
@NonNull final NativeAuthPublicClientApplicationConfiguration configuration,
841791
@NonNull final OAuth2TokenCache tokenCache,
842792
@NonNull final String continuationToken,
@@ -853,8 +803,8 @@ public static MFASelectedDefaultChallengeCommandParameters createMFASelectedChal
853803

854804
final String authMethodId = authMethod.getId();
855805

856-
final MFASelectedDefaultChallengeCommandParameters commandParameters =
857-
MFASelectedDefaultChallengeCommandParameters.builder()
806+
final MFAChallengeAuthMethodCommandParameters commandParameters =
807+
MFAChallengeAuthMethodCommandParameters.builder()
858808
.platformComponents(AndroidPlatformComponentsFactory.createFromContext(configuration.getAppContext()))
859809
.applicationName(configuration.getAppContext().getPackageName())
860810
.applicationVersion(getPackageVersion(configuration.getAppContext()))
@@ -927,44 +877,6 @@ public static MFASubmitChallengeCommandParameters createMFASubmitChallengeComman
927877
return commandParameters;
928878
}
929879

930-
/**
931-
* Creates command parameter for [{@link com.microsoft.identity.common.nativeauth.internal.commands.GetAuthMethodsCommand}] of Native Auth
932-
* @param configuration PCA configuration
933-
* @param tokenCache token cache for storing results
934-
* @param correlationId correlation ID to use in the API request, taken from the previous request in the flow
935-
* @param continuationToken Continuation token
936-
* @return Command parameter object
937-
*/
938-
public static GetAuthMethodsCommandParameters createGetAuthMethodsCommandParameters(
939-
@NonNull final NativeAuthPublicClientApplicationConfiguration configuration,
940-
@NonNull final OAuth2TokenCache tokenCache,
941-
@NonNull final String continuationToken,
942-
@NonNull final String correlationId) {
943-
944-
final NativeAuthCIAMAuthority authority = ((NativeAuthCIAMAuthority) configuration.getDefaultAuthority());
945-
946-
final GetAuthMethodsCommandParameters commandParameters =
947-
GetAuthMethodsCommandParameters.builder()
948-
.platformComponents(AndroidPlatformComponentsFactory.createFromContext(configuration.getAppContext()))
949-
.applicationName(configuration.getAppContext().getPackageName())
950-
.applicationVersion(getPackageVersion(configuration.getAppContext()))
951-
.clientId(configuration.getClientId())
952-
.isSharedDevice(configuration.getIsSharedDevice())
953-
.redirectUri(configuration.getRedirectUri())
954-
.oAuth2TokenCache(tokenCache)
955-
.requiredBrokerProtocolVersion(configuration.getRequiredBrokerProtocolVersion())
956-
.sdkType(SdkType.MSAL)
957-
.sdkVersion(PublicClientApplication.getSdkVersion())
958-
.powerOptCheckEnabled(configuration.isPowerOptCheckForEnabled())
959-
.authority(authority)
960-
.continuationToken(continuationToken)
961-
.challengeType(configuration.getChallengeTypes())
962-
.correlationId(correlationId)
963-
.build();
964-
965-
return commandParameters;
966-
}
967-
968880
/**
969881
* Creates command parameter for [ResetPasswordStartCommand] of Native Auth.
970882
* @param configuration PCA configuration

msal/src/main/java/com/microsoft/identity/nativeauth/NativeAuthPublicClientApplication.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,8 @@ class NativeAuthPublicClientApplication(
768768
correlationId = result.correlationId,
769769
scopes = scopes,
770770
config = nativeAuthConfig
771-
)
771+
),
772+
authMethods = result.authMethods.toListOfAuthMethods()
772773
)
773774
}
774775

msal/src/main/java/com/microsoft/identity/nativeauth/statemachine/errors/MFAErrors.kt

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.microsoft.identity.nativeauth.statemachine.errors
22

3-
import com.microsoft.identity.nativeauth.statemachine.results.MFAGetAuthMethodsResult
43
import com.microsoft.identity.nativeauth.statemachine.results.MFARequiredResult
54
import com.microsoft.identity.nativeauth.statemachine.results.MFASubmitChallengeResult
65

@@ -26,27 +25,6 @@ class MFARequestChallengeError(
2625
override var exception: Exception? = null
2726
): MFARequiredResult, BrowserRequiredError, Error(errorType = errorType, error = error, errorMessage= errorMessage, correlationId = correlationId, errorCodes = errorCodes, exception = exception)
2827

29-
/**
30-
* MFA get authentication methods error. Use the utility methods of this class
31-
* to identify and handle the error. This error is produced by
32-
* [com.microsoft.identity.nativeauth.statemachine.states.MFARequiredState.getAuthMethods]
33-
* @param errorType the error type value of the error that occurred.
34-
* @param error the error returned by the authentication server.
35-
* @param errorMessage the error message returned by the authentication server.
36-
* @param correlationId a unique identifier for the request that can help in diagnostics.
37-
* @param errorCodes a list of specific error codes returned by the authentication server.
38-
* @param exception an internal unexpected exception that happened.
39-
*/
40-
class MFAGetAuthMethodsError(
41-
override val errorType: String? = null,
42-
override val error: String? = null,
43-
override val errorMessage: String?,
44-
override val correlationId: String,
45-
override val errorCodes: List<Int>? = null,
46-
val subError: String? = null,
47-
override var exception: Exception? = null
48-
): MFAGetAuthMethodsResult, BrowserRequiredError, Error(errorType = errorType, error = error, errorMessage= errorMessage, correlationId = correlationId, errorCodes = errorCodes, exception = exception)
49-
5028
/**
5129
* MFA submit challenge error. The user should use the utility methods of this class
5230
* to identify and handle the error. This error is produced by

msal/src/main/java/com/microsoft/identity/nativeauth/statemachine/results/MFAResult.kt

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
package com.microsoft.identity.nativeauth.statemachine.results
2525

26-
import com.microsoft.identity.nativeauth.AuthMethod
2726
import com.microsoft.identity.nativeauth.statemachine.states.MFARequiredState
2827

2928
/**
@@ -46,26 +45,8 @@ interface MFARequiredResult: Result {
4645
val sentTo: String,
4746
val channel: String,
4847
) : MFARequiredResult, Result.SuccessResult(nextState = nextState)
49-
50-
/**
51-
* Selection required result, which indicates that a specific authentication method must be selected, which
52-
* the server will send the challenge to (once sendChallenge() is called).
53-
*
54-
* @param nextState [com.microsoft.identity.nativeauth.statemachine.states.MFARequiredState] the current state of the flow with follow-on methods.
55-
* @param authMethods the authentication methods that can be used to complete the challenge flow.
56-
*/
57-
class SelectionRequired(
58-
override val nextState: MFARequiredState,
59-
val authMethods: List<AuthMethod>
60-
) : MFARequiredResult, MFAGetAuthMethodsResult, Result.SuccessResult(nextState = nextState)
6148
}
6249

63-
/**
64-
* Results related to get authentication methods operation, produced by
65-
* [com.microsoft.identity.nativeauth.statemachine.states.MFARequiredState.getAuthMethods]
66-
*/
67-
interface MFAGetAuthMethodsResult : Result
68-
6950
/**
7051
* Results related to MFA submit challenge operation, produced by
7152
* [com.microsoft.identity.nativeauth.statemachine.states.MFARequiredState.submitChallenge]

msal/src/main/java/com/microsoft/identity/nativeauth/statemachine/results/SignInResult.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,9 @@ interface SignInResult : Result {
8282
* @param nextState [com.microsoft.identity.nativeauth.statemachine.states.AwaitingMFAState] the current state of the flow with follow-on methods.
8383
*/
8484
class MFARequired(
85-
override val nextState: AwaitingMFAState
86-
) : SignInResult, Result.SuccessResult(nextState = nextState), SignInSubmitPasswordResult
85+
override val nextState: AwaitingMFAState,
86+
val authMethods: List<AuthMethod>
87+
) : Result.SuccessResult(nextState = nextState), SignInResult, SignInSubmitPasswordResult
8788

8889
/**
8990
* StrongAuthMethodRegistration Result, which indicates that a registration of a strong authentication method is required to continue.
@@ -94,7 +95,7 @@ interface SignInResult : Result {
9495
class StrongAuthMethodRegistrationRequired(
9596
override val nextState: RegisterStrongAuthState,
9697
val authMethods: List<AuthMethod>
97-
) : SignInResult, SignInSubmitPasswordResult, Result.SuccessResult(nextState = nextState)
98+
) : Result.SuccessResult(nextState = nextState), SignInResult, SignInSubmitPasswordResult
9899
}
99100

100101
/**

0 commit comments

Comments
 (0)