Security Top

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security 5:

>> CHECK OUT THE COURSE

1. Overview

Spring Security handles receiving and parsing authentication credentials for us.

In this short tutorial, we're going to look at how to get the SecurityContext information from a request, within our handler code.

2. The @CurrentSecurityContext Annotation

We could use some boilerplate code to read the security context:

SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();

However, there is now a @CurrentSecurityContext annotation to help us.

Furthermore, using annotations makes the code more declarative and makes the authentication object injectable. With @CurrentSecurityContext, we can also access the Principal implementation of the current user.

In the examples below, we're going to look at a couple of ways to get security context data, like the Authentication and the name of the Principal. We'll also see how to test our code.

3. Dependencies

We first need the dependency for spring-security-core:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>5.2.1.RELEASE</version>
</dependency>

4. Implementing with @CurrentSecurityContext

We can use SpEL (Spring Expression Language) with @CurrentSecurityContext to inject the Authentication object or the Principal. SpEL works together with type lookup. The type check is not enforced by default, but we can enable it via the errorOnInvalidType parameter of the @CurrentSecurityContext annotation.

4.1. Obtaining the Authentication Object

Let's read the Authentication object so that we can return its details:

@GetMapping("/authentication")
public Object getAuthentication(@CurrentSecurityContext(expression = "authentication") 
  Authentication authentication) {
    return authentication.getDetails();
}

Note that the SpEL expression refers to the authentication object itself.

Let's test it:

@Test
public void givenOAuth2Context_whenAccessingAuthentication_ThenRespondTokenDetails() {
    ClientCredentialsResourceDetails resourceDetails = 
      getClientCredentialsResourceDetails("baeldung", singletonList("read"));
    OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);

    String authentication = executeGetRequest(restTemplate, "/authentication");

    Pattern pattern = Pattern.compile("\\{\"remoteAddress\":\".*"
      + "\",\"sessionId\":null,\"tokenValue\":\".*"
      + "\",\"tokenType\":\"Bearer\",\"decodedDetails\":null}");
    assertTrue("authentication", pattern.matcher(authentication).matches());
}

We should note that, in this example, we're getting all the details of our connection. As our test code cannot predict the remoteAddress or tokenValue, we're using a regular expression to check the resulting JSON.

4.2. Obtaining the Principal

If we only want the Principal from our authentication data, we can change the SpEL expression and the injected object:

@GetMapping("/principal")
public String getPrincipal(@CurrentSecurityContext(expression = "authentication.principal") 
  Principal principal) { 
    return principal.getName(); 
}

In this case, we're returning only the Principal name using the getName method.

Let's test it:

@Test
public void givenOAuth2Context_whenAccessingPrincipal_ThenRespondBaeldung() {
    ClientCredentialsResourceDetails resourceDetails = 
       getClientCredentialsResourceDetails("baeldung", singletonList("read"));
    OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);

    String principal = executeGetRequest(restTemplate, "/principal");

    assertEquals("baeldung", principal);
}

Here we see the name baeldung, which was added to the client credentials, being found and returned from inside the Principal object injected into the handler.

5. Conclusion

In this article, we've seen how to access properties within the current security context and inject them into parameters in our handler methods.

We've done this by taking advantage of SpEL and the @CurrentSecurityContext annotation.

As always, the full source code for the examples is available over on GitHub.

Security bottom

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security 5:

>> CHECK OUT THE COURSE

Leave a Reply

avatar
  Subscribe  
Notify of