Hashchange seemingly not getting handled in auth code flow, and thus no access token is requested (Safari)
See original GitHub issueCore Library
MSAL.js v2 (@azure/msal-browser)
Core Library Version
2.21.0
Wrapper Library
MSAL React (@azure/msal-react)
Wrapper Library Version
1.2.0
Description
Somehow the seamless SSO in Safari does not perform an actual redirect for the auth code flow when using InteractionType.Redirect, but seemingly just adds the hash code directly to the URL.
(I’m not familiar with how seamless SSO works or any specifics of our seamless SSO configuration, so i cannot provide further details related to that.)
msal-browser/msal-react does not react to this hash change, and thus the user is left hanging with #code=XXX in the URL without requesting an access token.
The hacky fix below either reloads the page or creates a new instance when a hashchange containing “#code” is detected. That this works confirms that it is a problem of msal-browser/msal-react not reacting to an auth code provided this way.
Error Message
None
Msal Logs
No response
MSAL Configuration
const msalConfig: Configuration = {
auth: {
clientId: config.clientId,
authority: "https://login.microsoftonline.com/" + config.tenantId,
redirectUri: window.location.origin,
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: false,
},
};
Relevant Code Snippets
// Including this serves as a temporary fix:
window.addEventListener('hashchange', () => {
if (window.location.hash.startsWith('#code')) window.location.reload();
});
// The library is used in the following way:
<MsalProvider instance={publicClientApplication}>
<MsalAuthenticationTemplate
interactionType={InteractionType.Redirect}
authenticationRequest={authRequest}
loadingComponent={LoginLoading}
errorComponent={LoginError}
>
<BrowserRouter>
<App />
</BrowserRouter>
</MsalAuthenticationTemplate>
</MsalProvider>
// It's also possible to fix it without reloading by creating
// a new PublicClientApplication instance like so:
const HackyFix = () => {
const getNewInstance = () =>
// Our own custom function
getMsalPublicClientApplication({
clientId: environment.CLIENT_ID,
tenantId: environment.TENANT_ID,
});
const [instance, setInstance] = useState(getNewInstance);
useEffect(() => {
window.addEventListener('hashchange', () => {
if (window.location.hash.startsWith('#code')) setInstance(getNewInstance);
});
}, []);
return (
<MsalProvider instance={instance}>
<MsalAuthenticationTemplate
interactionType={InteractionType.Redirect}
authenticationRequest={authRequest}
loadingComponent={LoginLoading}
errorComponent={LoginError}
>
<BrowserRouter>
<App />
</BrowserRouter>
</MsalAuthenticationTemplate>
</MsalProvider>
);
};
Reproduction Steps
- I assume using seamless SSO is needed to reproduce the bug
- Clear localStorage or use a private window
- Access site in Safari
- Be left hanging with #code=XXX in the URL 😦
Expected Behavior
The library should request an access token when provided an auth code in the URL
Identity Provider
Azure AD / MSA
Browsers Affected (Select all that apply)
Safari
Regression
No response
Source
External (Customer)
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:9 (4 by maintainers)
Top GitHub Comments
@mikkelmk @MagnusHJensen Thank you for the information, I’ll look to see if we can properly handle this in the library, thanks!
I solved this by adding a trailing slash to redirectUri. It turns out Safari was stripping the hash because it was not preceeded by a slash.
This works everywhere but safari and for certain users IOS Chrome: https://app.foo.com/auth/return#code=0.AVcAeMaRO0JAkE… This works everywhere I have tested: https://app.foo.com/auth/return/#code=0.AVcAeMaRO0JAkE…