15 Aralık 2020 Salı

SpringSecurity OAuth2 AuthorizationServerConfigurerAdapter Sınıfı - Authorization Code Grant - Kullanmayın

Giriş 
"Spring Security OAuth" projesi artık deprecated. Bu yüzden bu sınıfı kullanmayın

Bu kullanımda "Authorization Code Grant" gerçekleştiriliyor.  OAuth2 Grant Tipleri yazısına bakabilirsiniz.

Bu akışta "confidential clients" yani güvenilen client' lara token verilir.

Bir örnek burada

Adımlar
1 Önce AuthorizationCode almamız gerekir
2. Authorization Code ile Access Token almamız gerekir

Kendi uygulamamızda "Login With Facebook" gibi bir link bulunur. Bu linke tıklanınca kullanıcı benim sunucuma gelir. Link şöyledir
localhost:8080/oauth/authorize?response_type=code&client_id=clientId&state=8781487s1
Link'in açıklaması şöyle
To get authorization code we need to request the server and redirect you to the auth server's login page if you're not authenticated. To get the code, we hit /oauth/authorize with a few required params.

- response_type = must set to code (Required)
- client_id = clientId that we set up in auth server (Required)
- state = Some random value to maintain state between server and client(Optional)
- redirect_uri = optional 
Bu linki karşılayan kod için şöyle yaparız. Bu kod iki tane adrese hizmet verir. Bunlar şöyle
localhost:8080/oauth/authorize?...
localhost:8080/oauth/token?grant_type=authorization_code&...
localhost:8080/oauth/authorize?... adresine gelince kod önce bizi bir form login sayfasına yönlendirir. Eğer login başarılı ise bizi redirectUris() ile tanımlanan adrese yönlendirir. 8081 portunu dinleyen kendi uygulamama yönlendirdiği görülebilir.
@SuppressWarnings("deprecation")
@Configuration
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
  @Bean("passwordEncoder")
  BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

  @Override
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients
      .inMemory()
        .withClient("clientId") //Linkteki client_id değeri
        .secret(passwordEncoder().encode("client-secret"))
        .scopes("read", "write")
        .authorizedGrantTypes("authorization_code", "refresh_token")
        .redirectUris("http://localhost:8081/oauth/login/client-app")
        .autoApprove(true);
     }

  @Bean
  JwtTokenStore getAccessTokenConverter() {
    return new JwtTokenStore(JwtTokenEnhancer.getInstance());
  }
}
Kullanıcı tanımlama için şöyle yaparız
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  @Autowired
  @Qualifier("passwordEncoder")
  BCryptPasswordEncoder passwordEncoder;
  
  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
      .withUser("username")
      .password(passwordEncoder.encode("password"))
      .roles("USER");
  }
  
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
      .anyRequest()
      .authenticated().and()
        .formLogin().permitAll()
      .and()
         .logout().permitAll();
    http.csrf().disable();
  }
}
Access Token Alma
Şöyle yaparız
POST /oauth/token?grant_type=authorization_code& code=X2KnGB& client_Id=clientId&state=8781487s1 HTTP/1.1
Host: localhost:8080
Authorization: Basic Y2xpZW50SWQ6Y2xpZW50LXNlY3JldA==
cache-control: no-cache
Çıktı olarak şunu alırız
{
  "access_token": "U9c7fB35jHh6vW-WsBd-VdfLcOs",
  "token_type": "bearer",
  "refresh_token": "hGMk8bgNwO7YHrKaCZkc380BB68",
  "expires_in": 43199,
  "scope": "read write"
}
Burada access token bir de public/private key ile de imzalanıyor. Bu gerekli mi bilmiyorum. Şöyle yaparız
public class JwtTokenEnhancer extends JwtAccessTokenConverter {
  private static final String PRIVATE_KEY = "Your private rsa key";
  private static final String PUBLIC_KEY = "Your public rsa key";
    
  public JwtTokenEnhancer(String publicKey, String privateKey) {
    super.setSigningKey(privateKey);
    super.setVerifierKey(publicKey);
  }
  public static JwtAccessTokenConverter getInstance() {
    return new JwtTokenEnhancer(JwtTokenEnhancer.PUBLIC_KEY, JwtTokenEnhancer.PRIVATE_KEY);
  }
}





Hiç yorum yok:

Yorum Gönder