1

Ich experimentiere mit gRPC mit einem Spring-basierten 'Backend' und Android 'Front-End', die Idee ist, dass ich ein Zugriffs-Token mit dem Passwort-Grant-Typ über HTTP anfordern (Verwenden Sie den RESTful-Endpunkt standard/oauth/token) und verwenden Sie das Zugriffstoken, das in allen nachfolgenden Anforderungen über RPC bereitgestellt wird (Festlegen des Autorisierungsheaders).gRPC und OAuth2 Authentifizierung mit Spring Security

Ich habe einen gRPC-Server Interceptor auf meinem Frühjahr 'Backend', die den Autorisierungsheader vom Server-Aufruf erhalten und das Zugriffs-Token gegen den Token-Speicher authentifizieren.

Ich bin fest, was als nächstes zu tun oder sogar, wenn das, was ich bisher habe, ist der "richtige" Ansatz.

Das ist mein Interceptor:

@Component 
public class GrpcRequestInterceptor implements ServerInterceptor { 
private AuthenticationManager authenticationManager; 

public GrpcRequestInterceptor(AuthenticationManager authenticationManager, AuthorizationCodeServices authorizationCodeServices) { 
     this.authenticationManager = authenticationManager; 
} 

@Override 
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata, ServerCallHandler<ReqT, RespT> serverCallHandler) { 
     String authorizationHeader = metadata.get(Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER)); 

     PreAuthenticatedAuthenticationToken preAuthenticatedAuthenticationToken = 
       new PreAuthenticatedAuthenticationToken(authorizationHeader.substring("Bearer ".length()), ""); 

     PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider = new PreAuthenticatedAuthenticationProvider(); 
     preAuthenticatedAuthenticationProvider.setPreAuthenticatedUserDetailsService(new AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken>() { 
      @Override 
      public UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken preAuthenticatedAuthenticationToken) throws UsernameNotFoundException { 
       ???? 
      } 
     }); 
     Authentication authentication = preAuthenticatedAuthenticationProvider.authenticate(preAuthenticatedAuthenticationToken); 

     SecurityContextHolder.getContext().setAuthentication(authentication); 

     return serverCallHandler.startCall(serverCall, metadata); 
    } 
} 

Wie kann ich den Token-Service erhalten und wie authentifizieren ich meinen Benutzer gegen diesen Dienst nur das Zugriffstoken ich mit mir selbst bereitstellt.

Meine Sicherheit Config ist wie folgt:

@Configuration 
@EnableAuthorizationServer 
@EnableResourceServer 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 
    @Autowired 
    private AccountDetailsService accountDetailsService; 

    @Profile(value = "development") 
    @Override 
    public void configure(WebSecurity web) throws Exception { 
     web.ignoring().antMatchers("/h2-console/**"); 
    } 

    @Override 
    public void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.userDetailsService(accountDetailsService) 
       .passwordEncoder(initPasswordEncoder()); 
    } 

    @Bean 
    public PasswordEncoder initPasswordEncoder() { 
     return new BCryptPasswordEncoder(10); 
    } 
} 

Sollte ich hier die Tokendienst manuell einstellen und dann, dass in meine Interceptor Injektion oder ??? Was ist der "früheste" Weg, dies zu erreichen?

Jede Hilfe wird sehr geschätzt!

Antwort

1

Sie haben wahrscheinlich eine org.springframework.security.oauth2.provider.token.TokenStore-Bean, die Sie injizieren können, um die Authentifizierung zu erhalten. Dann können Sie etwas entlang der Linie von

@Autowired 
private TokenStore tokenstore; 

... 

Authentication authentication = this.tokenstore.readAuthentication(authorizationHeader.substring("Bearer ".length())).getUserAuthentication(); 

(fügen notwendig null Kontrollen) tun.

+0

Genau was ich am Ende getan habe. Danke für die Antwort! – CurtisWebDev

1

Was ich getan habe, war ich weit vom Kurs ab!

@Component 
public class GrpcRequestInterceptor implements ServerInterceptor { 
    @Autowired 
    private TokenStore tokenStore; 

    @Override 
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata, ServerCallHandler<ReqT, RespT> serverCallHandler) { 
     boolean isAuthenticated = isAuthenticated(
      metadata.get(
        Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER) 
      ).substring("Bearer ".length()) 
     ); 

     if (isAuthenticated) { 
      return serverCallHandler.startCall(serverCall, metadata); 
     } 

     throw new UnauthorizedClientException("Unauthorised client connection."); 
    } 

    private boolean isAuthenticated(String bearerToken) { 
     OAuth2Authentication authentication = tokenStore.readAuthentication(bearerToken); 
     if (authentication == null) { 
      return false; 
     } 

     SecurityContextHolder.getContext().setAuthentication(authentication); 

     return true; 
    } 
} 
+0

Hallo CurtisWebDev, ich habe angefangen, an genau der gleichen Implementierung von OAuth2.0 zu arbeiten. Hier kommt mein Benutzer Principal vom gRPC Server selbst. So bekomme ich eine Ausnahme für das Passwort (da es binäres Format sein sollte) beim Abrufen des Benutzers. Obwohl ich Serverinterceptor auch implementiere, empfange ich nicht Prinzipal oder Token. Könnten Sie mir bitte mehr Code über GitHub oder auf andere Weise mitteilen? Deine Hilfe macht mich besser und sehr geschätzt. Irgendwelche Vorschläge werden sehr geschätzt. – Basavaraj

1

Es ist wahrscheinlich besser auf Draht in einem ResourceServerTokenServices anstelle einem TokenStor. Die ResourceServerTokenServices führt zusätzliche Prüfungen für das Zugriffstoken durch, die der TokenStore nicht ausführt, z. B. um sicherzustellen, dass das Token nicht abgelaufen ist.

@Autowired 
private ResourceServerTokenServices tokenServices; 

... 

OAuth2Authentication authentication = tokenServices.loadAuthentication(token); 
SecurityContextHolder.getContext().setAuthentication(authentication); 
Verwandte Themen