We're using resource-owner credentials grant type (with oauth2:password
in security-config.xml
. Let's play out this scenario to explain my predicament:
- Bob was created with authorities
ROLE_USER
- Bob tries to access an oauth2 protected resource
- Bob uses the official mobile app to access it, so the client credentials are correct
- Bob's access token is created and stored in the
TokenStore
, keyed on hisusername
,client_id
, andscope
. (see DefaultAuthenticationKeyGenerator.java) - Bob's phone tries to call the protected services with this access token, but those services require users to have an
authority
ofROLE_MOBILE_USER
. - Bob contacts the db owner and has
ROLE_MOBLE_USER
added to his user in the database. - Bob tries to get another access token, but the
DefaultTokenServices
returns him the same, non-working access token. - The only way to take advantage of his new
authority
is to wait until his old access token expires so he can get a new access token with the correctauthority
.
There are a number of ways to address this.
For one, the administration app that adds ROLE_MOBILE_USER
to Bob's authorities could then clear all access tokens and authorizations in the database. This way the DefaultTokenServices
will just create a new one with the correct authorities serialized as his new OAuth2Authentication. However we may not want the Administration webapp to be concerned with OAuth at this point (at least not yet). If possible we'd like to keep the administration app concerns as concise as possible, and right now there are no dependencies on oauth.
We could expose the DELETE
method to the /oauth/access_token
endpoint and tell the mobile app to try deleting that access token and re-requesting one, just in case the stored authorities
are stale. This feels more like a work-around though.
Finally I can serialize the authorities
in my own defined AuthenticationKeyGenerator
. It would basically use the username
, client_id
, scope
, and authorities
of the authorization and perform the same digest algorithm on them. This way when Bob tries to log in he'll get the same access token, but the underlying token store will recognize that he has a different authentication (from the authentication manager in the token granter bean) and refresh its database. The problem I have with this solution is that it simply relies on the implementation behavior of the underlying token store (though both InMemoryTokenStore
and JdbcTokenStore
behave this way).
Can you think of any better/cleaner solutions? Am I over-thinking this?
Thanks in advance.