Soumyaansh
Soumyaansh

Reputation: 8988

Implemented Spring OAuth2, getting same access token from different devices

Implemented Spring OAuth2 security and getting same access token when logging with the same user but from different device. When i logout from any one of these devices(revoke Token)other devices are also getting logged out. Is it a expected behavior or i am missing something ? hoping that sharing the massive code will not help much so kept the question short and simple.

Upvotes: 4

Views: 5305

Answers (3)

user2946262
user2946262

Reputation: 95

(Please read org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator code to put the following solution into context)

DefaultAuthenticationKeyGenerator is available in spring. I just created a custom version with the same code with one extension, i.e., device_id sent from the client as a request parameter is retrieved from OAuth2Authentication as follows;

String deviceId = authentication.getOAuth2Request().getRequestParameters().get("device_id")

and then is put into the values map (used to generate the token finally). Hence the device_id becomes a part of the token resulting in a unique token per device.

Following is the full solution which is mostly the DefaultAuthenticationKeyGenerator apart from the bit explained above.

public class CustomAuthenticationKeyGenerator implements AuthenticationKeyGenerator
{
    private static final String CLIENT_ID = "client_id";

    private static final String SCOPE = "scope";

    private static final String USERNAME = "username";

    @Override
    public String extractKey(OAuth2Authentication authentication) {
        Map<String, String> values = new LinkedHashMap<String, String>();
        OAuth2Request authorizationRequest = authentication.getOAuth2Request();
        if (!authentication.isClientOnly()) {
            values.put(USERNAME, authentication.getName());
        }
        values.put(CLIENT_ID, authorizationRequest.getClientId());
        if (authorizationRequest.getScope() != null) {
            values.put(SCOPE, OAuth2Utils.formatParameterList(authorizationRequest.getScope()));
        }

        String deviceId = authorizationRequest.getRequestParameters().get(CustomHeader.device_id.name());
        if(deviceId != null && !deviceId.isEmpty()) {
            values.put("device_id", deviceId);
        }

        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("MD5");
        }
        catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("MD5 algorithm not available.  Fatal (should be in the JDK).");
        }

        try {
            byte[] bytes = digest.digest(values.toString().getBytes("UTF-8"));
            return String.format("%032x", new BigInteger(1, bytes));
        }
        catch (UnsupportedEncodingException e) {
            throw new IllegalStateException("UTF-8 encoding not available.  Fatal (should be in the JDK).");
        }
    }
}

Upvotes: 6

Soumyaansh
Soumyaansh

Reputation: 8988

For those who are facing the same issue can work on the replied solution by MangEngkus, for precise solution you can also refer this link Spring OAuth2 Generate Access Token per request to the Token Endpoint

Upvotes: 1

KSTN
KSTN

Reputation: 2022

The default behaviour of the DefaultTokenServices is to re-use existing tokens (based on the behaviour of the existing TokenStore implementations)

http://forum.spring.io/forum/spring-projects/security/oauth/121797-multiple-valid-oauth-access-tokens-for-same-client

If you want every device to be given different access_token then create your own AuthenticationKeyGenerator e.g. send your device id on authorization process and let your AuthenticationKeyGenerator process that device id to create access_token specific for that device.

Upvotes: 6

Related Questions