Describe the bug
When I configure the library with Auth code + refresh token, and the authorization server doesn't return an id_token on refresh, the refresh mechanism breaks.
To Reproduce
Config:
responseType: 'code',
silentRenew: true,
useRefreshToken: true
First call
POST:
{
grant_type: authorization_code
client_id: myclientid
code_verifier: 123456
code: abcdef
redirect_uri: http://localhost:4200/
}
RESPONSE:
{
access_token: "blabla"
expires_in: 599
id_token: "blabla"
refresh_token: "blabla"
scope: "blabla"
token_type: "Bearer"
}
md5-c465d2a68e467bfb72d7885e6e1d2323
POST:
{
grant_type: refresh_token
client_id: myclientid
refresh_token: blabla
}
md5-051ca490a5175132a9786da40b0dbb0c
RESPONSE:
{
access_token: "blabla"
expires_in: 599
refresh_token: "blabla"
scope: "blabla"
token_type: "Bearer"
}
md5-a5b3c8cf6e2721d682084f807816759a
Checking: silentRenewRunning: false id_token: false userData: true
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: false userData: true
silent renew, periodic check finished!
Expected behavior
According to spec, I think it should be acceptable for an id_token not to be in the response of the refresh.
https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokenResponse
Upon successful validation of the Refresh Token, the response body is the Token Response of Section 3.1.3.3 except that it might not contain an id_token.
Additional context
Apologies if it's an issue in my config :)
Hi @sive87
This could be a problem with the implementation, not sure if I have implemented this to require an _id_token on every refresh.
Will check, can you post your configuration as well?
Out of interest, what IDP do you use?
Greetings Damien
@damienbod
It's an in-house home made IDP (which is why I double-checked the spec :) to be sure)
Looks like it should work, going through the code, what fails? any logs in the browser console?
I might need to disable the id_token expired time check, I know people want this.
Greetings Damien
Has id_token expired: false, 1614800942000 > 1614758340000
Has access_token expired: false, 1614758343000 > 1614758340000
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: true userData: true
Has id_token expired: false, 1614800942000 > 1614758344000
Has access_token expired: true, 1614758343000 > 1614758344000
starting silent renew...
Wanted to read 'xxx_storageCustomRequestParams' but nothing was found
BEGIN refresh session Authorize
RefreshSession created. adding myautostate: 0a6272b42abba7b587bffe2f55816af725iRVdKDS
found refresh code, obtaining new credentials with refresh code
logger.service.ts:55 token refresh response:
{access_token: "xxx", token_type: "Bearer", expires_in: 599, refresh_token: "xxx", scope: "scope1 scope2"}
history clean up inactive
{access_token: "xxx", token_type: "Bearer", expires_in: 599, refresh_token: "xxx", scope: "scope1 scope2", 鈥
authorizedCallback created, begin token validation
logger.service.ts:55 Getting signinkeys from https://blabla/oauth2/api/jwks
zone.js:3324 XHR finished loading: POST "https://blabla/oauth2/api/token".
No id_token found, skipping id_token validation
token '' is not valid --> token falsy
Code Flow active, and no at_hash in the id_token, skipping check!
AuthorizedCallback token(s) validated, continue
storing the accessToken
SafeSubscriber._next: NewAuthorizationResult
{type: 4, value: {鈥}
silent renew, periodic check finished!
XHR finished loading: GET "https://blabla/oauth2/api/jwks".
Checking: silentRenewRunning: false id_token: false userData: true
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: false userData: true
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: false userData: true
silent renew, periodic check finished!
token '' is not valid --> token falsy
Is the only error.
Whilst testing: If I add the id_token to the storage.authnResult, then the mechanism works again and properly performs checks on expiration
will fix this, see the bug, thanks for your patience.
Hello,
I restart the issue.
I am using version 11.6.4 but I have the exact same problem.
When I do the first "Refresh" my IDP doesn't return the id_token and after that the library doesn't do the checking anymore.
Is it a configuration problem?
Here are my console logs.
STS server: http://xxxxx
currentUrl to check auth with: http://localhost:4200/?code=xxx&state=xxxxx
Wanted to read 'xxxxx:client_storageSilentRenewRunning' but nothing was found
running validation for callback http://localhost:4200/?code=xxx&state=xxxxx
Wanted to read 'xxxxx:client_storageSilentRenewRunning' but nothing was found
Angular is running in development mode. Call enableProdMode() to enable production mode.
{id_token: "xxxx", access_token: "xxxxxx", refresh_token: "xxxxxx", scope: "openid profile", at_hash: "xxxx",聽鈥
authorizedCallback created, begin token validation
Getting signinkeys from xxxxxxx/api/jwks
[WDS] Live Reloading enabled.
validate id token iat max offset 1000 < 10000
Has id_token expired: false, 1616558901000 > 1616515702000
at_hash from the server:xxxxx
at_hash client validation not decoded:xxxx
AuthorizedCallback token(s) validated, continue
xxxx
storing the accessToken
Wanted to read 'xxxxx:client_userData' but nothing was found
Received user data {sub: "xxxx", family_name: "xxxx", given_name: "xxxx", ...}
accessToken xxxxx
Has id_token expired: false, 1616558901000 > 1616515713000
Has access_token expired: false, 1616515731000 > 1616515713000
persisted id_token and access token are valid
starting token validation check every 4s
checkAuth completed fired events, auth: true
app authenticated true
Current access token is 'xxxx'
Wanted to read 'xxxxxx:client_storageSilentRenewRunning' but nothing was found
Checking: silentRenewRunning: false id_token: true userData: true
Has id_token expired: false, 1616558901000 > 1616515717000
Has access_token expired: false, 1616515731000 > 1616515717000
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: true userData: true
Has id_token expired: false, 1616558901000 > 1616515721000
Has access_token expired: false, 1616515731000 > 1616515721000
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: true userData: true
Has id_token expired: false, 1616558901000 > 1616515725000
Has access_token expired: false, 1616515731000 > 1616515725000
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: true userData: true
Has id_token expired: false, 1616558901000 > 1616515729000
Has access_token expired: false, 1616515731000 > 1616515729000
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: true userData: true
Has id_token expired: false, 1616558901000 > 1616515733000
Has access_token expired: true, 1616515731000 > 1616515733000
starting silent renew...
Wanted to read 'xxxxx:client_storageCustomRequestParams' but nothing was found
BEGIN refresh session Authorize
RefreshSession created. adding myautostate: 5634409ee26c52311001d25e13a625d9fcF2LgPnN
found refresh code, obtaining new credentials with refresh code
token refresh response: {access_token: "xxxx", scope: "openid profile", refresh_token: "xxxx", expires_in: 29, token_type: "Bearer"}
history clean up inactive
{access_token: "xxx", scope: "openid profile", refresh_token: "xxx", expires_in: 29, token_type: "Bearer",聽鈥
authorizedCallback created, begin token validation
Getting signinkeys from https://xxxxxxx/oauth2/api/jwks
No id_token found, skipping id_token validation
AuthorizedCallback token(s) validated, continue
xxxxx
storing the accessToken
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: false userData: true
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: false userData: true
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: false userData: true
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: false userData: true
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: false userData: true
Hi @FiReBlUe45 tested this and it works. Could you post a example of what you do? and more info, STS etc. Maybe a stackblick would be good.
Greetings Damien
Hi @damienbod,
It is a private IDP server and accessible only from a VPN.
Here is my project on stackblitz: https://stackblitz.com/edit/angular-ivy-tqdsrf
I can provide a video from my browser with the console to show you.
Greetings,
Hi @damienbod
I meant to reply earlier but it doesn't work yet for us either
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: true userData: true
Has id_token expired: false, 1617068391000 > 1617025794000
Has access_token expired: true, 1617025791000 > 1617025794000
starting silent renew...
BEGIN refresh session Authorize
RefreshSession created. adding myautostate: ...
found refresh code, obtaining new credentials with refresh code
token refresh response: {access_token: "blabla", token_type: "Bearer", expires_in: 599, refresh_token: "blabla2", scope: "scope1 scope2 profile"}
history clean up inactive
{access_token: "blabla", token_type: "Bearer", expires_in: 599, refresh_token: "blabla2", scope: "scope1 scope2 profile", 鈥
authorizedCallback created, begin token validation
Getting signinkeys from https://.../oauth2/api/jwks
No id_token found, skipping id_token validation
AuthorizedCallback token(s) validated, continue
storing the accessToken
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: false userData: true
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: false userData: true
silent renew, periodic check finished!
Checking: silentRenewRunning: false id_token: false userData: true
So it stops checking the timestamp after
storage:
_authnResult : {"access_token":"blabla","token_type":"Bearer","expires_in":599,"refresh_token":blabla","scope":"scope1 scope2 openid profile","state":"4f3bc84dfc20485ae8c25bdb5f138472f8vU0Bxl8"}
_session_state: null
_access_token_expires_at: 1617026504000
_codeVerifier: "f48efd7ffd0068db4c848a2133e3573ef4d014e76b847216508ee9ed49525roQkoD"
_authStateControl: null
_storageSilentRenewRunning : null
Hi @damienbod, do you have a solution?
@FiReBlUe45 , @sive87 not yet, I was planning on looking at this, fixing this next chance I get,, just changed jobs and I'm pretty busy at the moment. It's on my todo list.
I'll track, fix this in this issue:
https://github.com/damienbod/angular-auth-oidc-client/issues/1039
I believe this is the same, correct me if I'm wrong
Greetings Damien