Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Keycloak username in AuditorAware

I have implemented Auditing with Spring Data JPA, following exactly this documentation. Everything works fine when I run the app, but when I deploy the WAR to Tomcat and try to create an entity, I get an error in the getCurrentAuditor method.

I have secured my app with keycloak, so in AuditorAwareConfig i am trying to get the keycloak username, and after debugging i found out that request.getUserPrincipal() is null :

java.lang.NullPointerException: null
    at com.cevital.cirta.util.AuditorAwareConfig.getCurrentAuditor(AuditorAwareConfig.java:20) ~[classes/:0.0.1-SNAPSHOT

AuditorAwareConfig :

public class AuditorAwareConfig implements AuditorAware<String> {
    @Autowired
    private HttpServletRequest request;

    @Override
    public Optional<String> getCurrentAuditor() {
        KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) request.getUserPrincipal();
        String userName = kp.getKeycloakSecurityContext().getToken().getPreferredUsername();
        return Optional.ofNullable(userName);
    }
}
like image 337
Bilal Dekar Avatar asked Oct 01 '20 10:10

Bilal Dekar


1 Answers

I recently did the same thing in my applications but I didn't use the Keycloak adapter, Spring Security 5 provides all we need to secure our applications with Keycloak or with any Oauth2 provider. Another difference, I use Hibernate Envers, which allow me to also audit delete operations.

To get the authenticated user, this is how I proceed.

   public static String extractUsernameFromAuthentication() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username;
        if ( isNull( authentication ) ) {
            return null;
        }
        if ( authentication instanceof JwtAuthenticationToken ) {
            JwtAuthenticationToken token = (JwtAuthenticationToken) authentication;
            username = (String) ( token ).getTokenAttributes().get( "preferred_username" );
        } else {
            username = authentication.getName();
        }
        return username;
    }

Remember, I do not use the Keycloak Adapter.

like image 110
akuma8 Avatar answered Sep 22 '22 05:09

akuma8