i_raqz
i_raqz

Reputation: 2959

Spring Boot OAuth - Multiple Access Tokens for same user

Spring-OAuth inserts multiple records in the access_token table when the same user logs in from different devices. What should be done to prevent Spring creating multiple access tokens. A user should be able to login from several devices at the same time.

Using 2.0.3.RELEASE

Upvotes: 4

Views: 9606

Answers (3)

Syakur Rahman
Syakur Rahman

Reputation: 2102

Just for a workaround, and to handle multiple instances of the service. Just get the token first, and if it is found return it, else then create it.

public class OAuthTokenServices extends DefaultTokenServices {
    @Override
    public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {
        OAuth2AccessToken token = super.getAccessToken(authentication);
        try {
            if (Objects.isNull(token) || token.isExpired()) {
                return super.createAccessToken(authentication);
            }
        } catch (DuplicateKeyException dke) {
            log.info("Duplicate key found. Lets get it instead.");
            token = super.getAccessToken(authentication);
            log.info("We got the token. {}", token);
            return token;
        } catch (Exception ex) {
            log.info(String.format("Exception while creating access token %s", ex));
        }
        return token;
    }
}

Then register it:

public class OAuthAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    DefaultTokenServices tokenServices;

    @Autowired
    private TokenStore tokenStore;

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        OAuthTokenServices tokenService = new OAuthTokenServices();
        tokenService.setTokenStore(tokenStore);
        tokenService.setSupportRefreshToken(true);
        return tokenService;
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.tokenServices(tokenServices);
    }

}

Upvotes: 2

jesse crossley
jesse crossley

Reputation: 56

I used one of the solutions suggested here and added @Transactional to my AuthorizationServerConfiguration's tokenStore() method.

Adding the @Transactional annotation allowed the same user to login from multiple clients, however, logging out from one client often results in the invalidation of the oauth_access_token (but not always!) and thus other clients were invalidated as well. I'm still looking into that bit...

For what it's worth, I also revved my versions (hopefully that's an option for you) of spring-security-oauth2 to 2.0.9.RELEASE and spring-security-web to 3.2.9.RELEASE.

Upvotes: 0

James
James

Reputation: 12182

The TokenStores use an AuthenticationKeyGenerator to create a key which is used to look up access tokens in the store/DB. The DefaultAuthenticationKeyGenerator that is used by default creates a key using the username, clientId and the scope. If these are the same it returns the same key, which results in the same access token to be returned. Create your own AuthenticationKeyGenerator and inject it into your TokenStore instance.

The question is why you want to do that. It really doesn't hurt that a user has multiple tokens. If you want to log out the user on all devices, ping the backend with the username so that it kills all tokens for this user.

Upvotes: 1

Related Questions