web-dev-qa-db-fra.com

Spring Boot 2.0.3 Oauth2 Security: obtention d'une erreur 401 même lors de l'utilisation d'un jeton d'accès dans l'en-tête

Je crée une application Spring Boot 2.0 et j'essaie d'activer la sécurité oauth2. J'ai maintenant un serveur Auth et un serveur de ressources dans la même application. Mes détails client et utilisateur ainsi que le jeton généré sont conservés dans les bases de données (mysql) et le schéma de la base de données est le même que celui fourni par la documentation de Spring. Lorsque j'atteins le point de terminaison '/ oauth/token /' fournissant clientId et clientSecret dans l'en-tête et les informations d'identification de l'utilisateur dans le corps à l'aide de Postman, j'obtiens le jeton d'accès avec succès.

{
"access_token": "bef2d974-2e7d-4bf0-849d-d80e8021dc50",
"token_type": "bearer",
"refresh_token": "32ed6252-e7ee-442c-b6f9-d83b0511fcff",
"expires_in": 6345,
"scope": "read write trust"
}

Mais lorsque j'essaie de toucher mon api de repos à l'aide de ce jeton d'accès, j'obtiens une erreur 401 non autorisée:

{
"timestamp": "2018-08-13T11:17:19.813+0000",
"status": 401,
"error": "Unauthorized",
"message": "Unauthorized",
"path": "/myapp/api/unsecure"
}

Les autres API que je rencontre sont les suivantes:

http: // localhost: 8080/myapp/api/unsecure

http: // localhost: 8080/myapp/api/secure

myapp est le chemin de contexte de mon application.

Pour une API "sécurisée", j'ai fourni un jeton d'accès dans l'en-tête de la demande, comme décrit dans la documentation Spring:

Authorization: Bearer bef2d974-2e7d-4bf0-849d-d80e8021dc50

Alors que pour les API non sécurisées, j'ai essayé avec et sans en-tête d'authentification. Dans tous les cas, je reçois la même erreur pour les deux API.

De plus, lorsque j'essaie d'imprimer l'utilisateur actuellement authentifié, il est imprimé en tant qu'utilisateur anonyme.

Ce que je veux sont les suivants:

1) Je souhaite que mon API sécurisée soit accessible uniquement lorsque le jeton d'accès est fourni dans l'en-tête de la demande.

2) Je souhaite que mon API non sécurisée soit accessible par un utilisateur non autorisé.

3) Je devrais obtenir un utilisateur actuellement authentifié en utilisant SecurityContextHolder lors de l'accès à une URL sécurisée.

Mon WebSecurityConfigurerAdapter est le suivant:

@Configuration
@EnableWebSecurity(debug=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private DataSource dataSource;

@Autowired
UserDetailsService userDetailsService;

@Autowired
private ClientDetailsService clientDetailsService;

@Bean
public PasswordEncoder userPasswordEncoder() {
    return new BCryptPasswordEncoder(8);
}

@Bean
public TokenStore tokenStore() {
    return new JdbcTokenStore(dataSource);
}

@Autowired
public void configure(AuthenticationManagerBuilder auth) throws 
Exception {
    auth
    .userDetailsService(userDetailsService)
    .passwordEncoder(userPasswordEncoder());
}

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws 
Exception {
    return super.authenticationManagerBean();
}

@Bean
@Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore 
tokenStore){
    TokenStoreUserApprovalHandler handler = new 
    TokenStoreUserApprovalHandler();
    handler.setTokenStore(tokenStore);
    handler.setRequestFactory(new 
    DefaultOAuth2RequestFactory(clientDetailsService));
    handler.setClientDetailsService(clientDetailsService);
    return handler;
}

@Bean
@Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws 
Exception {
    TokenApprovalStore store = new TokenApprovalStore();
    store.setTokenStore(tokenStore);
    return store;
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    .csrf().disable()
    .cors().disable()
    .anonymous().disable()
    .authorizeRequests()
    .antMatchers("/index.html", "/**.js", "/**.css", "/").permitAll()
    .anyRequest().authenticated()
    .and()
    .httpBasic();
}

Ici, en utilisant antMatchers, j'ai autorisé les pages statiques de Angular 6 application, car je prévois d'utiliser celles-ci dans ma vraie application. Et non, la ligne suivante ne fonctionne pas pour autoriser les pages statiques de = angular:

.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()

Mon AuthorizationServerConfigurerAdapter est le suivant:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends 
AuthorizationServerConfigurerAdapter {

@Autowired
private DataSource dataSource;

@Autowired
UserDetailsService userDetailsService;

@Autowired
PasswordEncoder passwordEncoder;

@Autowired
TokenStore tokenStore;

@Autowired
private UserApprovalHandler userApprovalHandler;

@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;


@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
    oauthServer
    .tokenKeyAccess("permitAll()")
    .checkTokenAccess("isAuthenticated()")
    .passwordEncoder(passwordEncoder);
}

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.jdbc(dataSource);
}

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints
    .tokenStore(tokenStore)
    .userApprovalHandler(userApprovalHandler)
    .authenticationManager(authenticationManager)
    .userDetailsService(userDetailsService);
}
}

Mon ResourceServerConfigurerAdapter est le suivant:

@Configuration
@EnableResourceServer
public abstract class ResourceServerConfig extends ResourceServerConfigurerAdapter {

private static final String RESOURCE_ID = "resource-server-rest-api";

@Autowired
TokenStore tokenStore;

@Override
public void configure(ResourceServerSecurityConfigurer resources) {
    resources
    .resourceId(RESOURCE_ID)
    .tokenStore(tokenStore);
}

@Override
public void configure(HttpSecurity http) throws Exception {

    http
    .csrf().disable()
    .cors().disable()
    .anonymous().disable()
    .requestMatchers()
    .antMatchers("/api/**").and()
    .authorizeRequests()
    .antMatchers("/api/secure").authenticated()
    .antMatchers("/api/unsecure").permitAll();
}
}

Mais lorsque j'active l'accès anonyme dans SecurityConfig et déclare mon URL non sécurisée comme permitAll, je peux accéder à cette URL.

.antMatchers("/api/unsecure", "/index.html", "/**.js", "/**.css", "/").permitAll()

Ma classe de contrôleur est la suivante:

@RestController
@RequestMapping("/api")
public class DemoController {

@GetMapping("/secure")
public void sayHelloFriend() {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    System.out.println("Current User: "+authentication.getName());
    System.out.println("Hello Friend");
}

@GetMapping("/unsecure")
public void sayHelloStranger() {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    System.out.println("Current User: "+authentication.getName());
    System.out.println("Hello Stranger");
}
}

Faites-moi savoir si des informations supplémentaires sont nécessaires. Toute aide serait appréciée. Mais veuillez garder à l'esprit que son Spring Boot 2.0 et non 1.5 car les deux ont des différences critiques selon mes résultats.

6
Aditya Kumar

Essayez d'ajouter

@Order(SecurityProperties.BASIC_AUTH_ORDER)

pour le securityConfig? ainsi la chaîne vérifiera d'abord la configuration de votre serveur de ressources.

Et ne savez pas si c'est votre erreur de type, supprimez le résumé du serveur de ressources.

1
Niuhuru Lang