@Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { RawAccessJwtToken rawAccessToken = (RawAccessJwtToken) authentication.getCredentials(); Jws<Claims> jwsClaims = rawAccessToken.parseClaims(jwtSettings.getTokenSigningKey()); String orgId = jwsClaims.getBody().getSubject(); String tenantId = jwsClaims.getBody().get("tenant", String.class); List<String> scopes = jwsClaims.getBody().get("scopes", List.class); List<GrantedAuthority> authorities = scopes.stream() .map(authority -> new SimpleGrantedAuthority(authority)) .collect(Collectors.toList()); UserContext context = UserContext.create(tenantId, orgId, authorities); return new JwtAuthenticationToken(context, context.getAuthorities()); }
public String getAuthenticationFromToken(final String base64EncodedToken) throws JwtException { // The library representations of the JWT should be kept internal to this service. try { final Jws<Claims> jws = parseTokenFromBase64EncodedString(base64EncodedToken); if (jws == null) { throw new JwtException("Unable to parse token"); } // Additional validation that subject is present if (StringUtils.isEmpty(jws.getBody().getSubject())) { throw new JwtException("No subject available in token"); } // TODO: Validate issuer against active IdentityProvider? if (StringUtils.isEmpty(jws.getBody().getIssuer())) { throw new JwtException("No issuer available in token"); } return jws.getBody().getSubject(); } catch (JwtException e) { logger.debug("The Base64 encoded JWT: " + base64EncodedToken); final String errorMessage = "There was an error validating the JWT"; logger.error(errorMessage, e); throw e; } }
private Jws<Claims> parseTokenFromBase64EncodedString(final String base64EncodedToken) throws JwtException { try { return Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter() { @Override public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) { final String identity = claims.getSubject(); // Get the key based on the key id in the claims final String keyId = claims.get(KEY_ID_CLAIM, String.class); final Key key = keyService.getKey(keyId); // Ensure we were able to find a key that was previously issued by this key service for this user if (key == null || key.getKey() == null) { throw new UnsupportedJwtException("Unable to determine signing key for " + identity + " [kid: " + keyId + "]"); } return key.getKey().getBytes(StandardCharsets.UTF_8); } }).parseClaimsJws(base64EncodedToken); } catch (final MalformedJwtException | UnsupportedJwtException | SignatureException | ExpiredJwtException | IllegalArgumentException e) { // TODO: Exercise all exceptions to ensure none leak key material to logs final String errorMessage = "Unable to validate the access token."; throw new JwtException(errorMessage, e); } }
public SecurityUser parseRefreshToken(RawAccessJwtToken rawAccessToken) { Jws<Claims> jwsClaims = rawAccessToken.parseClaims(settings.getTokenSigningKey()); Claims claims = jwsClaims.getBody(); String subject = claims.getSubject(); List<String> scopes = claims.get(SCOPES, List.class); if (scopes == null || scopes.isEmpty()) { throw new IllegalArgumentException("Refresh Token doesn't have any scopes"); } if (!scopes.get(0).equals(Authority.REFRESH_TOKEN.name())) { throw new IllegalArgumentException("Invalid Refresh Token scope"); } boolean isPublic = claims.get(IS_PUBLIC, Boolean.class); UserPrincipal principal = new UserPrincipal(isPublic ? UserPrincipal.Type.PUBLIC_ID : UserPrincipal.Type.USER_NAME, subject); SecurityUser securityUser = new SecurityUser(new UserId(UUID.fromString(claims.get(USER_ID, String.class)))); securityUser.setUserPrincipal(principal); return securityUser; }
@Test public void loginSuccessfullAdmin() throws Exception { final UserLoginDto user = new UserLoginDto("admin", "admin"); final MvcResult result = mockMvc.perform(post(PREFIX + "/login") .contentType(contentType).content(this.json(user))) .andExpect(status().isOk()) .andExpect(content().contentType(contentType)) .andExpect(jsonPath("token").exists()) .andReturn(); final String body = result.getResponse().getContentAsString(); final ObjectMapper mapper = new ObjectMapper(); final JsonNode node = mapper.readTree(body); final String token = node.get("token").asText(); log.debug("Token: " + token); final Jws<Claims> claims = Jwts.parser() .setSigningKey(TEST_KEY) .parseClaimsJws(token); assertEquals("admin", claims.getBody().getSubject()); }
@Test public void loginSuccessfullUser() throws Exception { final UserLoginDto user = new UserLoginDto("user", "user"); final MvcResult result = mockMvc.perform(post(PREFIX + "/login") .contentType(contentType).content(this.json(user))) .andExpect(status().isOk()) .andExpect(content().contentType(contentType)) .andExpect(jsonPath("token").exists()) .andReturn(); final String body = result.getResponse().getContentAsString(); final ObjectMapper mapper = new ObjectMapper(); final JsonNode node = mapper.readTree(body); final String token = node.get("token").asText(); log.debug("Token: " + token); final Jws<Claims> claims = Jwts.parser() .setSigningKey(TEST_KEY) .parseClaimsJws(token); assertEquals("user", claims.getBody().getSubject()); }
@Override public Authentication authenticate(final HttpServletRequest request) { final String token = request.getHeader(authHeaderName); final Optional<Jws<Claims>> tokenData = parseToken(token); if (tokenData.isPresent()) { try { final User user = getUserFromToken(tokenData.get()); return new UserAuthentication(user); } catch (UserNotFoundException e) { log.warn(e.getMessage()); } } return null; }
@Override public void authenticate(final JsonObject authRequest, final Handler<AsyncResult<HonoUser>> authenticationResultHandler) { final DeliveryOptions options = new DeliveryOptions().setSendTimeout(AUTH_REQUEST_TIMEOUT_MILLIS); vertx.eventBus().send(AuthenticationConstants.EVENT_BUS_ADDRESS_AUTHENTICATION_IN, authRequest, options, reply -> { if (reply.succeeded()) { JsonObject result = (JsonObject) reply.result().body(); String token = result.getString(AuthenticationConstants.FIELD_TOKEN); log.debug("received token [length: {}] in response to authentication request", token.length()); try { Jws<Claims> expandedToken = tokenValidator.expand(result.getString(AuthenticationConstants.FIELD_TOKEN)); authenticationResultHandler.handle(Future.succeededFuture(new HonoUserImpl(expandedToken, token))); } catch (JwtException e) { authenticationResultHandler.handle(Future.failedFuture(e)); } } else { authenticationResultHandler.handle(Future.failedFuture(reply.cause())); } }); }
public PortalRequest parsePortalRequest(String portalRequestToken) { final Jws<Claims> claims = parseEncrypteToken(portalRequestToken, PortalRequest.class); final String username = claims.getBody().getSubject(); // Properties @SuppressWarnings("unchecked") final Map<String,String> properties = (Map<String, String>) claims.getBody().get(JwtClaims.PROPERTIES.getName()); // Attributes @SuppressWarnings("unchecked") final Map<String,List<String>> attributes = (Map<String, List<String>>) claims.getBody().get(JwtClaims.ATTRIBUTES.getName()); // Parameters @SuppressWarnings("unchecked") final Map<String,List<String>> parameters = (Map<String, List<String>>) claims.getBody().get(JwtClaims.PARAMETERS.getName()); PortalRequest rslt = new PortalRequest(portalRequestToken, properties, attributes, parameters); logger.debug("Produced the following PortalRequest for user '{}': {}", username, rslt); return rslt; }
/** * {@inheritDoc} */ @Override public boolean verifyJwt(String jwt) { boolean verified = false; try { Assert.hasText(jwt, "JWT can't be null or empty!!"); JwtParser jwtParser = Jwts.parser().requireIssuer(this.jwtConfig.issuer()); this.setSigningKey(jwtParser); Jws<Claims> claimsJws = jwtParser.parseClaimsJws(jwt); verified = !this.jwtConfig.validateClaims() || this.claimsValidator != null && this.claimsValidator.validate(claimsJws.getBody()); } catch (RuntimeException ex) { // For reducing noise in the logs, set this config to false. if (this.jwtConfig.printJwtExceptionTrace()) { LOGGER.error(ex.getMessage(), ex); } else { LOGGER.error(ex.getMessage()); } } return verified; }
public JwtAuthenticationToken tokenFromStringJwt(String rawJwt) { DefaultJwtParser parser = ((DefaultJwtParser) Jwts.parser()); parser.setSigningKey(signingSecret); try { Jws<Claims> jws = parser.parseClaimsJws(rawJwt); Claims claims = jws.getBody(); UUID userId = UUID.fromString((String) claims.get("user_id")); String email = ((String) claims.get("email")); Collection<? extends GrantedAuthority> roles = parseRolesFromClaims(claims); return new JwtAuthenticationToken(userId, email, roles); } catch (Exception e) { log.info(String.format("Exception occurred parsing JWT [%s].\nException message: %s", rawJwt, e.getMessage())); return null; } }
/** * {@inheritDoc} */ @Override public Jws<Claims> parse(String token, Asymmetric issuer) { Jws<Claims> jws; try { Jwk jwk = jwkProvider.get(issuer.getKID()); byte[] publicKeyBytes = jwk.getPublicKey().getEncoded(); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey pubKey = keyFactory.generatePublic(keySpec); jws = Jwts.parser() .setAllowedClockSkewSeconds(issuer.getSkewSeconds()) .setSigningKey(pubKey) .parseClaimsJws(token); return jws; } catch (Exception e) { LOGGER.error(e.getMessage(), e); throw new InvalidTokenException(e.getMessage()); } }
@SuppressWarnings("unchecked") public boolean hasValidSessionCookie() { decrypt(); boolean valid = false; if (StringUtils.isNotBlank(this.value)) { try { Jws<Claims> jwsClaims = Jwts.parser() .setSigningKey(this.secret) .parseClaimsJws(this.value); Claims claims = jwsClaims.getBody(); Date expiration = claims.getExpiration(); if (expiration != null) { this.sessionValues = claims.get(ClaimKey.DATA.toString(), Map.class); this.authenticityToken = claims.get(ClaimKey.AUTHENTICITY.toString(), String.class); this.expiresDate = dateToLocalDateTime(expiration); valid = true; } } catch (Exception e) { //NOSONAR LOG.error("Failed to parse JWS for seesion cookie", e); } } return valid; }
public boolean hasValidAuthenticationCookie() { decrypt(); boolean valid = false; if (StringUtils.isNotBlank(this.value)) { try { Jws<Claims> jwsClaims = Jwts.parser() .setSigningKey(this.secret) .parseClaimsJws(this.value); Claims claims = jwsClaims.getBody(); Date expiration = claims.getExpiration(); if (expiration != null) { this.authenticatedUser = claims.getSubject(); this.twoFactor = claims.get(ClaimKey.TWO_FACTOR.toString(), Boolean.class); this.expiresDate = dateToLocalDateTime(expiration); valid = true; } } catch (Exception e) { //NOSONAR LOG.error("Failed to parse JWS for authentication cookie", e); } } return valid; }
private Authentication toAuthentication(String token) throws AuthenticationException { if (token == null || settings.isDemoMode()) { return null; } int pos = token.startsWith(BEARER_) ? BEARER_.length() : 0; try { Jws<Claims> claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token.substring(pos)); return new PreAuthenticatedAuthenticationToken( Long.valueOf(claims.getBody().getSubject()), WebappCredentials.builder() .externalId(claims.getBody().getId()) .customerName(claims.getBody().get(JWT_CLAIM_CUSTOMER_NAME, String.class)) .email(claims.getBody().get(JWT_CLAIM_EMAIL, String.class)) .source(claims.getBody().get(JWT_CLAIM_SOURCE, String.class)) .build(), USER_AUTHORITY); } catch (Exception e) { logger.debug("Failed to authenticate token: " + e); return null; } }
@Override public Authentication authenticate(final HttpServletRequest request) { final String token = request.getHeader(SecurityConstants.AUTH_HEADER_NAME); final Jws<Claims> tokenData = parseToken(token); if (tokenData != null) { User user = getUserFromToken(tokenData); if (user != null) { return new UserAuthentication(user); } } return null; }
private Jws<Claims> parseToken(final String token) { if (token != null) { try { return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); } catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException e) { return null; } } return null; }
private User getUserFromToken(final Jws<Claims> tokenData) { try { return (User) userDetailsService .loadUserByUsername(tokenData.getBody().get("username").toString()); } catch (UsernameNotFoundException e) { throw new UserNotFoundException("User " + tokenData.getBody().get("username").toString() + " not found"); } }
/** * Parses and validates JWT Token signature. * * @throws BadCredentialsException * @throws JwtExpiredTokenException * */ public Jws<Claims> parseClaims(String signingKey) { try { return Jwts.parser().setSigningKey(signingKey).parseClaimsJws(this.token); } catch (UnsupportedJwtException | MalformedJwtException | IllegalArgumentException | SignatureException ex) { logger.error("Invalid JWT Token", ex); throw new BadCredentialsException("Invalid JWT token: ", ex); } catch (ExpiredJwtException expiredEx) { logger.info("JWT Token is expired", expiredEx); throw new JwtExpiredTokenException(this, "JWT Token expired", expiredEx); } }
/** * Creates and validates Refresh token * * @param token * @param signingKey * * @throws BadCredentialsException * @throws JwtExpiredTokenException * * @return */ public static Optional<RefreshToken> create(RawAccessJwtToken token, String signingKey) { Jws<Claims> claims = token.parseClaims(signingKey); List<String> scopes = claims.getBody().get("scopes", List.class); if (scopes == null || scopes.isEmpty() || !scopes.stream().filter(scope -> Scopes.REFRESH_TOKEN.authority().equals(scope)).findFirst().isPresent()) { return Optional.empty(); } return Optional.of(new RefreshToken(claims)); }
private Authentication parseToken(final String token) { final Jws<Claims> tokenData = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); final Authentication jwtAuth = getAuthenticationFromToken(tokenData); if (Objects.isNull(jwtAuth)) { return null; } return validatePasswordFromToken(tokenData, jwtAuth); }
private Authentication validatePasswordFromToken(final Jws<Claims> tokenData, final Authentication jwtAuth) { final String tokenPassword = tokenData.getBody().get("password").toString(); if(tokenPassword.equals(jwtAuth.getCredentials())) { jwtAuth.setAuthenticated(true); return jwtAuth; } return null; }
private String modifyTokenExpirationTime(final String token) { final Jws<Claims> tokenData = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); final JwtBuilder jwtBuilder = Jwts.builder(); final Calendar calendar = Calendar.getInstance(); jwtBuilder.setClaims(tokenData.getBody()); calendar.add(Calendar.MILLISECOND, 1); jwtBuilder.setExpiration(calendar.getTime()); return jwtBuilder.signWith(SignatureAlgorithm.HS512, secretKey).compact(); }
private void validateTokenData(final String token, final User user) { final Jws<Claims> tokenData = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); final String username = tokenData.getBody().get("username").toString(); final String password = tokenData.getBody().get("password").toString(); final User userFromToken = userService.findByUsername(username); assertEquals(user.getUsername(), userFromToken.getUsername()); assertEquals(user.getPassword(), password); }
@Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { RawAccessJwtToken rawAccessToken = (RawAccessJwtToken) authentication.getCredentials(); Jws<Claims> jwsClaims = rawAccessToken.parseClaims(AppConfig.prop.getProperty("security.tokenSigningKey")); String subject = jwsClaims.getBody().getSubject(); List<String> scopes = jwsClaims.getBody().get("scopes", List.class); List<GrantedAuthority> authorities = scopes.stream() .map(authority -> new SimpleGrantedAuthority(authority)) .collect(Collectors.toList()); UserContext context = UserContext.create(subject, authorities); return new JwtAuthenticationToken(context, context.getAuthorities()); }
String[] getPrincipalsAndCredentials(String authorizeParam) { Jws<Claims> claims = Jwts.parser() .setSigningKey(TokenRepository.SECURET.getBytes()) .parseClaimsJws(authorizeParam); String email = claims.getBody().getSubject(); return new String[]{email, authorizeParam}; }
public SecurityUser parseAccessJwtToken(RawAccessJwtToken rawAccessToken) { Jws<Claims> jwsClaims = rawAccessToken.parseClaims(settings.getTokenSigningKey()); Claims claims = jwsClaims.getBody(); String subject = claims.getSubject(); List<String> scopes = claims.get(SCOPES, List.class); if (scopes == null || scopes.isEmpty()) { throw new IllegalArgumentException("JWT Token doesn't have any scopes"); } SecurityUser securityUser = new SecurityUser(new UserId(UUID.fromString(claims.get(USER_ID, String.class)))); securityUser.setEmail(subject); securityUser.setAuthority(Authority.parse(scopes.get(0))); securityUser.setFirstName(claims.get(FIRST_NAME, String.class)); securityUser.setLastName(claims.get(LAST_NAME, String.class)); securityUser.setEnabled(claims.get(ENABLED, Boolean.class)); boolean isPublic = claims.get(IS_PUBLIC, Boolean.class); UserPrincipal principal = new UserPrincipal(isPublic ? UserPrincipal.Type.PUBLIC_ID : UserPrincipal.Type.USER_NAME, subject); securityUser.setUserPrincipal(principal); String tenantId = claims.get(TENANT_ID, String.class); if (tenantId != null) { securityUser.setTenantId(new TenantId(UUID.fromString(tenantId))); } String customerId = claims.get(CUSTOMER_ID, String.class); if (customerId != null) { securityUser.setCustomerId(new CustomerId(UUID.fromString(customerId))); } return securityUser; }
@Produces public User getUser() { String authHeader = req.getHeader(HttpHeaders.AUTHORIZATION); if (authHeader != null && authHeader.contains("Bearer")) { String token = authHeader.substring("Bearer".length()).trim(); Jws<Claims> parseClaimsJws = Jwts.parser().setSigningKey(keyGenerator.getKey()).parseClaimsJws(token); return getUser(parseClaimsJws.getBody().getSubject()); } else { return null; } }
@Override public Authentication authenticate(final Authentication authentication) { final JwtAuthenticationToken authRequest = (JwtAuthenticationToken) authentication; final Jws<Claims> claimsJws = parserAndVerify(authRequest); if (claimsJws.getBody().getExpiration() == null) { throw new BadCredentialsException("Only temporary JWT supported"); } final String username = claimsJws.getBody().getSubject(); final UserDetails userDetails; try { userDetails = userDetailsService.loadUserByUsername(username); } catch (final UsernameNotFoundException notFound) { throw new BadCredentialsException("Bad credentials"); } if (!userDetails.isAccountNonLocked()) { throw new LockedException("User account is locked"); } if (!userDetails.isEnabled()) { throw new DisabledException("User is disabled"); } if (!userDetails.isAccountNonExpired()) { throw new AccountExpiredException("User account has expired"); } if (!userDetails.isCredentialsNonExpired()) { throw new CredentialsExpiredException("User credentials have expired"); } LOG.info("Successful JWT authentication for username={}", userDetails.getUsername()); return JwtAuthenticationToken.createAuthenticated(userDetails, authRequest.getDetails()); }
private Optional<Jws<Claims>> parseToken(final String token) { Optional<Jws<Claims>> result = Optional.empty(); if (Objects.nonNull(token)) { try { result = Optional.ofNullable(Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token)); } catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException e) { log.warn(e.getMessage()); } } return result; }
@Test public void Can_parse_a_jwt_token() throws IOException { final String token = someString(); final Class<Object> type = Object.class; final JwtParser parser = mock(JwtParser.class); final JwtParser secretParser = mock(JwtParser.class); @SuppressWarnings("unchecked") final Jws<Claims> jws = mock(Jws.class); final Claims claims = mock(Claims.class); final Map map = mock(Map.class); final Object expected = new Object(); // Given given(parserFactory.create()).willReturn(parser); given(parser.setSigningKey(publicKey)).willReturn(secretParser); given(secretParser.parseClaimsJws(token)).willReturn(jws); given(jws.getBody()).willReturn(claims); given(claims.get(PRINCIPAL, Map.class)).willReturn(map); given(objectMapper.convertValue(map, type)).willReturn(expected); // When final Object actual = decryptor.decrypt(token, type); // Then assertThat(actual, is(expected)); }
@Override public Jws<Claims> expand(final String token) { Objects.requireNonNull(token); return Jwts.parser() .setSigningKey(key) .parseClaimsJws(token); }
/** * Creates a new device for a token. * <p> * The token is expected to contain the device identifier in the <em>sub</em> claim and * the tenant identifier in the <em>ten</em> claim. * * @param token The token asserting the device's identity. * @throws NullPointerException if the token does not contain a tenant and device identifier. */ public Device(final Jws<Claims> token) { this(Objects.requireNonNull(token).getBody().get("ten", String.class), token.getBody().getSubject()); try { Set<?> aut = token.getBody().get("aut", Set.class); if (aut != null) { authorities.addAll(aut); } } catch (RequiredTypeException e) { // token contains no authorities claim } }
private HonoUserImpl(final Jws<Claims> expandedToken, final String token) { Objects.requireNonNull(expandedToken); Objects.requireNonNull(token); if (expandedToken.getBody() == null) { throw new IllegalArgumentException("token has no claims"); } this.token = token; this.expandedToken = expandedToken; this.authorities = AuthoritiesImpl.from(expandedToken.getBody()); }
@Test public void testCreateAndExpandToken() { Authorities authorities = new AuthoritiesImpl() .addResource("telemetry", "*", Activity.READ, Activity.WRITE) .addOperation("registration", "*", "assert"); String token = helper.createToken("userA", authorities); Jws<Claims> parsedToken = helper.expand(token); assertNotNull(parsedToken.getBody()); }