IdentityModel / oidc-client-js

OpenID Connect (OIDC) and OAuth2 protocol support for browser-based JavaScript applications
Apache License 2.0
2.43k stars 841 forks source link

Monitor session is not working properly in Chrome #1257

Closed tomii8 closed 3 years ago

tomii8 commented 3 years ago

I'm using oidc-client-js version 10.1.0 in Vue.js application with IdentityServer4 version 3.1.3. On IdentityServer is configured client with autorization_code flow part of configuration:

 {
          ...
          "AllowedGrantTypes": [ "authorization_code" ],
          "AllowAccessTokensViaBrowser": true,
          "AllowOfflineAccess": true,
          "AccessTokenLifetime": 1800,
          "SlidingRefreshTokenLifetime": 3600,
          "RefreshTokenUsage": "OneTimeOnly",
          "RefreshTokenExpiration": "Sliding",
          "UpdateAccessTokenClaimsOnRefresh": true,
          "RequireConsent": false,
          "RequireClientSecret": false,
          "RedirectUris": [ "/", "/auth/callback.html", "/auth/silent-renew.html" ],
          "PostLogoutRedirectUris": [ "/" ],
          "RequirePkce": true,
          "AllowedScopes": [
            "openid",
            "profile",
            "email",
            "introspection",
            "address",
            "phone"
          ]
        }

On Vue.js side UserManager client settings are:

const settings: any = {
                userStore: webStorageStateStore,
                authority: authority,
                client_id: "some_name",
                redirect_uri: `${this.oidcClient.buildUri()}/auth/callback.html`,
                response_type: 'code',
                scope: `openid profile email ${scopes.join(' ')}`,
                post_logout_redirect_uri: this.oidcClient.buildUri(),
                automaticSilentRenew: true,
                silent_redirect_uri: `${this.oidcClient.buildUri()}/auth/silent-renew.html`,
                accessTokenExpiringNotificationTime: 10,
                filterProtocolClaims: true,
                loadUserInfo: true,
                revokeAccessTokenOnSignout: true,
                monitorSession: true,
                redirectNavigator: new PostRedirectNavigator()
            } as UserManagerSettings; 

Monitor session is turned on and everything works fine on Firefox, but Chrome is continuously making requests to connect/token endpoint. Because oidc-client somehow detect changes on session and make a request to connect/token endpoint on IdentityServer, when response is received from IdentityServer oidc-client process this response successfully but immediately after response is processed oidc-client detect changes on session and make a repeats above steps.

Oidc client logs which are infinitely repeating:

