# Security

## [DOCUMENTATION](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#introduction)

[OAuth2 Feature Matrix](https://github.com/spring-projects/spring-security/wiki/OAuth-2.0-Features-Matrix). All OAuth 2.0 Client and Resource Server features implemented by Spring. The matrix may be used to determine which project to use based on your OAuth 2.0 Client and Resource Server requirements.

[OAuth2 Login Spring Boot samples](https://github.com/spring-projects/spring-security/tree/5.2.0.RELEASE/samples/boot/oauth2login)

[Spring Security components](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#modules)

## Features

* **Authentication**. It is how we verify the identity of **who is trying to access** a particular resource. A common way to authenticate users is by requiring the user to enter a **username and password**. Once **authentication is performed** we know the identity and can **perform authorization**.
  * Password storage.
    * `PasswordEncoder` is used to perform one way password transformation to store it securely (DelegatingPasswordEncoder)
* [Protection against Exploits](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#exploits)
  * **Cross Site Request Forgery (CSRF)**. The reason that a CSRF attack is possible is that the HTTP **request** from the **victim’s** website and the request from the **attacker’s** website are exactly the **same**. This means there is **no way** to **reject** requests coming from the **evil** website and **allow** requests coming from the **bank’s** website. To protect against CSRF attacks we need to ensure there is **something** in the **request** that the **evil** site is *unable* to provide so we can differentiate the two requests.
    * [Synchronizer Token Pattern](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#csrf-protection-stp)
    * [SameSite attribute](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#csrf-protection-ssa)
    * When should you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection.
  * **Security HTTP Response Headers.**&#x20;
    * ```
      Cache-Control: no-cache, no-store, max-age=0, must-revalidate
      Pragma: no-cache
      Expires: 0
      X-Content-Type-Options: nosniff
      Strict-Transport-Security: max-age=31536000 ; includeSubDomains
      X-Frame-Options: DENY
      X-XSS-Protection: 1; mode=block
      ```
    * Default Security HTTP Response Headers

## Servlet security. Big Picture

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMPNBYr5DjIs5J4i3dX%2F-MMPTmtTfpRSLtMEXfMv%2FScreenshot%202020-11-18%20at%2009.31.43.png?alt=media\&token=c0b68407-cfea-4ad9-b745-bae30eda43ac)

* Spring provides `Filter` implementation named `DelegatingFilterProxy` which is a bridge for *Servlet container lifecycle* and Spring *ApplicationContext*.
* `DelegatingFilterProxy` can be registered via standard Servlet container mechanism, but delegate all the work to a Spring Bean that implements `Filter`&#x20;
* ```java
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
      // Lazily get Filter that was registered as a Spring Bean
      // For the example in DelegatingFilterProxy delegate is an instance of Bean Filter0
      Filter delegate = getFilterBeanFromApplicationContext(someBeanName);
      // delegate work to the Spring Bean
      delegate.doFilter(request, response);
  }
  ```
* **FilterChainProxy** is a special *Filter* provided by Spring Security that allows delegating to many *Filter* instances through SecurityFilterChain.

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMQSkdH9Rhb5iCv44xE%2F-MMQTzX_ptP6_lfexQtU%2FScreenshot%202020-11-18%20at%2014.12.13.png?alt=media\&token=9f094fb9-52ba-4ad5-abea-45c733bf7070)

* **FilterChainProxy** is a starting point for all of Spring Security Servlet support.
  * :bulb: **FilterChainProxy is a great place to start debugging**
  * **FilterChainProxy** clears *SecurityContext* to avoid memory leaks
  * **FilterChainProxy** can be used to determine which *SecurityFilterChain* should be used.

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMQSkdH9Rhb5iCv44xE%2F-MMQV89_us9kyj9KWu13%2FScreenshot%202020-11-18%20at%2014.17.10.png?alt=media\&token=37f01110-f5f5-418b-8563-b16389338e91)

```java
if (URL == "/api/messages") only SecurityFilterChain0 will be invoked;
if (URL == "/messages") SecurityFilterChainN will be invoked;
```

### [Handling Security exceptions](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-exceptiontranslationfilter)

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMQVdsCd3a-U4q-gBrq%2F-MMQW62224OXC1xB30J6%2FScreenshot%202020-11-18%20at%2014.21.28.png?alt=media\&token=5904b47f-6013-4e4d-bc00-736256b06ca5)

1. **ExceptionTranslationFilter** invokes *FilterChain.doFilter(request, response)* to invoke the rest of application
2. ```java
   if (!user.authenticated() || AuthenticationException) {
       startAuthentication();
   }

   void startAuthentication() {
       clear SecurityContextHolder;
       requestCache.save(HttpServletRequest);
       AuthenticationEntryPoint.requestCredentialsFromClient();
       // e.g. login page OR WWW-Authenticate header
   }
   ```

   3\. If (AccessDeniedException) => AccessDeniedHandler.handleAccessDenied();

## Authentication

#### SecurityContextHolder

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMQXxLNmFasLweJHiq7%2F-MMQYWWNKOTJWs6x4335%2FScreenshot%202020-11-18%20at%2014.32.01.png?alt=media\&token=12be7408-422c-4353-acb0-9890830eb888)

This is a :blue\_heart: heart of Spring Security authentication model.

```java
SecurityContext context = SecurityContextHolder.createEmptyContext(); 
Authentication authentication =
    new TestingAuthenticationToken("username", "password", "ROLE_USER"); 
context.setAuthentication(authentication);

SecurityContextHolder.setContext(context); 
// BAD! SecurityContextHolder.getContext().setAuthentication(authentication) to 
// avoid race conditions
```

SecurityContextHolder uses **ThreadLocal** to store details.

#### ProviderManager

ProviderManager is the most commonly user implementation of AuthenticationManager.

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMUC_fFeKud5Ug9YsBe%2F-MMUE-RRFRuCJbdKBe6Q%2FScreenshot%202020-11-19%20at%2007.40.50.png?alt=media\&token=991081d9-9957-4f76-8d46-c6bed71a96a9)

