2013-08-15 12 views
5

Używamy poświadczenia zasobów właściciela przyznania homologacji typu (z oauth2:password w security-config.xml Zagrajmy się ten scenariusz, aby wyjaśnić mój kłopot.Używając Spring Security OAuth2, jaki jest właściwy sposób na odświeżenie zapisanego uwierzytelnienia w TokenStore?

  1. Bob został stworzony z organami ROLE_USER
  2. Bob próbuje uzyskać dostęp do OAuth2 chronionej zasób
  3. Bob korzysta z oficjalną aplikację mobilną do niego dostęp, więc poświadczenia klienta są poprawne
  4. token dostępu Boba jest tworzony i przechowywany w TokenStore, włączył na jego username, client_id i scope. (patrz DefaultAuthenticationKeyGenerator.java)
  5. Telefon Boba próbuje wywołać chronione usługi tym tokenem dostępu, ale te usługi wymagają od użytkowników posiadania authority z ROLE_MOBILE_USER.
  6. Bob kontaktuje się z właścicielem bazy danych i dodaje do swojego użytkownika ROLE_MOBLE_USER w bazie danych.
  7. Bob próbuje uzyskać kolejny token dostępu, ale DefaultTokenServices zwraca mu ten sam, niepracujący token dostępu.
  8. Jedynym sposobem na wykorzystanie jego nowego authority jest poczekać, aż wygasa jego stary token dostępu, aby mógł uzyskać nowy token dostępu z poprawną authority.

Istnieje wiele sposobów rozwiązania tego problemu.

Po pierwsze aplikacja administracyjna, która dodaje ROLE_MOBILE_USER do władz Boba, może następnie usunąć wszystkie tokeny dostępu i autoryzacje w bazie danych. W ten sposób DefaultTokenServices po prostu utworzy nowy z odpowiednimi uprawnieniami uszeregowanymi jako jego nowa autoryzacja OAuth2. Jednak możemy nie chcieć, aby administracyjna aplikacja webowa zajmowała się OAuth w tym momencie (przynajmniej jeszcze nie). Jeśli to możliwe, chcielibyśmy, aby obawy administracyjne były jak najbardziej zwięzłe, a na razie nie ma zależności na oauth.

mogliśmy narazić metodę do punktu końcowego /oauth/access_tokenDELETE i powiedz aplikację mobilną i spróbuj usunąć ten żeton dostępu i ponowne zainteresowanie jeden, tylko w przypadku, gdy są przechowywane authorities zestarzeć. Czuje się bardziej jak praca na okrągło.

Wreszcie mogę serializować authorities w mojej własnej zdefiniowanej AuthenticationKeyGenerator. Zasadniczo użyłby autoryzacji i wykonałby na nich ten sam algorytm skrótu. W ten sposób, gdy Bob spróbuje się zalogować, dostanie ten sam token dostępu, ale bazowy magazyn tokenowy rozpozna, że ​​ma inne uwierzytelnienie (od menedżera uwierzytelniania w komponencie bean tokena) i odświeża swoją bazę danych. Problem z tym rozwiązaniem polega na tym, że polega on tylko na zachowaniu implementacyjnym bazowego magazynu tokenów (chociaż zachowują się one zarówno w ten sposób), jak InMemoryTokenStore i JdbcTokenStore.

Czy możesz wymyślić jakieś lepsze/czystsze rozwiązania? Czy to nadmiar myślenia?

Z góry dziękuję.

+0

dodam, że w tym momencie użył niestandardowego 'AuthenticationKeyGenerator' i rzeczy działały poprawnie. Nadal chciałbym mieć lepsze/czystsze rozwiązanie, ponieważ klucz jest sprawdzany tylko wtedy, gdy serwer autoryzacji jest proszony o nowy token, ale serwer zasobów wciąż może używać starych uprawnień. – Joe

+0

Czy wciąż trzymasz się tego rozwiązania, czy też znalazłeś lepszy sposób rozwiązania tego problemu? Mam dokładnie ten sam problem i nie jestem pewien, jak sobie z tym poradzić. – rpvilao

+0

Utknęliśmy przy tym rozwiązaniu i nie napotkaliśmy na razie żadnych problemów. Polecam jednak pierwsze rozwiązanie i przyjmuję, że zmiana autoryzacji użytkownika wymaga dotknięcia bazy danych tokenu. – Joe

Odpowiedz

2

Rozwiązałem ten problem w mojej aplikacji, usuwając wszystkie tokeny dla danego użytkownika po wysłaniu informacji uwierzytelniających.

Użyj niestandardowego komponentu bean uwierzytelniania uwierzytelniania.

@Component("authenticationProvider") 
public class AuthenticationProviderImpl implements AuthenticationProvider 

Autowire w fasoli sklepu tokena.

@Autowired 
@Qualifier("tokenStore") 
private TokenStore tokenStore; 

Następnie w metodzie uwierzytelniania usuń wszystkie tokeny dla danego użytkownika, jeśli poświadczenia zostaną przekazane po raz drugi.

@Override 
public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
    UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication; 

    try { 
     //Do authentication 

     //Delete previous tokens 
     Collection<OAuth2AccessToken> tokenCollection = tokenStore.findTokensByUserName(token.getName()); 
     for (OAuth2AccessToken oToken : tokenCollection){ 
      tokenStore.removeAccessToken(oToken); 
     } 

     //return Authentication; 
    } 
} 

większość wniosków będzie użycie tokena i ominie to całkowicie, ale gdy poświadczenia są przekazywane, nowy żeton zostanie wygenerowany. Ten token zostanie powiązany z nowym obiektem uwierzytelniania, który będzie zawierał wszystkie nowe role i zmiany wprowadzone do użytkownika.

+0

Rozumiem ten sposób robienia rzeczy, ale czy nie ma lepszego sposobu na zrobienie tego? Trudno mi uwierzyć, że deweloperzy wiosny oauth2 nie myśleli o tym problemie ... Nie wydaje mi się, żebym musiał ponownie przesłać referencje, aby unieważnić poprzedni stan, ponieważ najpierw aplikacja nie powinna przechowywać poświadczenia i to jest cały punkt oauth, a po drugie nie wydaje się właściwe, aby zapytać użytkownika ponownie poświadczenia tylko dlatego, że nie możemy wykonać podstawowej operacji po stronie serwera:/Czy nadal trzymasz się tego, czy znalazłeś jakieś inne rozwiązanie do tego problemu? – rpvilao

+0

Rozwiązałem to w ten sam sposób. Myślę, że brakuje nam wsparcia, aby zaktualizować uwierzytelnianie z oauth2. – Gazeciarz

0

miałem ten sam problem i rozwiązać go z tej funkcji:

protected void reloadUserFromSecurityContext(SecurityContext securityContext, Person user){ 
    OAuth2Authentication requestingUser = (OAuth2Authentication) securityContext.getUserPrincipal(); 
    Object principal = (PersonUserDetails) requestingUser.getUserAuthentication().getPrincipal(); 
    if(principal instanceof PersonUserDetails) { 
     ((PersonUserDetails) principal).setPerson(user); 
    } 
    OAuth2AuthenticationDetails authDetails = (OAuth2AuthenticationDetails) requestingUser.getDetails(); 
    OAuth2AccessToken tokenStored = jdbcTokenStore.readAccessToken(authDetails.getTokenValue()); 
    jdbcTokenStore.storeAccessToken(tokenStored, requestingUser); 
} 

To jest przykład dla aktualizacji atrybutem dla PersonUserDetails obiekt, który znajduje się w OAuth2Authentication

Powiązane problemy