Je suis tombé sur le même problème lors du développement de mon backend avec Spring Boot et OAuth2. Le problème que j'ai rencontré était que, si plusieurs appareils partageaient les mêmes jetons, une fois qu'un appareil actualisait le jeton, l'autre appareil était sans aucune idée et, pour faire court, les deux appareils entraient dans une frénésie de rafraîchissement de jeton. Ma solution était de remplacer la valeur AuthenticationKeyGenerator
par défaut par une implémentation personnalisée qui remplaceDefaultAuthenticationKeyGenerator
et ajoute un nouveau paramètre client_instance_id
dans le mélange de générateurs de clés. Mes clients mobiles enverraient alors ce paramètre qui doit être unique dans toutes les installations d'applications (iOS ou Android). Ce n'est pas une exigence particulière, car la plupart des applications mobiles suivent déjà l'instance d'application sous une forme ou une autre.
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 vous injecteriez ensuite de manière similaire:
final JdbcTokenStore tokenStore = new JdbcTokenStore(mDataSource);
tokenStore.setAuthenticationKeyGenerator(new EnhancedAuthenticationKeyGenerator());
La requête HTTP ressemblerait alors à quelque chose comme ceci
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}}
L'avantage de l'utilisation de cette approche est que, si le client n'envoie pas de client_instance_id
, la clé par défaut est générée et si une instance est fournie, la même clé est renvoyée à chaque fois pour la même instance. En outre, la clé est indépendante de la plate-forme. L'inconvénient serait que le condensé MD5 (utilisé en interne) est appelé deux fois.