CheckSessionIFrame.start
oidc-client.min.js:1 CheckSessionIFrame: changed message from check session op iframe
oidc-client.min.js:1 CheckSessionIFrame.stop
oidc-client.min.js:1 UserManager._signinStart: got navigator window handle
oidc-client.min.js:1 OidcClient.createSigninRequest
oidc-client.min.js:1 MetadataService.getMetadataProperty for: authorization_endpoint
oidc-client.min.js:1 MetadataService.getMetadata: Returning metadata from settings
oidc-client.min.js:1 MetadataService.getMetadataProperty: metadata recieved
oidc-client.min.js:1 OidcClient.createSigninRequest: Received authorization endpoint http://localhost:60470/connect/authorize
oidc-client.min.js:1 SigninState.toStorageString
oidc-client.min.js:1 WebStorageStateStore.set 0514d11fc0bc4265813afaafbab7aaa3
oidc-client.min.js:1 UserManager._signinStart: got signin request
oidc-client.min.js:1 IFrameWindow.navigate: Using timeout of: 10000
client:52 [WDS] Live Reloading enabled.
oidc-client.min.js:1 IFrameWindow.message
oidc-client.min.js:1 IFrameWindow.message
oidc-client.min.js:1 IFrameWindow: cleanup
oidc-client.min.js:1 IFrameWindow: Successful response from frame window
oidc-client.min.js:1 OidcClient.processSigninResponse
oidc-client.min.js:1 OidcClient.readSigninResponseState
oidc-client.min.js:1 WebStorageStateStore.remove 0514d11fc0bc4265813afaafbab7aaa3
oidc-client.min.js:1 SigninState.fromStorageString
oidc-client.min.js:1 OidcClient.processSigninResponse: Received state from storage; validating response
oidc-client.min.js:1 ResponseValidator.validateSigninResponse
oidc-client.min.js:1 ResponseValidator._processSigninParams: state validated
oidc-client.min.js:1 ResponseValidator.validateSigninResponse: state processed
oidc-client.min.js:1 ResponseValidator._validateTokens: Validating code
oidc-client.min.js:1 MetadataService.getMetadataProperty for: token_endpoint
oidc-client.min.js:1 MetadataService.getMetadata: Returning metadata from settings
oidc-client.min.js:1 MetadataService.getMetadataProperty: metadata recieved
oidc-client.min.js:1 TokenClient.exchangeCode: Received token endpoint
oidc-client.min.js:1 JsonService.postForm, url:  http://localhost:60470/connect/token
oidc-client.min.js:1 JsonService.postForm: HTTP response received, status 200
oidc-client.min.js:1 TokenClient.exchangeCode: response received
oidc-client.min.js:1 ResponseValidator._processCode: token response successful, processing id_token
oidc-client.min.js:1 MetadataService.getMetadataProperty for: issuer
oidc-client.min.js:1 MetadataService.getMetadata: Returning metadata from settings
oidc-client.min.js:1 MetadataService.getMetadataProperty: metadata recieved
oidc-client.min.js:1 ResponseValidator._validateIdTokenAttributes: Validaing JWT attributes; using clock skew (in seconds) of:  300
oidc-client.min.js:1 JoseUtil.parseJwt
oidc-client.min.js:1 ResponseValidator.validateSigninResponse: tokens validated
oidc-client.min.js:1 ResponseValidator._processClaims: response is OIDC, processing claims
oidc-client.min.js:1 ResponseValidator._filterProtocolClaims, incoming claims: {nbf: 1606814701, exp: 1606815001, iss: "http://127.0.0.1:60470", aud: "webdash", iat: 1606814701, …}
oidc-client.min.js:1 ResponseValidator._filterProtocolClaims: protocol claims filtered {s_hash: "Q7dSZeHBcSHMR2GhwEgqqQ", sid: "-3lYsfFCDTxiJDtINo81Bg", sub: "7ff8146f-5308-494d-b556-50b02d0d15be", auth_time: 1606814699, idp: "local", …}
oidc-client.min.js:1 ResponseValidator._processClaims: not loading user info
oidc-client.min.js:1 ResponseValidator.validateSigninResponse: claims processed
oidc-client.min.js:1 UserManager.querySessionStatus: got signin response
oidc-client.min.js:1 UserManager.querySessionStatus: querySessionStatus success for sub:  7ff8146f-5308-494d-b556-50b02d0d15be

