Fix 401: send ID token instead of Graph access token

Access tokens for User.Read scope have audience=graph.microsoft.com,
but the backend validates audience=CLIENT_ID. ID tokens always have
audience=CLIENT_ID so they validate correctly.

Also add upn claim fallback for email extraction from ID token.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vadym Samoilenko 2026-03-30 11:16:44 +01:00
parent 4b4e48be01
commit b7db37828b
2 changed files with 8 additions and 3 deletions

View file

@ -68,7 +68,11 @@ async def get_current_user(
return {
"oid": payload.get("oid"),
"name": payload.get("name"),
"email": payload.get("preferred_username") or payload.get("email"),
"email": (
payload.get("preferred_username")
or payload.get("upn")
or payload.get("email")
),
}
except JWTError as e:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=f"Invalid token: {e}")

View file

@ -13,10 +13,11 @@ api.interceptors.request.use(async (config) => {
try {
const result = await msalInstance.acquireTokenSilent({
...loginRequest,
scopes: ['openid', 'profile', 'email'],
account: accounts[0],
});
config.headers.Authorization = `Bearer ${result.accessToken}`;
// ID token has audience=CLIENT_ID so the backend can validate it
config.headers.Authorization = `Bearer ${result.idToken}`;
} catch {
// Token expired or failed — trigger interactive login
await msalInstance.loginRedirect(loginRequest);