angular-auth-oidc-client
angular-auth-oidc-client copied to clipboard
[Bug]: Authorization header stops being set if `id_token` is missing in the refresh token response
What Version of the library are you using?
13.0.0
Describe the bug
When the refresh token process is executed, the authnResult
object is overwritten with the response. NetIQ does not return an id_token
from from the refresh process. After the refresh, the application receives errors saying isAuthenticated
is false. Additional HTTP calls error because the Authorization
header is not set.
The user is logged in, but the id_token
is required for a user to be identified as logged in. When id_token
is null or undefined, isAuthenticated
calls fail:
https://github.com/damienbod/angular-auth-oidc-client/blob/main/projects/angular-auth-oidc-client/src/lib/auth-state/auth-state.service.ts#L157
This causes the check in the AuthInterceptor to fail to fetch the access_token properly (isAuthenticated returns false): https://github.com/damienbod/angular-auth-oidc-client/blob/main/projects/angular-auth-oidc-client/src/lib/interceptor/auth.interceptor.ts#L46-L52
Let me know if you need any other information from us on this 👍
To Reproduce
Steps to reproduce the behavior:
- Using identify provider NetIQ (Or an identify provider that does not return an
id_token
on token refresh)
Expected behavior
User access_token
should be refreshed and future https calls identified in secureRoutes
should have the authorization header
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
- OS: Mac OS 12.3.1
- Browser Chrome
- Version 100.0.4896.127
Smartphone (please complete the following information):
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
Additional context
Configuration:
{
`logLevel`: LogLevel.Debug,
`authority`: authConfig.authority,
`redirectUrl`: authConfig.redirectUri,
`postLogoutRedirectUri`: window.location.origin,
`clientId`: authConfig.clientId,
'scope': 'openid profile usermanager roles',
'responseType': 'code',
'silentRenew': true,
'useRefreshToken': true,
'autoUserInfo': true,
'enableIdTokenExpiredValidationInRenew': false,
'allowUnsafeReuseRefreshToken': true,
'renewTimeBeforeTokenExpiresInSeconds': 3595, // our tokens expire in an hour, this is for testing
'customParamsRefreshTokenRequest': {
scope: 'openid profile usermanager roles',
},
'unauthorizedRoute': '/unauthorized',
'forbiddenRoute': '/forbidden',
'secureRoutes': ['/'],
};
authorization_code Request
grant_type: authorization_code
client_id: *redacted client_id*
code_verifier: 64b7f02d161445f1b7c447dbcfa8f252251bda6c7a2dc51faeee043679c3LYCbh8R
code: ...
redirect_uri: *redacted*
authorization_code Response
{
"access_token":"eyJ...",
"token_type":"bearer",
"expires_in":3599,
"refresh_token":"eyJ...",
"id_token":"eyJ...",
"scope":"profile roles"
}
refresh_token Request
grant_type: refresh_token
client_id: *redacted client_id*
refresh_token: eyJ...
scope: openid profile usermanager roles
refresh_token Response
{
"access_token":"eyJ...",
"token_type":"bearer",
"expires_in":3599,
"scope":"profile roles"
}
Debug output
core.mjs:24863 Angular is running in development mode. Call enableProdMode() to enable production mode.
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Working with config '0-*redacted client_id*' using https://*redacted*.com/nidp/oauth/nam
angular-auth-oidc-client.mjs:157 [DEBUG] 0-*redacted client_id* - currentUrl to check auth with: https://localhost:4200/authcallback?code=/...
angular-auth-oidc-client.mjs:157 [DEBUG] 0-*redacted client_id* - running validation for callback https://localhost:4200/authcallback?code=/...
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Did not find any configured route for route https://*redacted*.com/nidp/oauth/nam/token
index.js:551 [webpack-dev-server] Live Reloading enabled.
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - AuthResult '{
"access_token": "eyJ...",
"token_type": "bearer",
"expires_in": 3599,
"refresh_token": "eyJ...",
"id_token": "eyJ...",
"scope": "profile roles",
"state": "cb685b592a6575ee0c997d3f85c123b42bymgtAYr",
"session_state": ""
}'.
AuthCallback created, begin token validation
angular-auth-oidc-client.mjs:157 [DEBUG] 0-*redacted client_id* - Getting signinkeys from https://*redacted*.com/nidp/oauth/nam/keys
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Did not find any configured route for route https://*redacted*.com/nidp/oauth/nam/keys
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - validate id token iat max offset 0 < 120000
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Has idToken expired: false --> expires in 60:00 , 12:18:19 PM > 11:18:19 AM
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Code Flow active, and no at_hash in the id_token, skipping check!
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - authCallback token(s) validated, continue
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - storing the accessToken 'eyJ...'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact' matches configured route '/'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact' matches configured route '/', adding token
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/navigation/oneplatform' matches configured route '/'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/navigation/oneplatform' matches configured route '/', adding token
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Did not find any configured route for route https://*redacted*.com/nidp/oauth/nam/userinfo
angular-auth-oidc-client.mjs:157 [DEBUG] 0-*redacted client_id* - Received user data: {preferredTimeZone: 'Etc/GMT+12', sub: '3c0dd97642498c468e793c0dd9764249', mail: '*@gmail.com', preferredCurrency: 'AUD', Roles: Array(7), …}
angular-auth-oidc-client.mjs:157 [DEBUG] 0-*redacted client_id* - accessToken: eyJ...
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Working with config '0-*redacted client_id*' using https://*redacted*.com/nidp/oauth/nam
angular-auth-oidc-client.mjs:157 [DEBUG] 0-*redacted client_id* - currentUrl to check auth with: https://localhost:4200/authcallback
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Has accessToken expired: false --> expires in 0:04 , 12:18:18 PM > 12:18:14 PM
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - persisted idToken and accessToken are valid
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact' matches configured route '/'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact' matches configured route '/', adding token
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/navigation/oneplatform' matches configured route '/'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/navigation/oneplatform' matches configured route '/', adding token
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - checkAuth completed - firing events now. isAuthenticated: true
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Working with config '0-*redacted client_id*' using https://*redacted*.com/nidp/oauth/nam
angular-auth-oidc-client.mjs:157 [DEBUG] 0-*redacted client_id* - currentUrl to check auth with: https://localhost:4200/authcallback
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Has accessToken expired: false --> expires in 0:04 , 12:18:18 PM > 12:18:14 PM
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - persisted idToken and accessToken are valid
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact' matches configured route '/'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact' matches configured route '/', adding token
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/navigation/oneplatform' matches configured route '/'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/navigation/oneplatform' matches configured route '/', adding token
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - checkAuth completed - firing events now. isAuthenticated: true
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact/administrators' matches configured route '/'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact/administrators' matches configured route '/', adding token
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact/administrators' matches configured route '/'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact/administrators' matches configured route '/', adding token
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact/administrators' matches configured route '/'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact/administrators' matches configured route '/', adding token
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Checking: silentRenewRunning: false - has idToken: true - has userData: true
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Has accessToken expired: true --> expires in 0:00 , 12:18:18 PM > 12:18:18 PM
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - starting silent renew...
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - BEGIN refresh session Authorize
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - RefreshSession created. Adding myautostate: 28fdc730e4b425df55bd4ff5a60a3a4f23h7sxd6h
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - found refresh code, obtaining new credentials with refresh code
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Did not find any configured route for route https://*redacted*.com/nidp/oauth/nam/token
angular-auth-oidc-client.mjs:157 [DEBUG] 0-*redacted client_id* - token refresh response: {access_token: 'eyJ...', token_type: 'bearer', expires_in: 3599, scope: 'profile roles'}
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - history clean up inactive
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - AuthResult '{
"access_token": "eyJ...",
"token_type": "bearer",
"expires_in": 3599,
"scope": "profile roles",
"state": "28fdc730e4b425df55bd4ff5a60a3a4f23h7sxd6h"
}'.
AuthCallback created, begin token validation
angular-auth-oidc-client.mjs:157 [DEBUG] 0-*redacted client_id* - Getting signinkeys from https://*redacted*.com/nidp/oauth/nam/keys
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Did not find any configured route for route https://*redacted*.com/nidp/oauth/nam/keys
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - No id_token found, skipping id_token validation
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - authCallback token(s) validated, continue
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - storing the accessToken 'eyJ...'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/contact' matches configured route '/'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Wanted to add token to /api/contact but found no token: 'null'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - '/api/navigation/oneplatform' matches configured route '/'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Wanted to add token to /api/navigation/oneplatform but found no token: 'null'
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - silent renew, periodic check finished!
zone.js:2863 GET https://localhost:4200/api/contact 401 (Unauthorized)
core.mjs:6485 ERROR HttpErrorResponse {headers: HttpHeaders, status: 401, statusText: 'Unauthorized', url: 'https://localhost:4200/api/*redacted*', ok: false, …}
defaultErrorLogger @ core.mjs:6485
...
zone.js:2863 GET https://localhost:4200/api/navigation/*redacted* 401 (Unauthorized)
scheduleTask @ zone.js:2863
...
Show 1,054 more frames
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Checking: silentRenewRunning: false - has idToken: false - has userData: true
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - silent renew, periodic check finished!
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Checking: silentRenewRunning: false - has idToken: false - has userData: true
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - silent renew, periodic check finished!
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - Checking: silentRenewRunning: false - has idToken: false - has userData: true
angular-auth-oidc-client.mjs:160 [DEBUG] 0-*redacted client_id* - silent renew, periodic check finished!
Duplicate of #1408 ?
We fix, add support for this in version 14, PR:
https://github.com/damienbod/angular-auth-oidc-client/pull/1571
fixed in version 15.0.0
Once released you can configure it something like this:
import { NgModule } from '@angular/core';
import { AuthModule, LogLevel } from 'angular-auth-oidc-client';
@NgModule({
imports: [
AuthModule.forRoot({
config: {
authority: '--idp--',
redirectUrl: window.location.origin,
postLogoutRedirectUri: window.location.origin,
clientId: '--client_id--',
scope: 'openid profile offline_access',
responseType: 'code',
silentRenew: true,
useRefreshToken: true,
ignoreNonceAfterRefresh: true, // this is required if the id_token is not returned
// allowUnsafeReuseRefreshToken: true, // this is required if the refresh token is not rotated
triggerRefreshWhenIdTokenExpired: false, // required to refresh the browser if id_token is not updated after the first authentication
autoUserInfo: false, // if the user endpoint is not supported
logLevel: LogLevel.Debug,
},
}),
],
exports: [AuthModule],
})
export class AuthConfigModule {}
fixed in v15.0.0