oidc-client.min.js:1 CheckSessionIFrame.start
oidc-client.min.js:1 SessionMonitor._callback: Same sub still logged in at OP, restarting check session iframe; session_state: uQ8-aouo1rmkK3vjb5YsOU-YjScSOSKJ73QmFnkVL1s.TrffIZVEBkPKHgFkWSMKEg
oidc-client.min.js:1 CheckSessionIFrame: changed message from check session op iframe
oidc-client.min.js:1 CheckSessionIFrame.stop
oidc-client.min.js:1 UserManager._signinStart: got navigator window handle
oidc-client.min.js:1 OidcClient.createSigninRequest
oidc-client.min.js:1 MetadataService.getMetadataProperty for: authorization_endpoint
oidc-client.min.js:1 MetadataService.getMetadata: Returning metadata from settings
oidc-client.min.js:1 MetadataService.getMetadataProperty: metadata recieved
oidc-client.min.js:1 OidcClient.createSigninRequest: Received authorization endpoint http://localhost:60470/connect/authorize
oidc-client.min.js:1 SigninState.toStorageString
oidc-client.min.js:1 WebStorageStateStore.set d5334cc97cb64a5a9fda6da8ddabf20e
oidc-client.min.js:1 UserManager._signinStart: got signin request
oidc-client.min.js:1 IFrameWindow.navigate: Using timeout of: 10000
oidc-client.min.js:1 IFrameWindow.message
oidc-client.min.js:1 IFrameWindow: cleanup
oidc-client.min.js:1 IFrameWindow: Successful response from frame window
oidc-client.min.js:1 OidcClient.processSigninResponse
oidc-client.min.js:1 OidcClient.readSigninResponseState
oidc-client.min.js:1 WebStorageStateStore.remove d5334cc97cb64a5a9fda6da8ddabf20e
oidc-client.min.js:1 SigninState.fromStorageString
oidc-client.min.js:1 OidcClient.processSigninResponse: Received state from storage; validating response
oidc-client.min.js:1 ResponseValidator.validateSigninResponse
oidc-client.min.js:1 ResponseValidator._processSigninParams: state validated
oidc-client.min.js:1 ResponseValidator.validateSigninResponse: state processed
oidc-client.min.js:1 ResponseValidator._validateTokens: Validating code
oidc-client.min.js:1 MetadataService.getMetadataProperty for: token_endpoint
oidc-client.min.js:1 MetadataService.getMetadata: Returning metadata from settings
oidc-client.min.js:1 MetadataService.getMetadataProperty: metadata recieved
oidc-client.min.js:1 TokenClient.exchangeCode: Received token endpoint
oidc-client.min.js:1 JsonService.postForm, url:  http://localhost:60470/connect/token
oidc-client.min.js:1 JsonService.postForm: HTTP response received, status 200
oidc-client.min.js:1 TokenClient.exchangeCode: response received
oidc-client.min.js:1 ResponseValidator._processCode: token response successful, processing id_token
oidc-client.min.js:1 MetadataService.getMetadataProperty for: issuer
oidc-client.min.js:1 MetadataService.getMetadata: Returning metadata from settings
oidc-client.min.js:1 MetadataService.getMetadataProperty: metadata recieved
oidc-client.min.js:1 ResponseValidator._validateIdTokenAttributes: Validaing JWT attributes; using clock skew (in seconds) of:  300
oidc-client.min.js:1 JoseUtil.parseJwt
oidc-client.min.js:1 ResponseValidator.validateSigninResponse: tokens validated
oidc-client.min.js:1 ResponseValidator._processClaims: response is OIDC, processing claims
oidc-client.min.js:1 ResponseValidator._filterProtocolClaims, incoming claims: {nbf: 1606814701, exp: 1606815001, iss: "http://127.0.0.1:60470", aud: "webdash", iat: 1606814701, …}
oidc-client.min.js:1 ResponseValidator._filterProtocolClaims: protocol claims filtered {s_hash: "5v1XivFG0oHTE3xfFxK8eQ", sid: "-3lYsfFCDTxiJDtINo81Bg", sub: "7ff8146f-5308-494d-b556-50b02d0d15be", auth_time: 1606814699, idp: "local", …}
oidc-client.min.js:1 ResponseValidator._processClaims: not loading user info
oidc-client.min.js:1 ResponseValidator.validateSigninResponse: claims processed
oidc-client.min.js:1 UserManager.querySessionStatus: got signin response
brockallen commented 3 years ago

Check the iframe to see if the session cookie is not being sent to the token server.

tomii8 commented 3 years ago

First call to /connect/token endpoint before session monitor is started:

POST /connect/token HTTP/1.1
Host: localhost:60470
Connection: keep-alive
Content-Length: 274
sec-ch-ua: "Google Chrome";v="87", "\"Not;A\\Brand";v="99", "Chromium";v="87"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: */*
Origin: http://localhost:63790
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:63790/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,hr;q=0.8

with form data

client_id: webdash
code: LhPGWm2iSFwBZorXjaId3CHD-ENNJtGoHJfNQiBjfqo
redirect_uri: http://localhost:63790/auth/callback.html
code_verifier: 7cd37a25425f4c53a1953f832ec077b8dee27192b38240a3b4f158b6c8f15b0b2508caf58d274d3095f93b1d7dd805a0
grant_type: authorization_code

And then when session monitor is turned on initial checksession request:

GET /connect/checksession HTTP/1.1
Host: localhost:60470
Connection: keep-alive
sec-ch-ua: "Google Chrome";v="87", "\"Not;A\\Brand";v="99", "Chromium";v="87"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: navigate
Sec-Fetch-Dest: iframe
Referer: http://localhost:63790/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,hr;q=0.8
Cookie: .AspNetCore.Antiforgery.UdZcnMp4nig=CfDJ8B2zTN94EWhBj8zRhuMUo0qDclAs6byKYLF3hSAj93sjVfxO8YfLfIgznFTINGWxHtHMVhpeGhOUsfAZMPLZoOi51zUVgcAfsJSUIwqLmxDqBZ12A68X2CQFlbt8attcw_9ZTZC9AldxL6_jDmuDGSg; .AspNetCore.Cookies=CfDJ8B2zTN94EWhBj8zRhuMUo0qyBso99fCACkUUAOmMy2s8b4GEGb129P_hxIeGREVV5gXtERR4W3usLO385HKc15kh8ZeqP8ASyycBJbW6BPki0B00QrHIyE98dAYfNQG7qYzgi-ECaNh0ulvUrzwN4rX6m8L92_N7Th4DVnej4zNi5ylPC_03Yqxspj2zd6gDSdTNlLUwx7OpxU9HDT1M06mAnpeEBPvBBatb8KHcrN_RqhAZPxN1Hhzh5FAdUitYygRIDQjPJ9ExfDH5C5Mmq2hL1gzonpzWHnbtXzflPFWDIY1SLJHsW1O8F9-vg1mAGiWFDJuNbw0_PGD3TYvtzosMcOgofzJWFeCYUfA5uYcSEe9xB9RRSNJLCVqWpf6z6y9OgFCJTpGryccQx3zva7ky5MI7OEVMrc1neV9MdYYkJywyhDxBRVcXDZdgNxUq9yu5Ag0ji_2Hm-IZHlW3dYW1cyoEm8kYGOR9d-3TzPKgVpWPU5QJny9lRdpZbAZMHj72lBNIGtWpW9mD163fODgwLBJIr4rhRVzhT-w3RYdo

and after that inifinite loop of requests to token and authorize endpoints:

POST /connect/token HTTP/1.1
Host: localhost:60470
Connection: keep-alive
Content-Length: 278
sec-ch-ua: "Google Chrome";v="87", "\"Not;A\\Brand";v="99", "Chromium";v="87"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: */*
Origin: http://localhost:63790
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:63790/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,hr;q=0.8

