Description
Core Library
MSAL.js (@azure/msal-browser)
Core Library Version
3.27.0
Wrapper Library
MSAL Angular (@azure/msal-angular)
Wrapper Library Version
3.1.0
Public or Confidential Client?
Public
Description
Scenario
- Angular is built and its assets uploaded to
https://cdn.example.com/my-app/1.2.3/
- The application is served from an nginx web server at
https://app.example.com/
(maybe it has the API there, or just a lot of important proxies etc)
The idiomatic way of doing this
- Build the Angular app with
--base-href="https://cdn.example.com/my-app/1.2.3/"
- Provide
https://app.example.com/
as APP_BASE_HREF (otherwise no routes will work)
This will set <base href="https://cdn.example.com/my-app/1.2.3/">
in the built index.html
, not hardcode any base urls in the assets, and prefix all routes in the app with https://app.example.com/
. Otherwise they'll try to use the base href and you'll end up on the CDN.
Error Message
What happens is that, a lot of times, the MSAL library will redirect away for auth, then back again to the CDN and not the app! Which of course explodes, because that's not where the app lives, it's served by a web server on https://app.example.com/
.
I still haven't understood exactly when it happens and when it doesn't but the culprit seems to live here:
It calculates the baseUrl using the base
element. Which Angular wants you to set to the CDN!
Here's some context where people got mad when Angular deprecated deployUrl
(later reversed, but with gotchas) with suggestions about the idiomatic way of serving things: angular/angular-cli#23765
MSAL Logs
Not sure what logs are applicable here. I can barely capture anything before getting redirected away, I have to throw myself on the escape key :-)
Network Trace (Preferrably Fiddler)
- Sent
- Pending
MSAL Configuration
{
auth: {
clientId: 'super-secret-client-id',
authority: 'super-secret-client-authority,
redirectUri: 'https://app.example.com/',
postLogoutRedirectUri: 'https://app.example.com/',
},
cache: {
cacheLocation: BrowserCacheLocation.LocalStorage,
}
}
Relevant Code Snippets
getDestinationUrl(path: string): string {
this.authService.getLogger().verbose("Guard - getting destination url");
// Absolute base url for the application (default to origin if base element not present)
const baseElements = document.getElementsByTagName("base");
const baseUrl = this.location.normalize(
baseElements.length ? baseElements[0].href : window.location.origin
);
// ....
Reproduction Steps
- Configure your assets to live on a CDN referenced via
<base href>
as per Angular recommendations - Serve the app from elsewhere
- Make your code path end up in
getDestinationUrl
by using the MsalGuard - Trigger the guard - have it redirect you to Azure and back
- You end up on the CDN 💥
Expected Behavior
I expect to - when authenticating - jump back to where I started (the place the app is hosted from), not a completely different url (the referenced base href for the CDN).
Identity Provider
Entra ID (formerly Azure AD) / MSA
Browsers Affected (Select all that apply)
Chrome, Firefox, Edge, Safari
Regression
No response