28 Eylül 2020 Pazartesi

SpringSecurity OAuth2 @EnableOAuth2Sso Anotasyonu - Kullanmayın

Giriş
Açıklaması şöyle. Eğer SpringBoot kullanıyorsak bu anotasyona gerek yok.
...the @EnableOAuth2Sso annotation transforms our application into an OAuth2 client. It instructs Spring to configure an OAuth2ClientAuthenticationProcessingFilter, along with other components that our application needs to be capable of obtaining access tokens from an authorization server.


23 Eylül 2020 Çarşamba

SpringData Rest Kullanımı

Giriş
Tüm @RepositoryRestResource olarak işaretli repository sınıflarını tarar ve HATEOAS formatında çıktı verir. Açıklaması şöyle. @RepositoryRestResource Anotasyonu yazısına bakabilirsiniz.
By default, Spring Data REST will export ALL top-level, public interface repositories. You only need @RepositoryRestResource to either NOT export an interface, or to alter the details of the endpoint.
Enpoint'lerin ismi repository arayüzünün çoğul hale getirilmiş halidir.

Maven
Şu satırı dahil ederiz
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency>

1. Resource Discoverability İçin Kullanılacak URL
Örneği application.properties dosyası şöyle olsun
spring.data.rest.base-path=myapi
Bu durumda 
"localhost:8080/myapi" adresine gittiğimizde SpringData Rest tarafından bilinen rest endpoint'leri görebiliriz. Eğer base-path tanımlı değilse "http://localhost:8080/" adresini kullanırız

Örnek
Şöyle yaparız
spring.data.rest.base-path=/api

2. Ne Zaman Spring Data Rest yerine Custom Service Kullanmalı?
Ne zaman Custom Service yazmalı ve ne zaman Spring Data Rest kullanmalı sorusu hep kafa karıştırıyor. Bu sorunun cevaplarından birisi şöyle. Eğer sadece basit CRUD benzeri işler REST üzerinden yapacaksak Spring Data Rest yeterli. Açıklaması şöyle
Spring Data is an additional convenient mechanism for interacting with database entities, organizing them in a repository, extracting data, changing it. in some cases, it will be enough to declare the interface and method in it, without implementing it. P.S and it's a good choice if you're creating a simple crud
3. Repository İçin URL Örnekleri
- findAll işlemi için repository ismi yazılır.
findAll işlemi yazısına taşıdım

- findById, Delete, Post , Put işlemleri için Repository'den sonra id yazılır. Şöyle yaparız.
http://localhost:8080/people/1

- http://localhost:8080/myendpoint/search şeklinde yazarsak repository sınıfındaki custom Query'ler gösterilir.

- http://localhost:8080/people/search/findByLastName?name=Baggins şeklinde yazarsak findByLastName metodunu parametreler ile çağırırız.

3. URI Template Kullanımı
- Eğer sayfalama istemiyorsak Repository nesnemizi JpaRepository, PaginsAndSortingRepository yerine CrudRepository 'den kalıtmak gerekir.
- Veya spring.data.rest.default-page-size değeri değiştirilebilir. Varsayılan sayfa büyüklüğü 20

Page ve Size Parametreleri
- ?size=10 yazarsak sayfa büyüklüğü değiştirilir.
- ?page=1 yazarsak kaçıncı sayfayı isteğimizi belirtiriz.

Sort Parametresi
?sort= şeklinde yaparız.

Projection 
Parametresi
Örnek ver

4. İlişki Kuralları
Açıklaması şöyle.
1) If you do not define a Repository for the child type, a link will not be generated, and it will instead be embedded in the parent object. Of course, this only is useful if you don't need a Repository for that object.

2) FetchType.EAGER will eagerly load the child object. Since the object is already loaded, there is no reason to provide a link to it, so spring-data-rest will embed the object. Make sure to put this on the side with the single object, not the Collection

21 Eylül 2020 Pazartesi

SpringSecurity OAuth2 Resource Server application.properties Ayarları