with form data

client_id: webdash
code: T_jcIRJgfob-cTvzjLGGivN7AMBjVd6GdGflUrAyQkA
redirect_uri: http://localhost:63790/auth/silent-renew.html
code_verifier: e7cf39dc2f1d4bd487d1624363db5bdd07a638713b7742ebab4f88f500b662ac3e3c3ce46ad9431ca313c2724220e746
grant_type: authorization_code

and after that authorize

GET /connect/authorize?client_id=webdash&redirect_uri=http%3A%2F%2Flocalhost%3A63790%2Fauth%2Fsilent-renew.html&response_type=code&scope=openid&state=29c541ab934d43bdbcd85baaf58e5ed5&code_challenge=OXT3t2Rc4DiwzkAQ8TzVA1f1WGPOF9J5Gc8qNZu29GQ&code_challenge_method=S256&prompt=none&response_mode=query HTTP/1.1
Host: localhost:60470
Connection: keep-alive
sec-ch-ua: "Google Chrome";v="87", "\"Not;A\\Brand";v="99", "Chromium";v="87"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: navigate
Sec-Fetch-Dest: iframe
Referer: http://localhost:63790/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,hr;q=0.8
Cookie: .AspNetCore.Antiforgery.UdZcnMp4nig=CfDJ8B2zTN94EWhBj8zRhuMUo0qDclAs6byKYLF3hSAj93sjVfxO8YfLfIgznFTINGWxHtHMVhpeGhOUsfAZMPLZoOi51zUVgcAfsJSUIwqLmxDqBZ12A68X2CQFlbt8attcw_9ZTZC9AldxL6_jDmuDGSg; .AspNetCore.Cookies=CfDJ8B2zTN94EWhBj8zRhuMUo0qyBso99fCACkUUAOmMy2s8b4GEGb129P_hxIeGREVV5gXtERR4W3usLO385HKc15kh8ZeqP8ASyycBJbW6BPki0B00QrHIyE98dAYfNQG7qYzgi-ECaNh0ulvUrzwN4rX6m8L92_N7Th4DVnej4zNi5ylPC_03Yqxspj2zd6gDSdTNlLUwx7OpxU9HDT1M06mAnpeEBPvBBatb8KHcrN_RqhAZPxN1Hhzh5FAdUitYygRIDQjPJ9ExfDH5C5Mmq2hL1gzonpzWHnbtXzflPFWDIY1SLJHsW1O8F9-vg1mAGiWFDJuNbw0_PGD3TYvtzosMcOgofzJWFeCYUfA5uYcSEe9xB9RRSNJLCVqWpf6z6y9OgFCJTpGryccQx3zva7ky5MI7OEVMrc1neV9MdYYkJywyhDxBRVcXDZdgNxUq9yu5Ag0ji_2Hm-IZHlW3dYW1cyoEm8kYGOR9d-3TzPKgVpWPU5QJny9lRdpZbAZMHj72lBNIGtWpW9mD163fODgwLBJIr4rhRVzhT-w3RYdo

Each call to token endpoint differs in 'code' and 'code_verifier' form data. Each call to authorize endpoint differs in 'state' and 'code_challenge' query paramters. Cookie remains the same.

tomii8 commented 3 years ago

Does anyone have idea how to solve this?

brockallen commented 3 years ago

Every figure this out? Sounds like you have some automatic token renewal happening.