@Test public void refresh_token_generate_a_new_hash() { setSecretKey(A_SECRET_KEY); underTest.start(); String token = underTest.encode(new JwtSession(USER_LOGIN, 30)); Optional<Claims> claims = underTest.decode(token); String newToken = underTest.refresh(claims.get(), 45); assertThat(newToken).isNotEqualTo(token); }
String encode(JwtSession jwtSession) { checkIsStarted(); long now = system2.now(); JwtBuilder jwtBuilder = Jwts.builder() .setId(uuidFactory.create()) .setSubject(jwtSession.getUserLogin()) .setIssuedAt(new Date(now)) .setExpiration(new Date(now + jwtSession.getExpirationTimeInSeconds() * 1000)) .signWith(SIGNATURE_ALGORITHM, secretKey); for (Map.Entry<String, Object> entry : jwtSession.getProperties().entrySet()) { jwtBuilder.claim(entry.getKey(), entry.getValue()); } return jwtBuilder.compact(); }
@Override public void start() { Optional<String> encodedKey = config.get(AUTH_JWT_SECRET.getKey()); if (encodedKey.isPresent()) { this.secretKey = decodeSecretKeyProperty(encodedKey.get()); } else { this.secretKey = generateSecretKey(); } }
@Test public void generate_new_secret_key_if_not_set_by_settings() { assertThat(underTest.getSecretKey()).isNull(); underTest.start(); assertThat(underTest.getSecretKey()).isNotNull(); assertThat(underTest.getSecretKey().getAlgorithm()).isEqualTo(SignatureAlgorithm.HS256.getJcaName()); }
@Test public void generate_token_with_property() { setSecretKey(A_SECRET_KEY); underTest.start(); String token = underTest.encode(new JwtSession(USER_LOGIN, 10, ImmutableMap.of("custom", "property"))); assertThat(token).isNotEmpty(); Claims claims = underTest.decode(token).get(); assertThat(claims.get("custom")).isEqualTo("property"); }
@Test public void validate_token_refresh_session_when_refresh_time_is_reached() { UserDto user = db.users().insertUser(); addJwtCookie(); // Token was created 10 days ago and refreshed 6 minutes ago Claims claims = createToken(user.getUuid(), TEN_DAYS_AGO); claims.put("lastRefreshTime", SIX_MINUTES_AGO); when(jwtSerializer.decode(JWT_TOKEN)).thenReturn(Optional.of(claims)); assertThat(underTest.validateToken(request, response).isPresent()).isTrue(); verify(jwtSerializer).refresh(any(Claims.class), eq(3 * 24 * 60 * 60)); }
@Test public void return_no_token_when_expiration_date_is_reached() { setSecretKey(A_SECRET_KEY); underTest.start(); String token = Jwts.builder() .setId("123") .setIssuedAt(new Date(system2.now())) .setExpiration(new Date(system2.now())) .signWith(SignatureAlgorithm.HS256, decodeSecretKey(A_SECRET_KEY)) .compact(); assertThat(underTest.decode(token)).isEmpty(); }
public void generateToken(UserDto user, Map<String, Object> properties, HttpServletRequest request, HttpServletResponse response) { String csrfState = jwtCsrfVerifier.generateState(request, response, sessionTimeoutInSeconds); String token = jwtSerializer.encode(new JwtSerializer.JwtSession( user.getUuid(), sessionTimeoutInSeconds, ImmutableMap.<String, Object>builder() .putAll(properties) .put(LAST_REFRESH_TIME_PARAM, system2.now()) .put(CSRF_JWT_PARAM, csrfState) .build())); response.addCookie(createCookie(request, JWT_COOKIE, token, sessionTimeoutInSeconds)); }
@Test public void refresh_token() { setSecretKey(A_SECRET_KEY); underTest.start(); Date now = new Date(); Date createdAt = DateUtils.parseDate("2016-01-01"); // Expired in 10 minutes Date expiredAt = new Date(now.getTime() + 10 * 60 * 1000); Claims token = new DefaultClaims() .setId("id") .setSubject("subject") .setIssuer("sonarqube") .setIssuedAt(createdAt) .setExpiration(expiredAt); token.put("key", "value"); // Refresh the token with a higher expiration time String encodedToken = underTest.refresh(token, 20 * 60); Claims result = underTest.decode(encodedToken).get(); assertThat(result.getId()).isEqualTo("id"); assertThat(result.getSubject()).isEqualTo("subject"); assertThat(result.getIssuer()).isEqualTo("sonarqube"); assertThat(result.getIssuedAt()).isEqualTo(createdAt); assertThat(result.get("key")).isEqualTo("value"); // Expiration date has been changed assertThat(result.getExpiration()).isNotEqualTo(expiredAt) .isAfterOrEqualsTo(new Date(now.getTime() + 19 * 1000)); }
private Optional<Token> validateToken(String tokenEncoded, HttpServletRequest request, HttpServletResponse response) { Optional<Claims> claims = jwtSerializer.decode(tokenEncoded); if (!claims.isPresent()) { return Optional.empty(); } Date now = new Date(system2.now()); Claims token = claims.get(); if (now.after(addSeconds(token.getIssuedAt(), SESSION_DISCONNECT_IN_SECONDS))) { return Optional.empty(); } jwtCsrfVerifier.verifyState(request, (String) token.get(CSRF_JWT_PARAM), token.getSubject()); if (now.after(addSeconds(getLastRefreshDate(token), SESSION_REFRESH_IN_SECONDS))) { refreshToken(token, request, response); } Optional<UserDto> user = selectUserFromUuid(token.getSubject()); if (!user.isPresent()) { return Optional.empty(); } return Optional.of(new Token(user.get(), claims.get())); }
@Test public void validate_token() { UserDto user = db.users().insertUser(); addJwtCookie(); Claims claims = createToken(user.getUuid(), NOW); when(jwtSerializer.decode(JWT_TOKEN)).thenReturn(Optional.of(claims)); assertThat(underTest.validateToken(request, response).isPresent()).isTrue(); verify(jwtSerializer, never()).encode(any(JwtSerializer.JwtSession.class)); }
private void refreshToken(Claims token, HttpServletRequest request, HttpServletResponse response) { String refreshToken = jwtSerializer.refresh(token, sessionTimeoutInSeconds); response.addCookie(createCookie(request, JWT_COOKIE, refreshToken, sessionTimeoutInSeconds)); jwtCsrfVerifier.refreshState(request, response, (String) token.get(CSRF_JWT_PARAM), sessionTimeoutInSeconds); }
@Test public void load_secret_key_from_settings() { setSecretKey(A_SECRET_KEY); underTest.start(); assertThat(settings.getString("sonar.auth.jwtBase64Hs256Secret")).isEqualTo(A_SECRET_KEY); }
@Test public void generate_token_with_expiration_date() { setSecretKey(A_SECRET_KEY); underTest.start(); Date now = new Date(); long expirationTimeInSeconds = 10L; String token = underTest.encode(new JwtSession(USER_LOGIN, expirationTimeInSeconds)); assertThat(token).isNotEmpty(); Claims claims = underTest.decode(token).get(); assertThat(claims.getExpiration().getTime()).isGreaterThanOrEqualTo(now.getTime() + expirationTimeInSeconds * 1000L - 1000L); }
@Test public void validate_token_does_not_refresh_session_when_refresh_time_is_not_reached() { UserDto user = db.users().insertUser(); addJwtCookie(); // Token was created 10 days ago and refreshed 4 minutes ago Claims claims = createToken(user.getUuid(), TEN_DAYS_AGO); claims.put("lastRefreshTime", FOUR_MINUTES_AGO); when(jwtSerializer.decode(JWT_TOKEN)).thenReturn(Optional.of(claims)); assertThat(underTest.validateToken(request, response).isPresent()).isTrue(); verify(jwtSerializer, never()).refresh(any(Claims.class), anyInt()); }
@Test public void return_no_token_when_secret_key_has_changed() { setSecretKey(A_SECRET_KEY); underTest.start(); String token = Jwts.builder() .setId("123") .setSubject(USER_LOGIN) .setIssuedAt(new Date(system2.now())) .setExpiration(new Date(system2.now() + 20 * 60 * 1000)) .signWith(SignatureAlgorithm.HS256, decodeSecretKey("LyWgHktP0FuHB2K+kMs3KWMCJyFHVZDdDSqpIxAMVaQ=")) .compact(); assertThat(underTest.decode(token)).isEmpty(); }
@Before public void setUp() throws Exception { when(system2.now()).thenReturn(NOW); when(request.getSession()).thenReturn(httpSession); when(jwtSerializer.encode(any(JwtSerializer.JwtSession.class))).thenReturn(JWT_TOKEN); when(jwtCsrfVerifier.generateState(eq(request), eq(response), anyInt())).thenReturn(CSRF_STATE); }
@Test public void validate_token_does_not_refresh_session_when_token_is_no_more_valid() { addJwtCookie(); when(jwtSerializer.decode(JWT_TOKEN)).thenReturn(Optional.empty()); assertThat(underTest.validateToken(request, response).isPresent()).isFalse(); }
@Test public void refresh_fail_when_not_started() { expectedException.expect(NullPointerException.class); expectedException.expectMessage("org.sonar.server.authentication.JwtSerializer not started"); underTest.refresh(new DefaultClaims(), 10); }