Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Springboot get username from Authentication via Controller

Problem: I would like to get/extract the username/email only from authenticate.getName()... if possible, not by using parsing the string.

authentication.getName() or principal.getName() values:

[username]: org.springframework.security.core.userdetails.User@21463e7a: Username: [email protected]; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities

In this example, I would like to get only the value of Username which is [email protected]

Solution:

Since I only want to get the username/email ([email protected]), and it is returning the whole principal content/text (above), I replaced the value I set in the subject from the pricipal value... to the email value.. and it works now.

@Override
protected void successfulAuthentication(HttpServletRequest req,
                                        HttpServletResponse res,
                                        FilterChain chain,
                                        Authentication auth) throws IOException, ServletException {
    String email = auth.getName();
    String principal = auth.getPrincipal().toString();
    Date expiration = new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME);
    String token = Jwts.builder()
            .setSubject(email) //from principal to email
            .setExpiration(expiration)
            .signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET.getBytes())
            .compact();
    AuthenticatedUser loginUser = new AuthenticatedUser(email);
    loginUser.setToken(token);
    String jsonUser = Util.objectToJsonResponseAsString(loginUser, "user");
    res.addHeader(SecurityConstants.HEADER_STRING, SecurityConstants.TOKEN_PREFIX + token);
    res.setContentType("application/json");
    res.setCharacterEncoding(ConstantUtil.DEFAULT_ENCODING);
    res.getWriter().write(jsonUser);
}

I can now get the username/email value using different ways like the one you guys are suggesting... even the one I am currently using. I do not need any special parsing now just to get the email value from the Authentication object.

On my previous non RESTful application using Spring... I can easily get the username using Authentication class injected in the controller method parameter.

Controller:

...  
public Ticket getBySwertresNo(Authentication authentication, @PathVariable String swertresNo) {  
    logger.debug("Inside getBySwertresNo: " + swertresNo);  
    System.out.println("\n[username]: " + authentication.getName() + "\n");  
    return m_sugalService.getSwertresInfoBySwertresNo(swertresNo);  
}  
...  

Console:

[username]: [email protected]

Now, on my current project... I used a RESTful approach and after successful authentication, I am returning a token which will be used/injected in the request header. I can login using the token... but when I get the value of authentication.getName()... the return is not just the email address but it contains some other information.

Console (REST + JWT):

[username]: org.springframework.security.core.userdetails.User@21463e7a: Username: [email protected]; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities

I would like to get only the username value which is "[email protected]".

JWT Authentication Filter:

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest req,
                                                HttpServletResponse res) throws AuthenticationException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
        Authentication authentication = authenticationManager.authenticate(authenticationToken);
        return authentication;
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest req,
                                            HttpServletResponse res,
                                            FilterChain chain,
                                            Authentication auth) throws IOException, ServletException {
        String email = auth.getName();
        String principal = auth.getPrincipal().toString();
        Date expiration = new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME);
        String token = Jwts.builder()
                .setSubject(principal)
                .setExpiration(expiration)
                .signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET.getBytes())
                .compact();
        AuthenticatedUser loginUser = new AuthenticatedUser(email);
        loginUser.setToken(token);
        String jsonUser = Util.objectToJsonResponseAsString(loginUser, "user");
        res.addHeader(SecurityConstants.HEADER_STRING, SecurityConstants.TOKEN_PREFIX + token);
        res.setContentType("application/json");
        res.setCharacterEncoding(ConstantUtil.DEFAULT_ENCODING);
        res.getWriter().write(jsonUser);
    }

}

JWT Authorization Filter:

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

    public JWTAuthorizationFilter(AuthenticationManager authManager) {
        super(authManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest req,
                                    HttpServletResponse res,
                                    FilterChain chain) throws IOException, ServletException {
        String header = req.getHeader(SecurityConstants.HEADER_STRING);

        if (header == null || !header.startsWith(SecurityConstants.TOKEN_PREFIX)) {
            chain.doFilter(req, res);
            return;
        }

        UsernamePasswordAuthenticationToken authentication = getAuthentication(req);

SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(req, res);
    }

    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        String token = request.getHeader(SecurityConstants.HEADER_STRING);
        if (token != null) {
            // parse the token.
            String user = Jwts.parser()
                    .setSigningKey(SecurityConstants.SECRET.getBytes())
                    .parseClaimsJws(token.replace(SecurityConstants.TOKEN_PREFIX, ""))
                    .getBody()
                    .getSubject();

            if (user != null) {
                return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
            }
            return null;
        }
        return null;
    }

}
like image 258
Borgy Manotoy Avatar asked Mar 28 '18 08:03

Borgy Manotoy


3 Answers

I think you can use authentication.getName and principal.getName in the injected controller argument of type Authentication and Principal:

@Controller
@RequestMapping("/info")
public class GetNameController {

    @RequestMapping(value = "/name", method = RequestMethod.GET)
    public String getName(Authentication authentication, Principal principal) {
        System.out.println(authentication.getName());
        System.out.println("-----------------");
        System.out.println(principal.getName());
        return "";
    }
}

could produce

admin
-----------------
admin
like image 141
Richard H.M Avatar answered Nov 06 '22 08:11

Richard H.M


It doesn't matter whether you are using token or basic spring security authentication as far as Authentication/Principal object is concerned.

In case of spring security, you can get your current logged in user by
1. Object user = Authentication authentication (as you are already doing)
2.

Object user = SecurityContextHolder.getContext().getAuthentication()
                    .getPrincipal();

In both cases, user will contains the user object you returning from UserDetailsService.loadUserByUsername(...). So using default UserDetailsService you will get spring security's User object which contains basic user information like username, password etc.

So in case if you are using default spring's UserDetailsService, then you can get your current logged in user simply by

UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication()
                        .getPrincipal();
String username = userDetails.getUsername();
like image 29
Afridi Avatar answered Nov 06 '22 09:11

Afridi


You can use

import org.springframework.security.core.Authentication;

import org.springframework.security.core.context.SecurityContextHolder;

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



   System.out.println("--------------------------------------------------------------");
    JwtUser jwtUser = (JwtUser) auth.getPrincipal();
    
    //Get the username of the logged in user: getPrincipal()
    System.out.println("auth.getPrincipal()=>"+jwtUser.getUsername() );
    //Get the password of the authenticated user: getCredentials()
    System.out.println("auth.getCredentials()=>"+auth.getCredentials());
    //Get the assigned roles of the authenticated user: getAuthorities()
    System.out.println("auth.getAuthorities()=>"+auth.getAuthorities());
    //Get further details of the authenticated user: getDetails()
    System.out.println("auth.getDetails()=>"+auth.getDetails());
    System.out.println("--------------------------------------------------------------");
like image 38
vaquar khan Avatar answered Nov 06 '22 08:11

vaquar khan