Örnek - ResourceServer
Şöyle yaparız. issuer-uri ile Resource Server'a Authorization Server'ın adresi belirtilir.
server: 
  port: 8081
  servlet: 
    context-path: /resource-server-jwt
 
spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://localhost:8083/auth/realms/baeldung
Örnek - ResourceServer
Şöyle yaparız
spring: security: oauth2: resourceserver: jwt: jwk-set-uri: http://localhost:8080/auth/realms/My-Realm/protocol/openid-connect/certs server: port: 9191
Açıklaması şöyle
This JWK URI is required to validate the JWT token that comes in with the request.

SpringSecurity OAuth2 @EnableAuthorizationServer Anotasyonu - Authorization Server Gerçekleştirimi

Giriş
Bu projeler maintenance moda alındılar. Dolayısıyla spring dokümantasyonunda 
"No Authorization Server Support" deniliyor. Yani gidin gerçek bir Authorization Server sağlayıcısı kullanın deniliyor.

Maven
Şu satırı dahil ederiz.  
- spring-boot-starter-web REST çağrılarına cevap vermek için lazım. 
- spring-security-jwt bir JWT token dönmek için lazım
- spring-security-oauth2-autoconfigure otomatik konfigürasyon için lazım
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-jwt</artifactId>
  <version>1.1.1.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework.security.oauth.boot</groupId>
  <artifactId>spring-security-oauth2-autoconfigure</artifactId>
  <version>2.4.0</version>
</dependency>
1. Basit Kullanım -  Client Credentials Grant
Client Credentials Grant (yani kullanıcı adı ve şifre ile token alma) için OAuth2 Grant Tipleri yazısına bakabilirsiniz.

Bu anotasyon şu adrese hizmet veriyor
localhost:8080/oauth/token?grant_type=client_credential&...
Postman ile token isterken şöyle yaparız
- Authorization sekmesinde Basic Auth seçilir. Username Password alanları doldurulur
- Body sekmesinde x-www-formurl-encoded seçilir. Key olarak grant_type ve Value olarak client_credentials seçilir
veya şöyle yaparız
- Authorization sekmesinde Basic Auth seçilir. Username Password alanları doldurulur
- URL olarak "localhost:8080/oauth/token?grant_type=client_credentials&scope=any" kullanılır
Basit kullanımda client bilgisi application.properties dosyasına giriliyor.

Örnek 
Şöyle yaparız
@EnableAuthorizationServer
@SpringBootApplication
public class SpringAuthorizationServerApplication {
  public static void main(String[] args) {
  SpringApplication.run(SpringAuthorizationServerApplication.class, args);
  }
}
applicaton.yml dosyasına şöyle yaparız. Burada tek bir client tanımlanabiliyor.
security:
  oauth2:
    client:
      client-id: clientId
      client-secret: very-strong-secret
2. AuthorizationServerConfigurerAdapter İle Kullanım
Bu kullanımda "Authorization Code Grant" gerçekleştiriliyor. Yani önce
1. Authorization Request isteği Resource Owner'a gönderiliyor. O da Authorization Grant dönüyor.
2. Bu Authorization Grant ile Authorization Server'a gideriz. O da bir Access Token döner




15 Eylül 2020 Salı

SpringSecurity ExpressionUrlAuthorizationConfigurer - HttpSecurity İle Kullanılır, AuthorizedRequests İçindir

Giriş
Bu sınıfın içinde iki tane sınıf daha var. Bunlar ExpressionInterceptUrlRegistry ve AuthrorizedUrl sınıfları. Bu yazıda her ikisinin metodlarını sanki birmiş anlattım.

Bu sınıfı httpSecurity.authorizedRequests() çağrısı ile elde ederiz.

Genel Kullanım
Önce herkesin doğrulamaya gerek kalmadan erişebileceği adresler belirtilir
Daha sonra belli rollere sahip kullanıcıların erişebileceği adresler belirtilir
Daha sonra doğrulanmış herhangi bir kullanıcının erişebileceği ortak adresler belirtilir.

Bu adımlar şöyle
1. antMatcher().permitAll() ile adrese herkesin erişmesi sağlanır
Örneğin OAuth doğrulaması yaptıktan sonra redirect url için permitAll() yapmak gerekir.

