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: butitoy@iyotbihagay.com; 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 butitoy@iyotbihagay.com
Solution:
Since I only want to get the username/email (butitoy@iyotbihagay.com), 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]: butitoy@iyotbihagay.com
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: butitoy@iyotbihagay.com; 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 "butitoy@iyotbihagay.com".
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;
}
}