package com.thinkbiganalytics.auth.jwt;
/*-
* #%L
* thinkbig-security-auth
* %%
* Copyright (C) 2017 ThinkBig Analytics
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import com.thinkbiganalytics.auth.config.JwtProperties;
import org.joda.time.DateTimeUtils;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.rememberme.InvalidCookieException;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JwtRememberMeServicesTest {
/**
* The JWT Remember Me service to be tested
*/
private JwtRememberMeServices service;
/**
* Create service and setup environment for tests
*/
@Before
public void setUp() {
DateTimeUtils.setCurrentMillisFixed(1461942300000L);
final JwtProperties properties = new JwtProperties();
properties.setAlgorithm(AlgorithmIdentifiers.HMAC_SHA256);
properties.setKey("https://www.thinkbiganalytics.com/");
service = new JwtRememberMeServices(properties);
}
/**
* Reset date/time after tests.
*/
@After
public void tearDown() {
DateTimeUtils.setCurrentMillisSystem();
}
/**
* Verifies token deserialization.
*/
@Test
public void decodeCookie() {
// Test with no groups
String[] actual = service.decodeCookie("eyJhbGciOiJIUzI1NiIsImtpZCI6IkhNQUMifQ.eyJleHAiOjE0NjMxNTE5MDAsInN1YiI6InVzZXIiLCJncm91cHMiOltdfQ.NKAD4m4bn1eDMGA9HSihOsLwrSUcDhBYfXIL7uJPWdo");
String[] expected = new String[]{"user"};
Assert.assertArrayEquals(expected, actual);
// Test with one group
actual = service.decodeCookie("eyJhbGciOiJIUzI1NiIsImtpZCI6IkhNQUMifQ.eyJleHAiOjE0NjMxNTE5MDAsInN1YiI6ImRsYWRtaW4iLCJncm91cHMiOlsiYWRtaW4iXX0."
+ "3RX9hsmfNA1rtWMs309N5MV5_gd4FUtU_odFIIOqsoY");
expected = new String[]{"dladmin", "admin"};
Assert.assertArrayEquals(expected, actual);
// Test with multiple groups
actual = service.decodeCookie("eyJhbGciOiJIUzI1NiIsImtpZCI6IkhNQUMifQ.eyJleHAiOjE0NjMxNTE5MDAsInN1YiI6ImRsYWRtaW4iLCJncm91cHMiOlsiZGVzaWduZXJzIiwib3BlcmF0b3JzIl19."
+ "fRxn00QbHAjL-R0DI1DmYfLEi3F7eMb3V2vTvgcFOy8");
expected = new String[]{"dladmin", "designers", "operators"};
Assert.assertArrayEquals(expected, actual);
}
/**
* Verify exception if subject is blank.
*/
@Test(expected = InvalidCookieException.class)
public void decodeCookieWithBlankSubject() {
service.decodeCookie("eyJhbGciOiJIUzI1NiIsImtpZCI6IkhNQUMifQ.eyJleHAiOjE0NjMxNTE5MDAsInN1YiI6IiIsImdyb3VwcyI6W119.TZlPnjJgAW5oP9DztgE9r10rZhMv0GAnhlbGhRiMtmA");
}
/**
* Verify exception if token is expired.
*/
@Test(expected = InvalidCookieException.class)
public void decodeCookieWithExpired() {
service.setTokenValiditySeconds(JwtRememberMeServices.TWO_WEEKS_S);
service.decodeCookie("eyJhbGciOiJIUzI1NiIsImtpZCI6IkhNQUMifQ.eyJleHAiOjE0NjE5NDIzMDAsInN1YiI6ImRsYWRtaW4iLCJncm91cHMiOlsiYWRtaW4iXX0.AsXMAoAM1EPAw5mk4YHNXWsB9H8-lVf4JrQ6K9zHIfw");
}
/**
* Verify exception if token signature is invalid.
*/
@Test(expected = InvalidCookieException.class)
public void decodeCookieWithInvalid() {
service.decodeCookie("eyJhbGciOiJIUzI1NiIsImtpZCI6IkhNQUMifQ.eyJleHAiOjE0NjMxNTE5MDAsInN1YiI6IiIsImdyb3VwcyI6W119.L_00dw3cpWbxw32Pddj6Jq1xeFqPf8ZFdPWAUdmj39k");
}
/**
* Verify exception if subject is missing.
*/
@Test(expected = InvalidCookieException.class)
public void decodeCookieWithMissingSubject() {
service.decodeCookie("eyJhbGciOiJIUzI1NiIsImtpZCI6IkhNQUMifQ.eyJleHAiOjE0NjMxNTE5MDB9.L_00dw3cpWbxw32Pddj6Jq1xeFqPf8ZFdPWAUdmj39k");
}
/**
* Verifies token serialization.
*/
@Test
public void encodeCookie() {
// Test with no groups
String actual = service.encodeCookie(new String[]{"user"});
String expected = "eyJhbGciOiJIUzI1NiIsImtpZCI6IkhNQUMifQ.eyJleHAiOjE0NjMxNTE5MDAsInN1YiI6InVzZXIiLCJncm91cHMiOltdfQ.NKAD4m4bn1eDMGA9HSihOsLwrSUcDhBYfXIL7uJPWdo";
Assert.assertEquals(expected, actual);
// Test with one group
actual = service.encodeCookie(new String[]{"dladmin", "admin"});
expected = "eyJhbGciOiJIUzI1NiIsImtpZCI6IkhNQUMifQ.eyJleHAiOjE0NjMxNTE5MDAsInN1YiI6ImRsYWRtaW4iLCJncm91cHMiOlsiYWRtaW4iXX0.3RX9hsmfNA1rtWMs309N5MV5_gd4FUtU_odFIIOqsoY";
Assert.assertEquals(expected, actual);
// Test with multiple groups
actual = service.encodeCookie(new String[]{"dladmin", "designers", "operators"});
expected = "eyJhbGciOiJIUzI1NiIsImtpZCI6IkhNQUMifQ.eyJleHAiOjE0NjMxNTE5MDAsInN1YiI6ImRsYWRtaW4iLCJncm91cHMiOlsiZGVzaWduZXJzIiwib3BlcmF0b3JzIl19.fRxn00QbHAjL-R0DI1DmYfLEi3F7eMb3V2vTvgcFOy8";
Assert.assertEquals(expected, actual);
}
/**
* Verify extracting tokens from authentication.
*/
@Test
public void onLoginSuccess() throws Exception {
// Mock request, response, and authentication
final AtomicReference<Cookie> cookie = new AtomicReference<>();
final HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
Mockito.doAnswer(answer -> cookie.compareAndSet(null, answer.getArgumentAt(0, Cookie.class)))
.when(response).addCookie(Mockito.any());
final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getContextPath()).thenReturn("");
final Authentication auth = new UsernamePasswordAuthenticationToken("dladmin", "thinkbig", Collections.singletonList(new SimpleGrantedAuthority("admin")));
// Test cookie set by login
service.onLoginSuccess(request, response, auth);
Assert.assertEquals("eyJhbGciOiJIUzI1NiIsImtpZCI6IkhNQUMifQ.eyJleHAiOjE0NjMxNTE5MDAsInN1YiI6ImRsYWRtaW4iLCJncm91cHMiOlsiYWRtaW4iXX0.3RX9hsmfNA1rtWMs309N5MV5_gd4FUtU_odFIIOqsoY",
cookie.get().getValue());
}
/**
* Verify building a user from tokens.
*/
@Test
public void processAutoLoginCookie() throws Exception {
final UserDetails user = service.processAutoLoginCookie(new String[]{"dladmin", "admin"}, Mockito.mock(HttpServletRequest.class), Mockito.mock(HttpServletResponse.class));
Assert.assertEquals("dladmin", user.getUsername());
Assert.assertEquals(Collections.singletonList("admin").toString(), user.getAuthorities().toString());
}
}