Eu me deparei com o mesmo problema ao desenvolver meu back-end com Spring Boot e OAuth2. O problema que encontrei foi que, se vários dispositivos compartilhavam os mesmos tokens, uma vez que um dispositivo atualizasse o token, o outro dispositivo ficaria sem noção e, resumindo, os dois dispositivos entrariam em um frenesi de atualização de token. Minha solução foi substituir o padrão AuthenticationKeyGenerator
por uma implementação personalizada que substitui DefaultAuthenticationKeyGenerator
e adiciona um novo parâmetro client_instance_id
na mistura do gerador de chaves. Meus clientes móveis enviaram esse parâmetro, que deve ser único nas instalações de aplicativos (iOS ou Android). Este não é um requisito especial, pois a maioria dos aplicativos móveis já rastreia a instância do aplicativo de alguma forma.
public class EnhancedAuthenticationKeyGenerator extends DefaultAuthenticationKeyGenerator {
public static final String PARAM_CLIENT_INSTANCE_ID = "client_instance_id";
private static final String KEY_SUPER_KEY = "super_key";
private static final String KEY_CLIENT_INSTANCE_ID = PARAM_CLIENT_INSTANCE_ID;
@Override
public String extractKey(final OAuth2Authentication authentication) {
final String superKey = super.extractKey(authentication);
final OAuth2Request authorizationRequest = authentication.getOAuth2Request();
final Map<String, String> requestParameters = authorizationRequest.getRequestParameters();
final String clientInstanceId = requestParameters != null ? requestParameters.get(PARAM_CLIENT_INSTANCE_ID) : null;
if (clientInstanceId == null || clientInstanceId.length() == 0) {
return superKey;
}
final Map<String, String> values = new LinkedHashMap<>(2);
values.put(KEY_SUPER_KEY, superKey);
values.put(KEY_CLIENT_INSTANCE_ID, clientInstanceId);
return generateKey(values);
}
}
que você injetaria de maneira semelhante:
final JdbcTokenStore tokenStore = new JdbcTokenStore(mDataSource);
tokenStore.setAuthenticationKeyGenerator(new EnhancedAuthenticationKeyGenerator());
A solicitação HTTP ficaria assim:
POST /oauth/token HTTP/1.1
Host: {{host}}
Authorization: Basic {{auth_client_basic}}
Content-Type: application/x-www-form-urlencoded
grant_type=password&username={{username}}&password={{password}}&client_instance_id={{instance_id}}
O benefício de usar essa abordagem é que, se o cliente não enviar uma client_instance_id
, a chave padrão será gerada e, se uma instância for fornecida, a mesma chave será retornada sempre para a mesma instância. Além disso, a chave é independente da plataforma. A desvantagem seria que o resumo MD5 (usado internamente) é chamado duas vezes.