Mi sono imbattuto nello stesso problema durante lo sviluppo del mio backend con Spring Boot e OAuth2. Il problema che ho riscontrato è che, se più dispositivi condividessero gli stessi token, una volta che un dispositivo avesse aggiornato il token, l'altro dispositivo sarebbe stato all'oscuro e, per farla breve, entrambi i dispositivi sarebbero entrati in una frenesia di aggiornamento del token. La mia soluzione è stata quella di sostituire il valore predefinito AuthenticationKeyGenerator
con un'implementazione personalizzata che sovrascrive DefaultAuthenticationKeyGenerator
e aggiunge un nuovo parametro client_instance_id
nella combinazione del generatore di chiavi. I miei client mobili invierebbero quindi questo parametro che deve essere univoco tra le installazioni di app (iOS o Android). Questo non è un requisito speciale, poiché la maggior parte delle app mobili tiene già traccia dell'istanza dell'applicazione in qualche modo.
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);
}
}
che poi inietteresti in modo simile:
final JdbcTokenStore tokenStore = new JdbcTokenStore(mDataSource);
tokenStore.setAuthenticationKeyGenerator(new EnhancedAuthenticationKeyGenerator());
La richiesta HTTP sarebbe quindi simile a questa
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}}
Il vantaggio di utilizzare questo approccio è che, se il client non invia un client_instance_id
, verrebbe generata la chiave predefinita e se viene fornita un'istanza, la stessa chiave viene restituita ogni volta per la stessa istanza. Inoltre, la chiave è indipendente dalla piattaforma. Il rovescio della medaglia sarebbe che il digest MD5 (usato internamente) viene chiamato due volte.