I followed the Microsoft B2C Msal example, to integrate B2C into my Ionic 7 Angular 17 mobile app.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/enable-authentication-angular-spa-app
I consolidated the MsalService code into my AppMsalService, below, to inject it. The B2C works fine in the browser, but when I build for Android Studio and run it there, I always get uninitialized_public_client_application and interaction_in_progress until session is cleared, or the app is restarted in Android Studio.
Why is the msalService initialized in web version, but not in Android version?
What needs to be done to make the msalService initialized in the Android Version, after the redirect from the InAppBrowser points the user back to the app on the device?
`import { Inject, Injectable } from '@angular/core';
import {
MSAL_GUARD_CONFIG,
MsalBroadcastService,
MsalGuardConfiguration,
MsalService,
} from '@azure/msal-angular';
import {
AuthenticationResult,
CacheLookupPolicy,
EventMessage,
EventType,
InteractionStatus,
InteractionType,
PopupRequest,
PublicClientApplication,
RedirectRequest,
} from '@azure/msal-browser';
import { Platform } from '@ionic/angular';
import { Store } from '@ngrx/store';
import { Subject, filter, takeUntil } from 'rxjs';
import { PigletActions } from './store/index copy';
import { msalConfig } from './configs/auth.config';
import NavigationAuthenticationClient from './common/navigation-auth-client';
@Injectable()
export class AppMsalService {
private readonly _destroying$ = new Subject<void>();
constructor(
@Inject(MSAL_GUARD_CONFIG) private msalGuardConfig: MsalGuardConfiguration,
private msalService: MsalService,
private msalBroadcastService: MsalBroadcastService,
private platform: Platform,
private store: Store
) {
this.initializeApp();
}
initializeApp(): void {
this.platform.ready().then(() => {
const pca = new PublicClientApplication(msalConfig);
this.msalService.instance.setNavigationClient(new NavigationAuthenticationClient(pca));
this.msalService.initialize();
this.inProgress();
this.msalSubject();
});
}
inProgress(): void {
this.msalBroadcastService.inProgress$
.pipe(
filter(
(status: InteractionStatus) => status === InteractionStatus.None
),
takeUntil(this._destroying$)
)
.subscribe(async () => this.setLoginDisplay());
}
msalSubject() {
this.msalBroadcastService.msalSubject$
.pipe(
filter(
(msg: EventMessage) =>
msg.eventType === EventType.LOGIN_SUCCESS ||
msg.eventType === EventType.SSO_SILENT_SUCCESS
)
)
.subscribe((result: EventMessage) => {
const payload = result.payload as AuthenticationResult;
this.msalService.instance.setActiveAccount(payload.account);
this.msalService
.acquireTokenSilent({
account: {
...payload.account,
username: payload.account.username,
},
scopes: ['application-id'],
forceRefresh: false,
cacheLookupPolicy: CacheLookupPolicy.AccessTokenAndRefreshToken,
})
.subscribe((t) => this.setupState(t));
this.setLoginDisplay();
});
}
setupState(t: any){
//retrieve from ngrx
}
setLoginDisplay() {
const loginDisplay = this.msalService.instance.getAllAccounts().length > 0;
this.store.dispatch(PigletActions.setLoginDisplay({ loginDisplay }));
}
login() {
if (this.msalGuardConfig.interactionType === InteractionType.Popup) {
if (this.msalGuardConfig.authRequest) {
this.msalService
.loginPopup({ ...this.msalGuardConfig.authRequest } as PopupRequest)
.subscribe((response: AuthenticationResult) => {
this.msalService.instance.setActiveAccount(response.account);
});
} else {
this.msalService
.loginPopup()
.subscribe((response: AuthenticationResult) => {
this.msalService.instance.setActiveAccount(response.account);
});
}
} else {
if (this.msalGuardConfig.authRequest) {
this.msalService.loginRedirect({
...this.msalGuardConfig.authRequest,
} as RedirectRequest);
} else {
this.msalService.loginRedirect();
}
}
}
logout() {
if (this.msalGuardConfig.interactionType === InteractionType.Popup) {
this.msalService.logoutPopup({
postLogoutRedirectUri: 'http://localhost:8100',
mainWindowRedirectUri: 'http://localhost:8100',
});
} else {
this.msalService.logoutRedirect({
postLogoutRedirectUri: 'http://localhost:8100',
});
}
}
}`
It has the same behavior if left in the app.component.ts or if the msal code is in the AppComponentService.
The
this.msalService.initialize();
is called the same amount of times in the app.component.ts as if it was in the AppMsalService.