Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.jevontech.wabl.security; import com.jevontech.wabl.services.WablConfigurationService; import com.jevontech.wabl.entities.SecurityUser; import io.jsonwebtoken.*; import java.io.UnsupportedEncodingException; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mobile.device.Device; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; @Component public class TokenUtils { private final Logger logger = Logger.getLogger(this.getClass()); private static final String AUDIENCE_UNKNOWN = "unknown"; private static final String AUDIENCE_WEB = "web"; private static final String AUDIENCE_MOBILE = "mobile"; private static final String AUDIENCE_TABLET = "tablet"; private final String SUB = "sub"; private final String CREATED = "created"; private final String AUDIENCE = "audience"; @Autowired WablConfigurationService configurationService; public String getUsernameFromToken(String token) { String username; final Claims claims = this.getClaimsFromToken(token); if (claims != null) { username = claims.getSubject(); } else { username = null; } return username; } public Date getCreatedDateFromToken(String token) { Date created; final Claims claims = this.getClaimsFromToken(token); if (claims != null) { created = new Date((Long) claims.get(this.CREATED)); } else { created = null; } return created; } public Date getExpirationDateFromToken(String token) { Date expiration; final Claims claims = this.getClaimsFromToken(token); if (claims != null) { expiration = claims.getExpiration(); } else { expiration = null; } return expiration; } public String getAudienceFromToken(String token) { String audience; final Claims claims = this.getClaimsFromToken(token); if (claims != null) { audience = (String) claims.get(this.AUDIENCE); } else { audience = null; } return audience; } private Claims getClaimsFromToken(String token) { Claims claims; try { claims = Jwts.parser().setSigningKey(configurationService.getSecret().getBytes("UTF-8")) .parseClaimsJws(token).getBody(); } catch (Exception e) { claims = null; } return claims; } private Date generateCurrentDate() { return new Date(System.currentTimeMillis()); } private Date generateExpirationDate() { long experationTime = configurationService.getExpirationTime() * 1000; return new Date(System.currentTimeMillis() + experationTime); } private Boolean isTokenExpired(String token) { final Date expiration = this.getExpirationDateFromToken(token); return expiration.before(this.generateCurrentDate()); } private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) { return (lastPasswordReset != null && created.before(lastPasswordReset)); } private String generateAudience(Device device) { String audience = this.AUDIENCE_UNKNOWN; if (device.isNormal()) { audience = this.AUDIENCE_WEB; } else if (device.isTablet()) { audience = AUDIENCE_TABLET; } else if (device.isMobile()) { audience = AUDIENCE_MOBILE; } return audience; } private Boolean ignoreTokenExpiration(String token) { String audience = this.getAudienceFromToken(token); return (this.AUDIENCE_TABLET.equals(audience) || this.AUDIENCE_MOBILE.equals(audience)); } public String generateToken(UserDetails userDetails, Device device) { Map<String, Object> claims = new HashMap<String, Object>(); claims.put(this.SUB, userDetails.getUsername()); claims.put(this.AUDIENCE, this.generateAudience(device)); claims.put(this.CREATED, this.generateCurrentDate()); return this.generateToken(claims); } private String generateToken(Map<String, Object> claims) { try { return Jwts.builder().setClaims(claims).setExpiration(this.generateExpirationDate()) .signWith(SignatureAlgorithm.HS512, configurationService.getSecret().getBytes("UTF-8")) .compact(); } catch (UnsupportedEncodingException ex) { //didn't want to have this method throw the exception, would rather log it and sign the token like it was before logger.warn(ex.getMessage()); return Jwts.builder().setClaims(claims).setExpiration(this.generateExpirationDate()) .signWith(SignatureAlgorithm.HS512, configurationService.getSecret()).compact(); } } public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) { final Date created = this.getCreatedDateFromToken(token); return (!(this.isCreatedBeforeLastPasswordReset(created, lastPasswordReset)) && (!(this.isTokenExpired(token)) || this.ignoreTokenExpiration(token))); } public String refreshToken(String token) { String refreshedToken; final Claims claims = this.getClaimsFromToken(token); if (claims != null) { claims.put(this.CREATED, this.generateCurrentDate()); refreshedToken = this.generateToken(claims); } else { refreshedToken = null; } return refreshedToken; } public Boolean validateToken(String token, UserDetails userDetails) { SecurityUser user = (SecurityUser) userDetails; final String username = this.getUsernameFromToken(token); final Date created = this.getCreatedDateFromToken(token); final Date expiration = this.getExpirationDateFromToken(token); boolean userNameValid = false; if (username != null) { userNameValid = username.equals(user.getUsername()); } return (userNameValid && !(this.isTokenExpired(token)) && !(this.isCreatedBeforeLastPasswordReset(created, user.getLastPasswordReset()))); } }