@@ -4,6 +4,7 @@ import PublicClientApplication, {
44 MSALSilentParams ,
55 MSALAccount ,
66 MSALSignoutParams ,
7+ MSALWebviewParams ,
78} from 'react-native-msal' ;
89
910export interface B2CPolicies {
@@ -15,6 +16,8 @@ export type B2CSignInParams = Omit<MSALInteractiveParams, 'authority'>;
1516export type B2CAcquireTokenSilentParams = Pick < MSALSilentParams , 'forceRefresh' | 'scopes' > ;
1617export type B2CSignOutParams = Pick < MSALSignoutParams , 'signoutFromBrowser' | 'webviewParameters' > ;
1718
19+ const delay = ( ms : number ) => new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
20+
1821export default class B2CClient {
1922 private static readonly B2C_PASSWORD_CHANGE = 'AADB2C90118' ;
2023 private pca : PublicClientApplication ;
@@ -50,7 +53,7 @@ export default class B2CClient {
5053 try {
5154 // If we don't provide an authority, the PCA will use the one we passed to it when we created it
5255 // (the sign in sign up policy)
53- return await this . pca . acquireToken ( { ... params } ) ;
56+ return await this . pca . acquireToken ( params ) ;
5457 } catch ( error ) {
5558 if ( error . message . includes ( B2CClient . B2C_PASSWORD_CHANGE ) && this . policies . passwordReset ) {
5659 return await this . resetPassword ( params ) ;
@@ -87,12 +90,23 @@ export default class B2CClient {
8790 }
8891
8992 private async resetPassword ( params : B2CSignInParams ) {
93+ const { webviewParameters : wvp , ...rest } = params ;
94+ const webviewParameters : MSALWebviewParams = {
95+ ...wvp ,
96+ // We use an ephemeral session because if we're resetting a password it means the user
97+ // is not using an identity provider, so we don't need a logged-in browser session
98+ ios_prefersEphemeralWebBrowserSession : true ,
99+ } ;
90100 if ( this . policies . passwordReset ) {
101+ // Because there is no prompt before starting an ephemeral session, it will be quick to
102+ // open and begin before the other one has ended, causing an error saying that only one
103+ // interactive session is allowed at a time. So we have to slow it down a little
104+ await delay ( 1000 ) ;
91105 // Use the password reset policy and the interactive `acquireToken` call
92106 const authority = this . getAuthority ( this . policies . passwordReset ) ;
93- await this . pca . acquireToken ( { ...params , authority } ) ;
107+ await this . pca . acquireToken ( { ...rest , webviewParameters , authority } ) ;
94108 // Sign in again after resetting the password
95- return await this . signIn ( { ... params } ) ;
109+ return await this . signIn ( params ) ;
96110 } else {
97111 throw Error ( 'B2CClient missing password reset policy' ) ;
98112 }
0 commit comments