90

In this Spring Boot application there is a web service, which returns some data for a logged-in user:

@RequestMapping("/resource")
public Map<String, Object> home() {
    Map<String, Object> model = new HashMap<String, Object>();
    model.put("id", UUID.randomUUID().toString());
    model.put("content", "Hello World");
    return model;
}

Imagine, the return value of the method depends on what user is currently logged in.

How can I find out, which user is logged in in that method?

Glory to Russia
  • 17,289
  • 56
  • 182
  • 325

9 Answers9

181

As per request:

Spring Boot which uses Spring Security internally provides a SecurityContextHolder class which allows the lookup of the currently authenticated user via:

Authentication auth = SecurityContextHolder.getContext().getAuthentication();

The authentication instance now provides the following methods:

  • Get the username of the logged in user: getPrincipal()
  • Get the password of the authenticated user: getCredentials()
  • Get the assigned roles of the authenticated user: getAuthorities()
  • Get further details of the authenticated user: getDetails()
Peter Kovac
  • 2,257
  • 1
  • 19
  • 18
Roman Vottner
  • 12,213
  • 5
  • 46
  • 63
  • 25
    Or easier and less intrusive, simply add a method argument of type `Principal` if you are only interested in the user, or `Authentication` if you want more. Saves you the hassle of working with the `SecurityContextHolder`. – M. Deinum Jul 01 '15 at 11:38
  • hello how can i use where should i put this to get the logged user thank you – Kamel Mili Mar 30 '16 at 16:00
  • @KamelMili As Spring Security usually is a filter hanging right before the actual application logic is entered, you should be able to access the authentication from almost anywhere in your application. Not sure though if this answers your question – Roman Vottner Mar 30 '16 at 16:11
  • 5
    Get the username of the logged in user: getPrincipal() => getName() ? – kamaci Dec 03 '16 at 14:13
  • Why getCredentials() always return empty string however using auth.eraseCredentials(false) – Ahmed Salem Mar 16 '20 at 08:10
  • Try my answer posted for similar question under https://stackoverflow.com/a/75058792/8294118 – user666 Jan 09 '23 at 14:39
  • After getting Authentication auth, as shown above, extract user name from principal in such way ((User)auth.getPrincipal()).getUsername() – Jeff_Alieffson Apr 18 '23 at 12:15
62

Since Spring Security 3.2 you can get currently logged in user (your implementation of UserDetails) by adding a parameter inside your controller method:

import org.springframework.security.web.bind.annotation.AuthenticationPrincipal;

@RequestMapping("/resource")
public Map<String, Object> home(@AuthenticationPrincipal User user) {
   ..
}

Replace User with the name of your class which implements UserDetails interface.

Edit:

Since Spring Security 4.0 annotation was moved to a different package:

import org.springframework.security.core.annotation.AuthenticationPrincipal;

Addendum:

This will work even in WebFlux reactive environment versus the SecurityContextHolder.getContext().getAuthentication() which won't work because of paradigm shift from thread per request model to multiple requests per thread.

NikolaB
  • 4,706
  • 3
  • 30
  • 38
  • 1
    This always returns null, even when Authentication auth = SecurityContextHolder.getContext().getAuthentication(); returns a user – Daniel Methner Mar 17 '20 at 07:21
  • 2
    @DanielMethner That shouldn't happen I'm using this in controllers in Webflux and Non-Webflux environments and it works everywhere. Can you open a new question and post your configuration, spring versions, and controller where it doesn't work and I'll take a look? – NikolaB Mar 18 '20 at 11:49
  • I forgot to send the authentication header. Problem is therefore solved. thanks anyways! – Daniel Methner Mar 18 '20 at 12:15
  • When I use `@AuthenticationPrincipal UserDetailsImpl user` is not null and working. This is for people using a separate class for principal other than `User` – FindOutIslamNow Aug 16 '21 at 03:48
17

You can simply use HttpServletRequest also to get user principle,

using HttpServletRequest request,

String user=request.getUserPrincipal().getName();
NikhilP
  • 1,508
  • 14
  • 23
17

One way is to add java.security.Principal as a parameter as follows:

@RequestMapping("/resource")
public Map<String, Object> home(Principal principal) {
    Map<String, Object> model = new HashMap<String, Object>();
    model.put("id", UUID.randomUUID().toString());
    model.put("content", "Hello " + principal.getName());
    return model;
}
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
David
  • 4,191
  • 2
  • 31
  • 40
13

Since version 5.2 you can use CurrentSecurityContext annotation:

@GetMapping("/hello")
public String hello(@CurrentSecurityContext(expression="authentication?.name")
                    String username) {
    return "Hello, " + username + "!";
}
ttulka
  • 10,309
  • 7
  • 41
  • 52
3

In Spring boot v2.1.9.RELEASE if you are trying to get the name, email, given_name you can get those details from Pricipal.

Note: I am using spring security with google oauth2.

Map<String , Object> userDetails = ((DefaultOidcUser)SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getAttributes();
        System.out.println(userDetails.get("name"));
        System.out.println(userDetails.get("email"));
        System.out.println(userDetails.get("given_name"));
Max von Hippel
  • 2,856
  • 3
  • 29
  • 46
Gourav
  • 31
  • 2
2

Recently using Keycloak authentication server and accessing currently logged-in user data is accessible like this

String userID;

KeycloakPrincipal kcPrincipal = getPrincipal();
KeycloakSecurityContext ksContext = kcPrincipal.getKeycloakSecurityContext();
IDToken idToken = ksContext.getToken();
userID = idToken.getName();
1

Im using spring boot 2.0 with OAuth so I'm doing it like this

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Object pricipal = auth.getPrincipal();
String user="";
if (pricipal instanceof DefaultOidcUser) {
       user = ((DefaultOidcUser) pricipal).getName();
}
-10

You can find the currently logged in user name without using any spring Security features. All you need is a jdk 1.8

Do the following :

@RequestMapping("/login")
@Override
public ModelAndView AuthChecker(@RequestParam("email") String email, @RequestParam("password") String password, Customers cust) {

     ModelAndView mv = new ModelAndView("index");
     if((repo.findByEmail(email)!=null) && (repo.findByPassword(password)!=null)) {
        
         
      List<Customers> l=  repo.findAll();
      
      cust = (Customers) l.stream() 
      .filter(x -> email.equals(x.getEmail()))        
      .findAny()                                      
      .orElse(null); 
    
        mv.addObject("user",cust.getName());
         mv.setViewName("DashBoardRedirect");
    
         return mv;

Once name fetched successfully, you can use the same in any jsp/thymeleaf view.