0

I've got an ID4 authentication server working well with an Angular app that is implementing angular-oauth2-oidc with SilentRefresh and a PCKE Authorisation flow.

Everything is working great - the ID4 is configured to serve AccessTokens with a 5 minute lifetime and the Angular app will silently refresh the token every minute (will likely change to refresh with 0.75 time elapsed). The problem I am finding however, is that I can close the browser having logged in - then open it again on the site 10 minutes later (after the original AccessToken has expired without being refreshed) - however the Silent Refresh kicks in a refreshes the token and the user remains logged in. This is a significant security hole.

My client side configuration looks like this:

{
    issuer: config.authServerUrl,
    clientId: '<redacted>', // The "Auth Code + PKCE" client
    responseType: 'code',
    redirectUri: window.location.origin,
    silentRefreshRedirectUri: window.location.origin + '/silent-refresh.html',
    postLogoutRedirectUri: window.location.origin,
    scope: 'openid profile email api',
    useSilentRefresh: true, // Needed for Code Flow to suggest using iframe-based refreshes
    silentRefreshTimeout: 60000, // For faster testing
    sessionChecksEnabled: true,
    showDebugInformation: !config.production, // Also requires enabling "Verbose" level in devtools
    clearHashAfterLogin: false,
    nonceStateSeparator : 'semicolon', // Real semicolon gets mangled by IdentityServer's URI encoding
  }

and My ID4 configuration looks like this:

      {
        "Enabled": true,
        "ClientId": "<redacted>",
        "ClientName": "<redacted>",
        "ClientSecrets": [ { "Value": "<redacted>" } ],
        "AccessTokenLifetime": "300",
        "AllowedGrantTypes": [ "authorization_code" ],
        "AllowedScopes": [ "openid", "profile", "email", "api" ],
        "AllowedCorsOrigins": [
          "http://localhost:4200"
        ],
        "PostLogoutRedirectUris": [
          "http://localhost:4200"
        ],
        "RedirectUris": [
          "http://localhost:4200",
          "http://localhost:4200/silent-refresh.html"
        ]
      }

I would like the behaviour to be that the silent refresh will only work if I open the browser again on the site, within the AccessToken's expiry time - i.e if I open after the AccessToken has expired - then I can't refresh and need to log in.

It seems that the Silent Refresh doesn't use RefreshTokens as the scopes presented on login don't include offline_access and I don't have AllowOfflineAccess set to true on the ID4 side. Are refresh tokens being used here - is the configuration implied in some way - if so, why can you allow a RefreshTokens lifetime to be longer than the AccessTokens?

1 Answers1

1

One thought is that your IdentityServer sets its own "session" cookie during your initial login and that one is used allow the application to silently reauthenticate and get a new access token. You can tweak the lifetime of this cookie from IdentityServer.

I would verify this behaviour using a proxy like Fiddler.

Tore Nestenius
  • 16,431
  • 5
  • 30
  • 40
  • If the intention is have their session end if they close the browser then using a non-persistent authentication cookie in your `identityserver4` IDP will do the trick. You should also ensure your client application signout mechanism also triggers a signout of the IDP via the end session endpoint. – mackie Feb 03 '21 at 13:16
  • I would like the "Remember Me" functionality to remember the user in the login screen - but not be used for the silent refresh - which I think, what you are saying the ID4 "remember me" session cookie is used for both.... I think then, I need to get the client app to use refresh tokens, not just allow the re-auth via the session token - divorcing the silent refresh from the "session cookie method" of refreshing. I guess that's by requesting `offline_access` scope in the client app - and enabliding `AllowOfflineAccess` on ID4. Am I on the right lines? – Alex Stevens Feb 04 '21 at 13:12
  • offline_access till give you the refresh token, then the question is if you should do the openid connect in the backend or frontend? see https://leastprivilege.com/2019/01/18/an-alternative-way-to-secure-spas-with-asp-net-core-openid-connect-oauth-2-0-and-proxykit/ – Tore Nestenius Feb 04 '21 at 13:51