spring-projects / spring-authorization-server

Spring Authorization Server
https://spring.io/projects/spring-authorization-server
Apache License 2.0
4.87k stars 1.29k forks source link

Opaque authentication with jdbc tokenstore is generating and storying multiple tokens on same clientId #1719

Closed anishcjose closed 1 month ago

anishcjose commented 1 month ago

Describe the bug

This is specific to opaque token generation and use key store.

To Reproduce

Create RegisteredClient with accessTokenFormat(OAuthorizationFormat.REFERENCE)

Add Configuration with JdbcRegisteredClientRepository( new JdbcTemplate(datasource))

Generate new token via oauth2/token using the client credentials ( multiple times)

verify JdbOAuth2Authorization -> save method (line number 224)

the existing logic for checking existingAuthorization findById will always return null

verify OAuth2AccessTokenGenerator (line no: 83, id generation) (always generate a new random uuid)

since incoming key generation request not checking existing key using findByClientId, new token will be generated always and this will increase the number of keys in database and cause flooding.

Expected behavior

save method should return recently generated non expired token.

JdbOAuth2Authorization save method should change to search based on clientId to find existing authorization because the id is always new random generated uuid.

Sample

https://github.com/spring-projects/spring-authorization-server/blob/main/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationService.java

@Override
public void save(OAuth2Authorization authorization) {
    Assert.notNull(authorization, "authorization cannot be null");
    OAuth2Authorization existingAuthorization = findById(authorization.getId());    /**  findByClientId(authorization.getRegisteredclientId))   **/
    if (existingAuthorization == null) {
        insertAuthorization(authorization);
    }
    else {
        updateAuthorization(authorization);
    }
}
jgrandja commented 1 month ago

@anishcjose

save method should return recently generated non expired token.

This is not correct. The current behaviour works as expected as per spec.

Please review the spec. Each time an authorization grant is performed a new access token is generated. It's up to the client to keep and use that access token until it expires and then obtain a new access token after expiry by performing another authorization grant flow.