Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache invalidation for OAuth routine #177

Closed
gbuda opened this issue Sep 27, 2016 · 9 comments
Closed

Cache invalidation for OAuth routine #177

gbuda opened this issue Sep 27, 2016 · 9 comments

Comments

@gbuda
Copy link

gbuda commented Sep 27, 2016

Hello.

I have configured module as OAuth resource server.
Resources behind the filter are protected based on OIDCAuthNHeader, whitch is set, when access token was verified on introspection endpoint. Tokens are cached on proxy side.
But when I logout from application, token will not be valid anymore.
If next request with this token was send before
cacheEntry(timestamp) + OIDCOAuthTokenIntrospectionInterval
, the token will be checked as valid and request will be set to backend server with header OIDCAuthNHeader.

Currently I use low OIDCOAuthTokenIntrospectionInterval = 60.
That does not completely eliminate our problem, also remove caching is not a solution.

Is it possible to add logout subroutine or even invalidateToken subroutine to OAuth scheme ?

Example solutions

  1. Simple solution - we want only to remove token from cache

a) Config entry OIDCOAuthTokenCacheRemoveParamName - name of header, for example remove_cached_token
b) setup var removeTokenFromCache based on config and request headers
c) remove header from request
d) changed oidc_oauth_resolve_access_token -> oidc_oauth_get_cached_access_token->
if ((dir_cfg->oauth_token_introspect_interval > 0 || removeTokenFromCache)
e) if remove_cached_token was set to true, token will be introspected again

If we remove token on application side and then execute any request with remove_cached_token we will got 401 error, but it not an issue, because all later requests will also return 401.

  1. Also simple solution - but without problems with 401 error code
    a), b),c) points the same as above
    d),e) not exists in this solution
    f) if remove_cached_token was set to true, simply remove token from cache at the end of oidc_oauth_resolve_access_token

In that solution out flow will be:
a) logout request with remove_cached_token = true
b) filter verifies token based on cache or introspection endpoint
c) token is valid
d) token will be removed from cache
d) request goes to backend
e) token was invalidated on backend
f) next request with the same token will be validated against introspection endpoint
g) 401 error will be returned

  1. More complex solution (not required - more like openid style) - handle logout url

a) Config entry OIDCOAuthTokenInvalidationUrl for exaple https://server/x
b) complete flow from solution 2
c) Check if request url matches OIDCOAuthTokenInvalidationUrl
d) If matches, we have to take url param from request (for example logout param from https://server/x?logout=http://backendserver/logout) and pass request to http://backendserver/logout
e) the limitation is that logout endpoint has to be behind proxy and only filter can call it without checking of token validity, otherwise request to token endpoint will be filtered and token will be introspected as valid and cached.

Thank you.

@zandbelt
Copy link
Member

Support for token introspection cache invalidation makes sense to me.

But I find it hard to parse your solution descriptions.

I would imagine that the client could indicate that it wants to force token introspection or there could be some sort of hook that can be called server side to invalidate the cache.

Are you looking for a client-side trigger or a server-side trigger (or both)? Perhaps you can rephrase your favorite option?

@gbuda
Copy link
Author

gbuda commented Sep 27, 2016

I am looking for server-side trigger based for example on request header.

We want to do all actions in single request:

  1. we want to pass access_token and additional header (for example invalidate_token=true) for logout request
  2. module should check token in cache or introspect token on backend if token is not in cache - normal authorization routine
  3. module should remove token info from cache
  4. module should remove header invalidate_token
  5. request should be passed to backend
  6. out backend will invalidate token
  7. next requests with this token require token introspection (because token does not exists in cache)
  8. introspection on backend return 401 or invalid token...
  9. module return 401 error

We don`t need to force introspection, rather cache invalidation.
This additional header will be set only in logout requests.

@zandbelt
Copy link
Member

I'm not sure what you mean by "logout requests". In OAuth RS mode, there's no such thing as logout.

If I understand your proposal correctly, I would like to suggest the following: the module wouldn't have to care about the header since that could be picked up by the backend. If the backend invalidates the token and could invalidate the cache by calling a hook on the module, would that work for you? I think that somewhat represents your initial 3rd solution but I want to avoid having to signal your backend from mod_auth_openidc since the Client could do that.

I'm trying to avoid having the Client pass in headers that are custom for mod_auth_openidc.

@gbuda
Copy link
Author

gbuda commented Sep 27, 2016

Logout is not in spec.
It is only example request in which we need somehow invalidate cache.
The second one will be refresh token.

Our backend does not know anything about proxy.
Can we call that hook somehow, based on client request, for example request for specific resource ? When that resource path matches config parameter, module can simply invalidate cache for token.

@zandbelt
Copy link
Member

The hook would be something like https://localhost/callback?invalidate_access_token=<access_token>, that could be called through the browser but also directly from any piece of code that has obtained the access token. Any backend that can make HTTP calls could do this.

Refresh tokens are different. The results are not cached; in fact the result is an access token. When the access token is revoked and its cache invalidated the refresh token will be used to obtain a new access token. When the refresh token is also revoked, that won't succeed.

@gbuda
Copy link
Author

gbuda commented Sep 27, 2016

OK.

Thank you.

zandbelt pushed a commit that referenced this issue Sep 28, 2016
@zandbelt
Copy link
Member

b7a15dc allows you to call the hook defined with OIDCRedirectURI with a remove_at_cache=<access_token> parameter, e.g. https://localhost/callback?remove_at_cache=<access_token> Let me know if that works out for you.

It is a bit of a misnomer that OIDCRedirectURI is overloaded (or even required for an OAuth 2.0 deployment) here, but the same has already happened for the key material to encrypt an access token and implementation-wise it avoids any duplication for another hook that does the same.

@gbuda
Copy link
Author

gbuda commented Sep 29, 2016

Hello.

It works great for me.
As you said I had to configure:

OIDCProviderAuthorizationEndpoint https://not_used
OIDCProviderIssuer not_used
OIDCCryptoPassphrase not_used
OIDCClientId not_used

But it is not an issue.

Thank you.

@zandbelt
Copy link
Member

yeah, that's awkward; you could set OIDCMetadataDir and OIDCCryptoPassphrase instead of the 4 primitives you mention

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants