본문 바로가기
Backend/Spring

Spring Security Architecture / 스프링 시큐리티 구조

by unknownomad 2023. 11. 20.

Authentication vs Authorization

Authentication

the process of validating your credentials (such as User username and password) to verify your identity and whether you are the person you claim to be, or not.

Or simply put, Authentication is about knowing who you are.

Authorization

the process to determine whether the authenticated user has access to a particular resource.

Or simply put, Authorization is about knowing whether you have the right to access what you want or not.

 

Spring Security Architecture (simple ver.)

https://medium.com/@haytambenayed/how-does-spring-security-work-internally-525d359d7af

 

SecurityFilterChain

Spring Security maintains a filter chain internally where each of the filters is invoked in a specific order. Each filter will try to process the request and retrieve authentication information from it. For example, we have the UsernamePasswordAuthenticationFilter which is used in case of a POST request with username and password parameters (typically with a login page).

 

AuthenticationManager

This is an interface whose implementation (ProviderManager) has a list of configured AuthenticationProviders that are used for authenticating user requests.

 

AuthenticationProvider

An AuthenticationProvider is an abstraction for fetching user information from a specific repository (like a database, LDAP, custom third party source, etc.). It uses the fetched user information to validate the supplied credentials. (e.g: DaoAuthenticationProvider, LdapAuthenticationProvider, OpenIDAuthenticationProvider …)
When talking about AuthenticationProvider, we usually come across the UserDetailsService. There is often a confusion between both, although they have different roles.

AuthenticationProvider authenticates (compares) the request credentials against system credentials.

UserDetailsService is purely a DAO for user data and performs no other function other than to supply that data that match with user provided Username. It does not tell the application whether authentication is successful or failed.

 

Authentication Flow

[Step 1]

When an incoming request reaches our system, Spring Security starts by choosing the right security filter to process that request:

Is the request a POST containing username and password elements?

=> UsernamePasswordAuthenticationFilter is chosen.

Is the request having a header “Authorization : Basic base64encoded(username:password)”? => BasicAuthenticationFilter is chosen… and so the chaining goes on.

[Step 2]

When a filter had successfully retrieved Authentication informations from the request,

the AuthenticationManager is invoked to authenticate the request.

Via its implementation, the AuthenticationManager goes through each of the provided AuthenticationProvider(s) and try to authenticate the user based on the passed Authentication Object.

[Step 3]

When the Authentication is successful, and a matching user is found, an Authentication Object containing the user Authorities (which will be used to manage the user access to the system’s resources) is returned and set into the SecurityContext.


Spring Security Architecture (in-depth ver.)

https://chathurangat.wordpress.com/2017/08/23/spring-security-authentication-architecture/

 

1. Received the Http Request 

Spring security has a series/chain of filters. Therefore when a request comes, it will go through a chain of filters for authentication and authorization purposes. When there is an user authentication request, that will also go through the chain of filters as usual until it finds the relevant Authentication Filter based on the authentication mechanism/model.

 

2. Creates AuthenticationToken based on user credentials

Once the authentication request is received by the relevant AuthenticationFilter, it extracts the username and password from the received request (most of the authentication mechanism require username and password). After that it creates an Authentication object based on the extracted user credentials.

If the extracted credentials are username and password, then UsernamePasswordAuthenticationToken will be created using username and password extracted/found.

 

3. Delegating created AuthenticationToken for AuthenticationManager

After creating the UsernamePasswordAuthenticationToken object, it will be used to invoke the authenticate method of the AuthenticationManager. AuthenticationManager is a just an interface and actual implementation is ProviderManager.

 

AuthenticationManager.java

public interface AuthenticationManager {
    Authentication authenticate(Authentication authentication) throws AuthenticationException;
}

 

ProviderManager has a list of configured AuthenticationProvider(s) that should be used for authenticating user requests. ProviderManager will go through each of the provided AuthenticationProvider(s) and try to authenticate the user based on the passed Authentication Object (e.g:- UsernamePasswordAuthenticationToken)

 

4. Trying to authenticate with list of AuthenticationProvider(s)

AuthenticationProvider tries to authenticate user with provided authentication object.

public interface AuthenticationProvider {
 
    Authentication authenticate(Authentication authentication) throws AuthenticationException;
 
    boolean supports(Class<?> authentication);
}

 

Here are some of the existing authentication providers that comes with the framework:

  • CasAuthenticationProvider
  • JaasAuthenticationProvider
  • DaoAuthenticationProvider
  • OpenIDAuthenticationProvider
  • RememberMeAuthenticationProvider
  • LdapAuthenticationProvider

 

5. UserDetailsService Required?

Some of the AuthenticationProvider may use UserDetailsService for retrieving the user details based on the username. (e.g:- DaoAuthenticationProvider)

public interface UserDetailsService {
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

 

6 and 7UserDetails or User Object?

UserDetailsService will retrieve the UserDetails (actual implementation is User) based on the username.

 

8. Authentication Object Or AuthenticationException?

If the user is successfully authenticated, then the fully populated Authentication object will be returned. Otherwise an AuthenticationException will be thrown.

According to the AuthenticationProvider interface, AuthenticationProvider will exactly return fully populated authentication object (on successful authentication) or throw an AuthenticationException (on authentication failure).

Fully populated Authentication Object

  • authenticated – true
  • grant authorities list
  • user credentials (username only)

If any AuthenticationException is thrown, that will be handled by the configured AuthenticationEntryPoint that supports for the authentication mechanism.

 

9. Authentication is done!

AuthenticationManager will return the obtained fully populated Authentication object back to the relevant Authentication Filter.

 

10. Setting up Authentication Object in SecurityContext

Then the related AuthenticationFilter will store the obtained authentication object in the SecurityContext for future filter uses. (Use for Authorization Filters)

SecurityContextHolder.getContext().setAuthentication(authentication);


Reference:

https://medium.com/@haytambenayed/how-does-spring-security-work-internally-525d359d7af

https://chathurangat.wordpress.com/2017/08/23/spring-security-authentication-architecture/

댓글