* each AuthenticationProvider knows how to perform a specific type of authentication.
  * e.g. one is able to validate username/password
  * another is able to validate SAML assertion

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMUC_fFeKud5Ug9YsBe%2F-MMUF0V-G0v16a8fnUya%2FScreenshot%202020-11-19%20at%2007.45.16.png?alt=media\&token=ebacf809-b908-4576-8805-2bfb63682a5e)

In fact, multiple **ProviderManager** instances might share the same parent **AuthenticationManager**. Common for scenarios where there are multiple **SecurityFilterChain** instances that have some authentication in common.

By default **ProviderManager** will clear any sensitive credentials info from **Authentication** object which is returned by a successful authentication request.&#x20;

#### AuthenticationEntryPoint

Used to send an HTTP response that requests credentials from a client.

#### AbstractAuthenticationProcessingFilter

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMUC_fFeKud5Ug9YsBe%2F-MMUHuYRALLuRiWDDuHv%2FScreenshot%202020-11-19%20at%2007.57.52.png?alt=media\&token=297679c1-b1a4-449f-ac26-2fbca4f7d313)

1. Based on subclass of **AbstractAuthenticationProcessingFilter** certain type of Authentication is created. E.g. for **UserPasswordAuthenticationFilter** **UserPasswordAuthenticationToken** is created from username and password from **HttpServletRequest**.
2. Authentication is passed to AuthenticationManager.
3. ```java
   if (authentication fails) {
       clear SecurityContextHolder;
       RememberMeServices.loginFail
       invoke AuthenticationFailureHandler;
   }    
   ```
4. ```java
   if (authentication success) {
       SessionAuthenticationStrategy is notified of new login;
       SecurityContextHolder saves Authentication;
       RememberMeServices.loginSuccess;
       ApplicationEventPublisher.publish(InteractiveAuthenticationSuccessEvent);
       invoke AuthenticationSuccessHandler;
   }
   ```

### Username/Password Authentication

* Reading username and password from HttpServletRequest
  * FormLogin
  * Basic Authentication
  * Digest Authentication
* Storage mechanisms
  * Simple (in-memory)
  * Relational DB (JDBC Authentication)
  * Custom data stores with UserDetailService
  * LDAP storage with LDAP Authentication

### [Form Login](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-authentication-form)

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMULx1EOaNIzDeHoUVe%2F-MMUMBmaTnwkCwfEYGmc%2FScreenshot%202020-11-19%20at%2008.16.39.png?alt=media\&token=8724d113-78f2-4d79-9e14-036004040613)

When the username and password submitted:

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMUMxjdwcIH9waRbF3J%2F-MMUN4Et7UM3Y1kX8NLR%2FScreenshot%202020-11-19%20at%2008.20.12.png?alt=media\&token=ab2d8dff-982e-4fcb-b736-64068c8122b8)

```java
protected void configure(HttpSecurity http) {
    http
        // ...
        .formLogin(withDefaults());
}
```

```java
// custom login form configuration
protected void configure(HttpSecurity http) throws Exception {
    http
        // ...
        .formLogin(form -> form
            .loginPage("/login") // src/main/resources/templates/login.html
            .permitAll()
        );
}
```

### [Basic Authentication](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-authentication-basic)

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMUMxjdwcIH9waRbF3J%2F-MMUQm2Wv3053qqVVXmr%2FScreenshot%202020-11-19%20at%2008.36.40.png?alt=media\&token=1b527e48-e32a-44ea-9a2c-4bb73960cfe3)

