Mehrere Oauth2-Zugriffstoken

13

Ich habe eine API, die oAuth2 verwendet, und meine eigenen mobilen Apps, die diese API als Backend verwenden. Da Benutzer gleichzeitig über mehrere Geräte (z. B. iPhone, iPad, Android-Tablet oder Android-Telefon) angemeldet sein können, benötige ich die API, um zwischen den einzelnen Verbindungen zu unterscheiden. Ich möchte dies über separate Zugriffstoken tun: Jeder Client erhält ein separates Zugriffstoken.

Das Problem ist, dass die aktuell verwendete Implementierung (spring-security-oauth2) einen eindeutigen Schlüssel basierend auf client_id, username und scope generiert. Wenn also ein Zugriffstoken abgerufen wird, erhalten alle Clients dasselbe Zugriffstoken für denselben Benutzer. Dies erfolgt mit DefaultAuthenticationKeyGenerator.

Ist es sicher, den Authentifizierungsschlüsselgenerator zu ignorieren und bei jeder Anforderung eines Clients einfach ein neues Zugriffstoken zu erstellen?

Checkliste
quelle
2
Können Sie den Umfang nutzen, um jeden Kunden zu differenzieren? dh gib ios einen "ios" -Bereich, android einen "android" -Bereich, das Tablet einen "tablet" -Bereich usw. Aber FWIW habe ich meine eigene TokenServices-Implementierung geschrieben (eigentlich denke ich, dass ich es zu einem Wrapper um den Standard gemacht habe) generiert jedes Mal ein brandneues Token.
Rob
Im Allgemeinen hat die Spring Security OAuth2-Implementierung für mich gut funktioniert (nachdem ich die XML-Konfiguration durchlaufen hatte), aber das Verwalten des Tokens und der Authentifizierungsobjekte war ein anhaltender Schmerzpunkt.
Rob
2
Das Durchsuchen von Google nach "DefaultAuthenticationKeyGenerator" führte mich zu einer .java-Datei in der Bibliothek spring-security-oauth auf GitHub. Diese Klasse implementiert die AuthenticationKeyGeneratorSchnittstelle. Könnten Sie eine eigene Implementierung erstellen und diese stattdessen verwenden?
Greg Burghardt
Die URL zu der .java-Datei, die ich gefunden habe: github.com/spring-projects/spring-security-oauth/blob/master/…
Greg Burghardt
2
Ich bin mit @Rob einverstanden, dass Sie mit Devicetype in Anfrage wie "Android", "iOS", "Web" usw. gehen können
Vikash Rajpurohit

Antworten:

1

Die Frühlingswolke liefert bereits dieses Verhalten. Fügen Sie einfach verschiedene Clients hinzu. Wie iosAppClient, androidAppClient in Ihrer AuthorizationServerConfiguration-Klasse.

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
                clients.inMemory().withClient("androidAppclient")
                    .secret("clientsecret")
                    .autoApprove(true)
                    .accessTokenValiditySeconds(120)
                    .authorizedGrantTypes("password")
                    .resourceIds("accountservice")
                    .scopes("read", "write")
                    .and()
                    .withClient("iosappclient")
                    ........

        }

Im Backend können Sie die ClientID wie folgt erhalten

clientId = ((OAuth2Authentication) authentication).getOAuth2Request().getClientId();

und implementieren Sie basierend auf der clientId ein anderes Verhalten.

Rocks360
quelle
0

Eine Antwort ist, dass jede App-Plattform ein anderer Client ist und daher eine andere Client-ID haben sollte. Eine für die iOS-App, eine für die Website usw.

Um zwischen einem iPad und einem iPhone zu unterscheiden, würde ich vorschlagen, sich nicht auf das OAuth-System zu verlassen.

RibaldEddie
quelle
0

Beim Entwickeln meines Backends mit Spring Boot und OAuth2 bin ich auf dasselbe Problem gestoßen. Das Problem, auf das ich gestoßen bin, war, dass, wenn mehrere Geräte die gleichen Token gemeinsam nutzen, sobald ein Gerät das Token aktualisiert hat, das andere Gerät keine Ahnung hat und, um es kurz zu machen, beide Geräte in einen Token-Aktualisierungsrausch geraten sind. Meine Lösung bestand darin, den Standardwert AuthenticationKeyGeneratordurch eine benutzerdefinierte Implementierung zu ersetzen, die DefaultAuthenticationKeyGeneratoreinen neuen Parameter client_instance_idin der Schlüsselgeneratormischung überschreibt und hinzufügt . Meine mobilen Clients würden dann diesen Parameter senden, der für alle App-Installationen (iOS oder Android) eindeutig sein muss. Dies ist keine spezielle Anforderung, da die meisten mobilen Apps die Anwendungsinstanz bereits in irgendeiner Form verfolgen.

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);
    }

}

welche du dann auf ähnliche weise spritzen würdest:

final JdbcTokenStore tokenStore = new JdbcTokenStore(mDataSource);
tokenStore.setAuthenticationKeyGenerator(new EnhancedAuthenticationKeyGenerator());

Die HTTP-Anfrage würde dann ungefähr so ​​aussehen

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}}

Der Vorteil dieses Ansatzes besteht darin, dass client_instance_idder Standardschlüssel generiert wird, wenn der Client keinen sendet. Wenn eine Instanz bereitgestellt wird, wird jedes Mal derselbe Schlüssel für dieselbe Instanz zurückgegeben. Außerdem ist der Schlüssel plattformunabhängig. Der Nachteil wäre, dass der MD5-Digest (intern verwendet) zweimal aufgerufen wird.

Cosmin Radu
quelle