package org.gcube.common.keycloak; import java.io.File; import java.nio.file.Files; import java.nio.file.Paths; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.common.keycloak.model.AccessToken; import org.gcube.common.keycloak.model.ModelUtils; import org.gcube.common.keycloak.model.RefreshToken; import org.gcube.common.keycloak.model.TokenIntrospectionResponse; import org.gcube.common.keycloak.model.TokenResponse; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestModelUtils { protected static final Logger logger = LoggerFactory.getLogger(TestModelUtils.class); @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } @Test public void testTokenDigitalSignature() throws Exception { logger.info("Start testing OIDC token response object binding..."); TokenResponse tr = new ObjectMapper().readValue(new File("src/test/resources/oidc-token-response.json"), TokenResponse.class); // Valid signature Assert.assertFalse("Token signature is valid", ModelUtils.isValid(tr.getAccessToken(), ModelUtils.createRSAPublicKey( new String(Files.readAllBytes(Paths.get("src/test/resources/rsa-public-key.pem")))))); } @Test public void testTokenResponseForOIDC() throws Exception { logger.info("Start testing OIDC token response object binding..."); TokenResponse tr = new ObjectMapper().readValue(new File("src/test/resources/oidc-token-response.json"), TokenResponse.class); logger.debug("OIDC token response:\n{}", ModelUtils.toJSONString(tr, true)); checkTokenResponse(tr); } @Test public void testTokenResponseForUMA() throws Exception { logger.info("Start testing UMA token response object binding..."); TokenResponse tr = new ObjectMapper().readValue(new File("src/test/resources/uma-token-response.json"), TokenResponse.class); logger.debug("UMA token response:\n{}", ModelUtils.toJSONString(tr, true)); checkTokenResponse(tr); } @Test public void testUMAAccessToken() throws Exception { logger.info("Start testing access token object binding..."); AccessToken at = new ObjectMapper().readValue(new File("src/test/resources/uma-access-token.json"), AccessToken.class); checkAccessToken(at, null, true); } @Test public void testRemoveBearerPrefixInHeader() throws Exception { TokenResponse tr = new ObjectMapper().readValue(new File("src/test/resources/oidc-token-response.json"), TokenResponse.class); AccessToken at1 = ModelUtils.getAccessTokenFrom(tr.getAccessToken()); AccessToken at2 = ModelUtils.getAccessTokenFrom("Bearer " + tr.getAccessToken()); AccessToken at3 = ModelUtils.getAccessTokenFrom("bearer " + tr.getAccessToken()); checkAccessToken(at1, null, true); checkAccessToken(at2, null, true); checkAccessToken(at3, null, true); Assert.assertEquals(ModelUtils.toJSONString(at1), ModelUtils.toJSONString(at2)); Assert.assertEquals(ModelUtils.toJSONString(at2), ModelUtils.toJSONString(at3)); } @Test public void testUMARefreshToken() throws Exception { logger.info("Start testing refresh token object binding..."); RefreshToken rt = new ObjectMapper().readValue(new File("src/test/resources/uma-refresh-token.json"), RefreshToken.class); checkRefreshToken(rt); } public static void checkTokenResponse(TokenResponse tr) throws Exception { checkTokenResponse(tr, true); } public static void checkTokenResponse(TokenResponse tr, boolean checkAlsoRefreshToken) throws Exception { Assert.assertNotNull(tr); Assert.assertEquals("bearer", tr.getTokenType().toLowerCase()); Assert.assertNotNull("Access token is null", tr.getAccessToken()); if (checkAlsoRefreshToken) { Assert.assertNotNull("Refresh token is null", tr.getRefreshToken()); } } public static void checkAccessToken(AccessToken at, String preferredUsername, boolean checkAudience) { logger.debug("Access token:\n{}", ModelUtils.toJSONString(at, true)); Assert.assertNotNull(at.getPreferredUsername()); if (preferredUsername != null) { Assert.assertEquals(preferredUsername, at.getPreferredUsername()); } if (checkAudience) { Assert.assertNotNull("Audience is null", at.getAudience()); } } public static void checkRefreshToken(RefreshToken rt) { logger.debug("Refresh token:\n{}", ModelUtils.toJSONString(rt, true)); Assert.assertNotNull("Other claims are null", rt.getOtherClaims()); Assert.assertNotNull("Audience is null", rt.getAudience()); } public static void checkOfflineToken(TokenResponse tr) throws Exception { RefreshToken rt = ModelUtils.getRefreshTokenFrom(tr.getRefreshToken()); Assert.assertEquals("Offline", rt.getType()); Assert.assertNull("Expiration is not null", rt.getExp()); } public static void checkTokenIntrospectionResponse(TokenIntrospectionResponse tir) { checkTokenIntrospectionResponse(tir, true); } public static void checkTokenIntrospectionResponse(TokenIntrospectionResponse tir, boolean mustBeActive) { logger.debug("Token introspection response :\n{}", ModelUtils.toJSONString(tir, true)); if (mustBeActive) { Assert.assertTrue("Token is not active", tir.getActive()); } else { Assert.assertFalse("Token is active", tir.getActive()); } } }