2. antMatcher().hasRole(), antMatcher().access() ile adrese doğrulama yapılması sağlanır
3. anyRequest().authenticated()  ile geri kalan adreslere doğrulama yapılması sağlanır.

Role ve Authority Farkı
Aslında bu ikisi aynı şey gibi anlatılıyor. Açıklaması şöyle
Roles and authorities are similar in Spring.

The main difference is that, roles have special semantics – starting with Spring Security 4, the ‘ROLE_‘ prefix is automatically added (if it's not already there) by any role related method.

So hasAuthority(‘ROLE_ADMIN') is similar to hasRole(‘ADMIN') because the ‘ROLE_‘ prefix gets added automatically.
Ancak aslında biraz farklı şeyler. Açıklaması şöyle.
ROLE_ prefix is used by spring security, to identify that it is as a role. A role has a set of privileges a.k.a Authorities, these authorities define varies permissions for a role. ex:- EDIT_PROFILE, DELETE_PROFILE

You can define both the roles and authorities, if you are defining a role then it must be prefixed with "ROLE_"
Role isimleri ROLE_ öneki ile başlamıyorsa Spring otomatik ekler. Spring dokümanındaki açıklama şöyle.
By default if the supplied role does not start with 'ROLE_' it will be added. This can be customized by modifying the defaultRolePrefix on DefaultWebSecurityExpressionHandler.
access metodu
Şöyle yaparız
antMatchers("/some-action-**").access("hasAuthority('ADMIN')")
antMatchers  metodu - URL
ANT tarzı URL kullanabilmeyi sağlar.
Örnek
Şöyle yaparız.
http
  .authorizeRequests()
  .antMatchers("/index.html", "/", "/home", "/login").permitAll()
  .anyRequest().authenticated()
antMatchers  metodu - HttpMethod + URL
Örnek
Şöyle yaparız
@Override
protected void configure(HttpSecurity http) throws Exception{
  http.authorizeRequests()
    .antMatchers(HttpMethod.POST,"/file/file-upload").hasAuthority("ADMIN")
    .antMatchers(HttpMethod.POST,"/data/add-data").hasAuthority("ADMIN")
    .antMatchers(HttpMethod.GET,"/data").hasAnyAuthority("ADMIN","USER")
    .antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_URL).permitAll()
    .anyRequest().authenticated()
  .and()
    ...
}
anyRequest metodu
Genellikle authenticated() veya hasRole() metodu çağrılır.

authenticated() metodu ile kullanıcının bir yöntem ile doğrulanmış olması gerekir.
hasRole() metodu ile kullanıcının hem doğrulanmış hem de belirtilen role sahip olması gerekir.

Örnek
Şöyle yaparız.
http.authorizeRequests()
  // api security is handled elsewhere (See OAuth2ServerConfiguration)
  .antMatchers("/api/**", "/oauth/**", "/management/**")
  .permitAll()
  // end api security
  .anyRequest().hasRole(UserRole.ADMIN.name())
  .and()
  .formLogin().loginPage("/login")
  .permitAll()
  .and()
  .logout().permitAll();
mvcMatchers metodu
Örnek
Şöyle yaparız
http.authorizeRequests()
  .mvcMatchers("/books").hasRole("admin")
  .mvcMatchers("/book").hasRole("admin")
  .mvcMatchers("/").permitAll()
permitAll metodu
Belirtilen adreslere herkesin erişebilmesini sağlar. Açıklaması şöyle
...will configure the authorization so that all requests are allowed on that particular path:
...
This is achieved without disabling the security filters – these still run, so any Spring Security related functionality will still be available.
Örnek
Şöyle yaparız.
 http.authorizeRequests()
     .antMatchers("/restservice/**").permitAll();

SpringSecurity RememberMeAuthenticationToken Sınıfı

constructor
Şöyle yaparız
UserPrincipal userPrincipal = ...
User user = userService.findById(userPrincipal.getId());
 new RememberMeAuthenticationToken("myKey2222", userPrincipal, user.getUserRole());