Spring Boot et OAuth 2.0 : Implémentation du flux Authorization Code

Comprendre OAuth 2.0

OAuth 2.0 est un protocole standard d'autorisation qui définit des flux spécifiques pour les applications web, mobiles et desktop. Il simplifie les processus d'accès délégué aux ressources protégées.

Le flux Authorization Code

Ce mode offre le processus d'autorisation le plus complet et sécurisé. L'interaction s'effectue principalement entre le serveur client et le serveur d'autorisation via les étapes :

  1. L'utilisateur est redirigé vers le serveur d'autorisation
  2. Validtaion des permissions par l'utilisateur
  3. Réception d'un code d'autorisation via l'URI de redirection
  4. Échange du code contre un jeton d'accès (backend)
  5. Founriture des jetons d'accès et de rafraîchissement

Implémentation Spring Boot

Dépendances Maven :

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.security.oauth.boot</groupId>
  <artifactId>spring-security-oauth2-autoconfigure</artifactId>
  <version>2.0.0.RELEASE</version>
</dependency>

Configuration de sécurité

@Configuration
public class SecuriteConfig extends WebSecurityConfigurerAdapter {

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

  @Autowired
  @Qualifier("serviceUtilisateurs")
  private UserDetailsService serviceUtilisateurs;

  @Override
  protected void configurerAuth(AuthenticationManagerBuilder auth) {
    auth.userDetailsService(serviceUtilisateurs);
  }

  @Override
  protected void configurerHttp(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/**/*.js", "/**/*.css").permitAll()
        .anyRequest().authenticated()
        .and().formLogin().loginPage("/connexion").permitAll()
        .and().csrf().disable();
  }
}

Serveur d'autorisation OAuth

@Configuration
@EnableAuthorizationServer
public class ConfigOAuth extends AuthorizationServerConfigurerAdapter {

  @Autowired
  private AuthenticationManager gestionAuth;

  @Autowired
  @Qualifier("serviceUtilisateurs")
  private UserDetailsService serviceUtilisateurs;

  @Override
  public void configurerSecurite(AuthorizationServerSecurityConfigurer sec) {
    sec.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
  }

  @Override
  public void configurerClients(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.inMemory()
        .withClient("monClient")
        .secret("{noop}secretClient")
        .scopes("complet")
        .authorizedGrantTypes("authorization_code")
        .autoApprove(true);
  }

  @Override
  public void configurerPointsFinaux(AuthorizationServerEndpointsConfigurer endpoints) {
    endpoints.authenticationManager(gestionAuth)
             .tokenStore(stockageMemoire());
  }

  @Bean
  public TokenStore stockageMemoire() {
    return new InMemoryTokenStore();
  }
}

Fournisseur d'authentification personnalisé

public class AuthProviderCustom implements AuthenticationProvider {

  private final UserDetailsService serviceUtilisateurs;
  private final BCryptPasswordEncoder encodeur;

  public AuthProviderCustom(UserDetailsService s, BCryptPasswordEncoder e) {
    this.serviceUtilisateurs = s;
    this.encodeur = e;
  }

  @Override
  public Authentication authentifier(Authentication auth) throws AuthenticationException {
    String identifiant = auth.getName();
    String motdepasse = auth.getCredentials().toString();
    
    UserDetails utilisateur = serviceUtilisateurs.loadUserByUsername(identifiant);
    
    if (utilisateur != null) {
      if (encodeur.matches(motdepasse, utilisateur.getPassword())) {
        List<GrantedAuthority> droits = Arrays.asList(
          new SimpleGrantedAuthority("ROLE_ADMIN"),
          new SimpleGrantedAuthority("AUTH_ECRITURE")
        );
        return new UsernamePasswordAuthenticationToken(identifiant, motdepasse, droits);
      }
      throw new BadCredentialsException("Mot de passe invalide");
    }
    throw new UsernameNotFoundException("Utilisateur introuvable");
  }

  @Override
  public boolean supports(Class<?> typeAuth) {
    return typeAuth.equals(UsernamePasswordAuthenticationToken.class);
  }
}

Étiquettes: Spring Boot oauth2 Authorization Code Spring Security

Publié le 27 juin à 21h09