Spring Security - Understanding Security Context

Security Context and its related classes are fundamental to Spring Security. A successful authentication process needs to properly set the SecurityContextHolder. The user information stored in Security Context will be used for authorization.

SecurityContextHolder

  • The SecurityContextHolder is where Spring Security stores the details of who is authenticated.
  • By default the SecurityContextHolder uses a ThreadLocal to store these details. You can set system property to override this behavior.
  • When a user is authenticated, authentication processing filter configures the SecurityContextHolder to hold the securityContext associated with the user.
  • Spring docs
  • java doc
  • source code

image from Spring Security Reference - SecurityContextHolder

important methods are

  • createEmptyContext()
  • setContext(SecurityContext context)
  • getContext()

SecurityContext

  • SecurityContext Interface defining the minimum security information associated with the current thread of execution.
  • The security context is stored in a SecurityContextHolder.
  • Java doc

SecurityContext contains method to get and set Authentication object.

1
2
3
4
public interface SecurityContext extends Serializable {
Authentication getAuthentication();
void setAuthentication(Authentication authentication);
}

SecurityContextImpl - the default implementation of SecurityContext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class SecurityContextImpl implements SecurityContext {
private Authentication authentication;

public SecurityContextImpl() {}

public SecurityContextImpl(Authentication authentication) {
this.authentication = authentication;
}

@Override
public Authentication getAuthentication() {
return authentication;
}

@Override
public void setAuthentication(Authentication authentication) {
this.authentication = authentication;
}
}

Authentication

  • Authentication interface extends Principal interface
  • Represents the token for an authentication request or for an authenticated principal once the request has been processed by the AuthenticationManager.authenticate(Authentication) method.
  • The most common Authentication implementation is UsernamePasswordAuthenticationToken
  • spring security doc
  • java doc
  • source code

The Authentication serves two main purposes within Spring Security:

  • An input to AuthenticationManager to provide the credentials a user has provided to authenticate. When used in this scenario, isAuthenticated() returns false.
  • Represents the currently authenticated user. The current Authentication can be obtained from the SecurityContext.

The Authentication should contain:

  • principal - identifies the user. When authenticating with a username/password this is often an instance of UserDetails. - identifies the user. When authenticating with a username/password this is often an instance of UserDetails.
  • credentials - Often a password. In many cases this will be cleared after the user is authenticated to ensure it is not leaked.
  • authorities - the GrantedAuthoritys are high level permissions the user is granted. A few examples are roles or scopes.

Authentication Interface

1
2
3
4
5
6
7
8
public interface Authentication extends Principal, Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
Object getCredentials();
Object getDetails();
Object getPrincipal();
boolean isAuthenticated();
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}

Access Authentication Object

You can easily get the currently authenticated principle from SecurityContextHolder in spring boot application.

1
2
3
4
5
6
7
8
public String getCurrentUserName(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication instanceof AnonymousAuthenticationToken)) {
String currentUserName = authentication.getName();
return currentUserName;
}
return "";
}

GrantedAuthority

  • Represents an authority granted to an Authentication object.
  • A GrantedAuthority must either represent itself as a String or be specifically supported by an AccessDecisionManager.
  • java doc
1
2
3
public interface GrantedAuthority extends Serializable {
String getAuthority();
}

The simpliest GrantedAuthority is SimpleGrantedAuthority. You create one by passing a role as String.

1
new SimpleGrantedAuthority("ROLE_USER")