3
votes

I implemented the openID Connect Authorization Code Flow and PKCE with silent refresh on my IdentityServer 4 I have a core API refering to IdentityServer and an angular 8 front and oidc-client.js.

When I'm not login the oidc-client redirect me to the IdentityServer login page from there I can login and then the IdentityServer redirect me to the angular app. I have an access token with Bearer format which is transmitted to the API and an iframe frequently popping and contacting the IdentityServer on /connect/authorize. When I logout I get redirected on IdentityServer and then to my angular front which ask me to login.

Here you may ask what the hell is this guy problem. There you go :

When I copy/paste the Bearer token inside postman I can use it for eternity with an AccessTokenLifetime (db field) set to 65, after the user is logout, after having truncated the PersistedGrants table, after executing "_signInManager.SignOutAsync" "_persistedGrantService.RemoveAllGrantsAsync".

I will now give you some code :

Startup.cs API

services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
         .AddIdentityServerAuthentication(options =>
         {
             options.Authority = configApp.UrlIdentityServer;
             options.RequireHttpsMetadata = false;
             options.ApiName = "example.api";
         });

controller method example :

 [HttpGet("{id:int}")]
        [Authorize]
        public ActionResult<FormatedResult<Stuff>> GetStuff(int id)
        {/*great stuff*/}

Angular logout method

async logout() {
        this.manager.signoutRedirect()
            .catch((error) => {
            });
        this.manager.signoutRedirectCallback()
            .then(() => {
                this.manager.removeUser();
            })
            .then(() => {
                this.user = null;
            })
            .catch((error) => {
            });
    }

Angular oidc manager settings

    authority: 'http://example.authserver.loc/',
    client_id: 'example.ng.manager',
    redirect_uri: 'http://ng.example.loc:5001/callbacksignin/',
    post_logout_redirect_uri: 'http://ng.example.manager.loc:5001/',
    response_type: 'code',
    scope: 'openid profile example.api',
    filterProtocolClaims: true,
    loadUserInfo: true,
    userStore: new WebStorageStateStore({store: window.localStorage}),
    automaticSilentRenew: true,
    silent_redirect_uri: 'http://ng.example.manager.loc:5001/silent-refresh.html',
    revokeAccessTokenOnSignout: true

I though silent-refresh was used to avoid having a bearer token stolen and a bad boy doing bad thing on my API for an unlimited period of time. With my implementation the bad boys can play with my API for eternity.

My questions :

  • Is it suppose to happen ?
  • Does the access_token is granted for life ?
  • If not what did I do wrong ?
  • How can I deny the use of the access token after AccessTokenLifetime is passed ? or after the user logout.

NB : I disabled all caching.

1

1 Answers

0
votes

I though silent-refresh was used to avoid having a bearer token stolen and a bad boy doing bad thing on my API for an unlimited period of time. With my implementation the bad boys can play with my API for eternity.

My questions :

Is it suppose to happen ?

Silent refresh is not to avoid having a bearer token stolen. Your access_token will always have a chance of being exposed because of the nature of public clients like javascript based client. Silent refresh is there so if the user can refresh using something like PKCE, that this is done silently without interrupting the user.

Also deleting PersistedGrants does not have any affect on Code + PKCE client because they don't use refresh tokens (that's what PKCE is for).

Does the access_token is granted for life ?

Access token are valid based on their expiration which is determined by AccessTokenLifetime. They are, however, can be renewed as I mentioned if you are using PKCE with silent refresh.

If not what did I do wrong ? How can I deny the use of the access token after AccessTokenLifetime is passed ? or after the user logout.

To be clear, the access token is lifetime is determined when your token is issued so if you change the value of AccessTokenLifetime after that will be the duration for new token not existing tokens. The token will automatically be invalidated once the access_token jwt expires.