When a client receives WWW-Authenticate header it knows it should retry with a username and password.

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMUMxjdwcIH9waRbF3J%2F-MMUROvaGR7A1SRz3EeQ%2FScreenshot%202020-11-19%20at%2008.39.23.png?alt=media\&token=dec8426e-1ae3-4f22-8a07-a7b90c61920d)

```java
// minimum explicit configuration
protected void configure(HttpSecurity http) {
    http
        // ...
        .httpBasic(withDefaults());
}
```

### Digest Authentication

:bulb: :fire: :warning: You should not use Digest Authentication in modern applications because it is not considered secure. The most obvious problem is that you must store your passwords in plaintext, encrypted, or an MD5 format. All of these storage formats are considered insecure. Instead, you should store credentials using a one way adaptive password hash (i.e. bCrypt, PBKDF2, SCrypt, etc) which is not supported by Digest Authentication.

### [In-memory Authentication](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-authentication-inmemory)

`InMemoryUserDetailsManager` implements [UserDetailsService](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-authentication-userdetailsservice).

```java
@Bean
public UserDetailsService users() {
    UserDetails user = User.builder()
        .username("user")
        .password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
        .roles("USER")
        .build();
    UserDetails admin = User.builder()
        .username("admin")
        .password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
        .roles("USER", "ADMIN")
        .build();
    return new InMemoryUserDetailsManager(user, admin);
}
```

### [JDBC Authentication](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-authentication-jdbc)

JdbcUserDetailsManager extends JdbcDaoImpl (which implements UserDetailsService)

:information\_source: The default schema is also exposed as a classpath resource named `org/springframework/security/core/userdetails/jdbc/users.ddl`.

There is a support for groups.

```java
// configure DataSource (here it is embedded)
@Bean
DataSource dataSource() {
    return new EmbeddedDatabaseBuilder()
        .setType(H2)
        .addScript("classpath:org/springframework/security/core/userdetails/jdbc/users.ddl")
        .build();
}
```

```java
// configure JdbcUserDetailsManager
@Bean
UserDetailsManager users(DataSource dataSource) {
    UserDetails user = User.builder()
        .username("user")
        .password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
        .roles("USER")
        .build();
    UserDetails admin = User.builder()
        .username("admin")
        .password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
        .roles("USER", "ADMIN")
        .build();
    JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);
    users.createUser(user);
    users.createUser(admin);
}
```

#### [UserDetails](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-authentication-userdetails) and UserDetailsService

[**DaoAuthenticationProvider**](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-authentication-daoauthenticationprovider) uses **UserDetailsService** to retrieve **UserDetails**. DaoAuthenticationProvider validates UserDetails and returns Authentication with proper principal.

![](https://415484505-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LxtoAXZwwOc4XGto8vb%2F-MMUVAwTAqPGqXZw2asr%2F-MMU_Nsp5U9PyZ1T3gF6%2FScreenshot%202020-11-19%20at%2009.18.38.png?alt=media\&token=eaab645e-3faa-48a4-89cb-cdc875be263d)

### [LDAP Authentication](https://docs.spring.io/spring-security/site/docs/current/reference/html5/#servlet-authentication-daoauthenticationprovider)

Did not have a look

## Authorization

* **FilterInvocationSecurityMetadataSource**
  * by default **ExpressionBasedFilterInvocationSecurityMetadataSource** is used
* AccessDecisionManager
* How is it glued to Filters => AbstractSecurityInterceptor. Subclasses
  * FilterSecurityInterceptor

### Protecting common attacks

#### Cache control

This is about cache control header. **Cache-Control**.&#x20;

#### HTTPS

This is about man-in-the-middle attack.\
HsTsHeaderWriter

#### XSS (Cross site scripting)

Header which helps to protect:\
X-XSS-Protection: 1; mode=block

* mode block means block the rendering

#### Content sniffing

X-Content-Type-Options: nosniff

### JSR 250 annotations (Method security)

* @**RolesAllowed**("ROLE\_somerole")
  * :warning: Do not forget to prefix roles with **ROLE\_**
* @**Secured**("ROLE\_somerole")
* @**PreAuthorize**("hasRole('ADMIN')")
  * check happens before method is invoked
  * Spring expression language is used
* @**PostAuthorize**("@authz.check(returnObject, principal?.user) ")
  * ```java
    @Service("authz")
    class AuthService {
        public boolean check(Message msg, User user) {
            return // check some conditions for authorization;
            // Message and User can vary as input params
        }
    }
    ```

## OAuth2

see CommonOAuth2Provider.java\
ClientRegistrationRepository.java\
OAuth2AuthorizationRequestRedirectFilter.java\
OAuth2LoginAuthenticationFilter.java\
OAuth2LoginAuthenticationProvider.java
