Reputation: 8988
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
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
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
Reputation: 2022
The default behaviour of the DefaultTokenServices is to re-use existing tokens (based on the behaviour of the existing TokenStore implementations)
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