Tengo un proyecto en Ionic angular, el cual tiene un Login a través de Microsoft usando la librería MSAL y configurando la aplicación en Azure AD, actualmente tengo problemas al emular el proyecto en Android studio, ya que cuando realizo el proceso de logueo me esta generando el siguiente error: • AADSTS9002326: Cross-origin token redemption is permitted only for the ‘Single-Page Application’ client-type. Request origin: ‘http://localhost’. Se ejecuta el siguiente comando para emular el proyecto en Android Studio: • ionic capacitor run android A continuación, relaciono el código del proyecto:
LoginPage
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { MsalService } from '@azure/msal-angular';
import { AuthService } from 'src/app/services/auth.service';
import { LogAplicacionService } from 'src/app/services/logaplicacion.service';
import { SimatdataService } from 'src/app/services/simatdata.service';
import { logAplicacion } from 'src/app/shared/logaplicacion.interface';
import { Simat } from 'src/app/shared/simat.interface';
import { Platform } from '@ionic/angular';
import { CustomNavigationClient } from './custom-navigation-client';
@Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {
constructor(private authService: MsalService, private router: Router,
private datosbasedata: SimatdataService, private auth: AuthService,
private logService: LogAplicacionService,
private platform: Platform) {
}
ngOnInit(): void {
this.authService.instance.setNavigationClient(new CustomNavigationClient(this.authService.instance));
}
async login() {
this.authService.instance.loginRedirect();
}
}
CustomNavigationClient
import { InAppBrowser } from "@awesome-cordova-plugins/in-app-browser";
import type { IPublicClientApplication } from "@azure/msal-browser";
import { NavigationClient } from "@azure/msal-browser";
import { Capacitor } from "@capacitor/core";
export class CustomNavigationClient extends NavigationClient {
constructor(private msalInstance: IPublicClientApplication) {
super();
}
async navigateExternal(url: string, options: any): Promise<boolean> {
if (Capacitor.isNativePlatform()) {
const browser = InAppBrowser.create(url, "_blank", {
location: "yes",
hidenavigationbuttons: "yes",
clearcache: "yes",
clearsessioncache: "yes",
hideurlbar: "yes",
fullscreen: "yes",
});
browser.on("loadstart").subscribe((event: any) => {
if (event.url.includes("#code")) {
browser.close();
const domain = event.url.split("#")[0];
alert(event.url)
const url = event.url.replace(domain, "http://localhost");
this.msalInstance
.handleRedirectPromise(url)
.then((res) => {
console.log('');
console.log(res?.account?.name + " has authenticated");
})
.catch((err) => {
//Siempre esta generando el error en esta seccion
console.log('Error handleRedirectPromise:');
console.log(err);
});
}
});
} else {
if (options.noHistory) {
window.location.replace(url);
} else {
window.location.assign(url);
}
}
return true;
}
}
AppModule
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { IonicModule } from '@ionic/angular';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { MsalModule } from '@azure/msal-angular';
import { PublicClientApplication, InteractionType } from '@azure/msal-browser';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { TokeninterceptorService } from './auth/token-interceptor.service';
import { environment } from 'src/environments/environment';
import { XFrameOptionsInterceptor } from './auth/XFrameOptionsInterceptor.service';
import { XContentTypeOptionsInterceptor } from './auth/XContentTypeOptionsInterceptor.service';
@NgModule({
declarations: [AppComponent],
imports: [
HttpClientModule,
BrowserModule,
IonicModule.forRoot(),
AppRoutingModule,
MsalModule.forRoot(new PublicClientApplication
(
{
auth:{
clientId: environment.CLIENT_ID,
redirectUri: environment.REDIRECT_URI,
postLogoutRedirectUri: environment.POSTLOGOUT_URI
},
cache:
{
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
secureCookies: false
},
}
),{
interactionType: InteractionType.Redirect,
authRequest: {
scopes:['api://<<ClientID>>/WebApiB.ExampleScope']
}
}, null
)
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: TokeninterceptorService,
multi: true},
{
provide: HTTP_INTERCEPTORS,
useClass: XFrameOptionsInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: XContentTypeOptionsInterceptor,
multi: true
},
],
bootstrap: [AppComponent],
})
export class AppModule {}
environment
export const environment = {
/*****URL SERVICIOS BACK********/
END_POINT_SSO: 'http://localhost:8080',
/*****URL SERVICIOS MSAL PERSONAL LOCAL ********/
CLIENT_ID: '<<ClientID>>', //CLIENT_ID personal
REDIRECT_URI: 'http://localhost', //REDIRECT_URI personal
POSTLOGOUT_URI: 'http://localhost', //POSTLOGOUT_URI personal
SCOPE: 'api:/<<clientID>>/WebApiB.ExampleScope', //SCOPE PERSONAL DESARROLLO,
production: false
};
Agradezco cualquier guia que me puedan brindar.
He configurado el handleRedirectPromise en el CustomNavigationClient, ya que en la ejecucion web tenia este metodo en el ngOnInit del LoginPage y allí funcionada correctamente y me redireccionada al home de mi aplicación una vez realizada el login exitosamente (La diferencia de la configuración WEB es que el redirect URI incluye el puerto http://localhost:7001/,al ejecutar con Ionic serve. Otra diferencia es que en via web no usaba el CustomNavigationClient) , pero al ejecutarlo en Android me abria el navegador del dispositivo movil, indage un poco y encontre la alternativa de usar NavigationClient de msal-brower