| 
									
										
										
										
											2019-08-31 20:51:14 -07:00
										 |  |  | package app;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-06 11:02:42 +05:30
										 |  |  | import static org.junit.jupiter.api.Assertions.assertEquals;
 | 
					
						
							|  |  |  | import static org.junit.jupiter.api.Assertions.assertTrue;
 | 
					
						
							|  |  |  | import static play.mvc.Http.Status.NOT_FOUND;
 | 
					
						
							|  |  |  | import static play.mvc.Http.Status.OK;
 | 
					
						
							|  |  |  | import static play.test.Helpers.fakeRequest;
 | 
					
						
							|  |  |  | import static play.test.Helpers.route;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 15:50:32 -05:00
										 |  |  | import com.nimbusds.jwt.JWT;
 | 
					
						
							|  |  |  | import com.nimbusds.jwt.JWTClaimsSet;
 | 
					
						
							|  |  |  | import com.nimbusds.jwt.JWTParser;
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  | import controllers.routes;
 | 
					
						
							| 
									
										
										
										
											2023-12-06 11:02:42 +05:30
										 |  |  | import java.io.IOException;
 | 
					
						
							|  |  |  | import java.net.InetAddress;
 | 
					
						
							| 
									
										
										
										
											2023-10-17 15:50:32 -05:00
										 |  |  | import java.text.ParseException;
 | 
					
						
							|  |  |  | import java.util.Date;
 | 
					
						
							| 
									
										
										
										
											2023-12-06 11:02:42 +05:30
										 |  |  | import java.util.List;
 | 
					
						
							|  |  |  | import java.util.Map;
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  | import no.nav.security.mock.oauth2.MockOAuth2Server;
 | 
					
						
							|  |  |  | import no.nav.security.mock.oauth2.token.DefaultOAuth2TokenCallback;
 | 
					
						
							|  |  |  | import okhttp3.mockwebserver.MockResponse;
 | 
					
						
							|  |  |  | import okhttp3.mockwebserver.MockWebServer;
 | 
					
						
							| 
									
										
										
										
											2022-12-26 10:09:08 -06:00
										 |  |  | import org.awaitility.Awaitility;
 | 
					
						
							|  |  |  | import org.awaitility.Durations;
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  | import org.junit.jupiter.api.AfterAll;
 | 
					
						
							|  |  |  | import org.junit.jupiter.api.BeforeAll;
 | 
					
						
							|  |  |  | import org.junit.jupiter.api.Test;
 | 
					
						
							|  |  |  | import org.junit.jupiter.api.TestInstance;
 | 
					
						
							|  |  |  | import org.junitpioneer.jupiter.SetEnvironmentVariable;
 | 
					
						
							|  |  |  | import org.openqa.selenium.Cookie;
 | 
					
						
							| 
									
										
										
										
											2022-12-26 10:09:08 -06:00
										 |  |  | import org.openqa.selenium.htmlunit.HtmlUnitDriver;
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  | import play.Application;
 | 
					
						
							|  |  |  | import play.Environment;
 | 
					
						
							|  |  |  | import play.Mode;
 | 
					
						
							|  |  |  | import play.inject.guice.GuiceApplicationBuilder;
 | 
					
						
							|  |  |  | import play.mvc.Http;
 | 
					
						
							|  |  |  | import play.mvc.Result;
 | 
					
						
							|  |  |  | import play.test.Helpers;
 | 
					
						
							|  |  |  | import play.test.TestBrowser;
 | 
					
						
							|  |  |  | import play.test.WithBrowser;
 | 
					
						
							| 
									
										
										
										
											2019-08-31 20:51:14 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  | @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 | 
					
						
							|  |  |  | @SetEnvironmentVariable(key = "DATAHUB_SECRET", value = "test")
 | 
					
						
							|  |  |  | @SetEnvironmentVariable(key = "KAFKA_BOOTSTRAP_SERVER", value = "")
 | 
					
						
							|  |  |  | @SetEnvironmentVariable(key = "DATAHUB_ANALYTICS_ENABLED", value = "false")
 | 
					
						
							|  |  |  | @SetEnvironmentVariable(key = "AUTH_OIDC_ENABLED", value = "true")
 | 
					
						
							|  |  |  | @SetEnvironmentVariable(key = "AUTH_OIDC_JIT_PROVISIONING_ENABLED", value = "false")
 | 
					
						
							|  |  |  | @SetEnvironmentVariable(key = "AUTH_OIDC_CLIENT_ID", value = "testclient")
 | 
					
						
							|  |  |  | @SetEnvironmentVariable(key = "AUTH_OIDC_CLIENT_SECRET", value = "testsecret")
 | 
					
						
							|  |  |  | public class ApplicationTest extends WithBrowser {
 | 
					
						
							|  |  |  |   private static final String ISSUER_ID = "testIssuer";
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @Override
 | 
					
						
							|  |  |  |   protected Application provideApplication() {
 | 
					
						
							|  |  |  |     return new GuiceApplicationBuilder()
 | 
					
						
							| 
									
										
										
										
											2023-12-06 11:02:42 +05:30
										 |  |  |         .configure("metadataService.port", String.valueOf(gmsServerPort()))
 | 
					
						
							|  |  |  |         .configure("auth.baseUrl", "http://localhost:" + providePort())
 | 
					
						
							|  |  |  |         .configure(
 | 
					
						
							|  |  |  |             "auth.oidc.discoveryUri",
 | 
					
						
							|  |  |  |             "http://localhost:"
 | 
					
						
							|  |  |  |                 + oauthServerPort()
 | 
					
						
							|  |  |  |                 + "/testIssuer/.well-known/openid-configuration")
 | 
					
						
							|  |  |  |         .in(new Environment(Mode.TEST))
 | 
					
						
							|  |  |  |         .build();
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-26 10:09:08 -06:00
										 |  |  |   @Override
 | 
					
						
							|  |  |  |   protected TestBrowser provideBrowser(int port) {
 | 
					
						
							|  |  |  |     HtmlUnitDriver webClient = new HtmlUnitDriver();
 | 
					
						
							|  |  |  |     webClient.setJavascriptEnabled(false);
 | 
					
						
							|  |  |  |     return Helpers.testBrowser(webClient, providePort());
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  |   public int oauthServerPort() {
 | 
					
						
							|  |  |  |     return providePort() + 1;
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   public int gmsServerPort() {
 | 
					
						
							|  |  |  |     return providePort() + 2;
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private MockOAuth2Server _oauthServer;
 | 
					
						
							|  |  |  |   private MockWebServer _gmsServer;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private String _wellKnownUrl;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-22 16:12:51 -06:00
										 |  |  |   private static final String TEST_USER = "urn:li:corpuser:testUser@myCompany.com";
 | 
					
						
							|  |  |  |   private static final String TEST_TOKEN = "faketoken_YCpYIrjQH4sD3_rAc3VPPFg4";
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  |   @BeforeAll
 | 
					
						
							| 
									
										
										
										
											2022-12-26 10:09:08 -06:00
										 |  |  |   public void init() throws IOException {
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  |     _gmsServer = new MockWebServer();
 | 
					
						
							| 
									
										
										
										
											2023-12-26 14:34:10 -06:00
										 |  |  |     _gmsServer.enqueue(new MockResponse().setResponseCode(404)); // dynamic settings - not tested
 | 
					
						
							|  |  |  |     _gmsServer.enqueue(new MockResponse().setResponseCode(404)); // dynamic settings - not tested
 | 
					
						
							|  |  |  |     _gmsServer.enqueue(new MockResponse().setResponseCode(404)); // dynamic settings - not tested
 | 
					
						
							| 
									
										
										
										
											2022-12-22 16:12:51 -06:00
										 |  |  |     _gmsServer.enqueue(new MockResponse().setBody(String.format("{\"value\":\"%s\"}", TEST_USER)));
 | 
					
						
							| 
									
										
										
										
											2023-12-06 11:02:42 +05:30
										 |  |  |     _gmsServer.enqueue(
 | 
					
						
							|  |  |  |         new MockResponse().setBody(String.format("{\"accessToken\":\"%s\"}", TEST_TOKEN)));
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  |     _gmsServer.start(gmsServerPort());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _oauthServer = new MockOAuth2Server();
 | 
					
						
							|  |  |  |     _oauthServer.enqueueCallback(
 | 
					
						
							| 
									
										
										
										
											2023-12-06 11:02:42 +05:30
										 |  |  |         new DefaultOAuth2TokenCallback(
 | 
					
						
							|  |  |  |             ISSUER_ID,
 | 
					
						
							|  |  |  |             "testUser",
 | 
					
						
							|  |  |  |             List.of(),
 | 
					
						
							|  |  |  |             Map.of(
 | 
					
						
							|  |  |  |                 "email", "testUser@myCompany.com",
 | 
					
						
							|  |  |  |                 "groups", "myGroup"),
 | 
					
						
							|  |  |  |             600));
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  |     _oauthServer.start(InetAddress.getByName("localhost"), oauthServerPort());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Discovery url to authorization server metadata
 | 
					
						
							|  |  |  |     _wellKnownUrl = _oauthServer.wellKnownUrl(ISSUER_ID).toString();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     startServer();
 | 
					
						
							|  |  |  |     createBrowser();
 | 
					
						
							| 
									
										
										
										
											2022-12-26 10:09:08 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Awaitility.await().timeout(Durations.TEN_SECONDS).until(() -> app != null);
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @AfterAll
 | 
					
						
							|  |  |  |   public void shutdown() throws IOException {
 | 
					
						
							|  |  |  |     if (_gmsServer != null) {
 | 
					
						
							|  |  |  |       _gmsServer.shutdown();
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     if (_oauthServer != null) {
 | 
					
						
							|  |  |  |       _oauthServer.shutdown();
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     stopServer();
 | 
					
						
							|  |  |  |   }
 | 
					
						
							| 
									
										
										
										
											2019-08-31 20:51:14 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @Test
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  |   public void testHealth() {
 | 
					
						
							|  |  |  |     Http.RequestBuilder request = fakeRequest(routes.Application.healthcheck());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Result result = route(app, request);
 | 
					
						
							|  |  |  |     assertEquals(OK, result.status());
 | 
					
						
							| 
									
										
										
										
											2019-08-31 20:51:14 -07:00
										 |  |  |   }
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @Test
 | 
					
						
							|  |  |  |   public void testIndex() {
 | 
					
						
							|  |  |  |     Http.RequestBuilder request = fakeRequest(routes.Application.index(""));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Result result = route(app, request);
 | 
					
						
							|  |  |  |     assertEquals(OK, result.status());
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @Test
 | 
					
						
							|  |  |  |   public void testIndexNotFound() {
 | 
					
						
							|  |  |  |     Http.RequestBuilder request = fakeRequest(routes.Application.index("/other"));
 | 
					
						
							|  |  |  |     Result result = route(app, request);
 | 
					
						
							|  |  |  |     assertEquals(NOT_FOUND, result.status());
 | 
					
						
							|  |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @Test
 | 
					
						
							|  |  |  |   public void testOpenIdConfig() {
 | 
					
						
							| 
									
										
										
										
											2023-12-06 11:02:42 +05:30
										 |  |  |     assertEquals(
 | 
					
						
							|  |  |  |         "http://localhost:" + oauthServerPort() + "/testIssuer/.well-known/openid-configuration",
 | 
					
						
							|  |  |  |         _wellKnownUrl);
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @Test
 | 
					
						
							| 
									
										
										
										
											2023-10-17 15:50:32 -05:00
										 |  |  |   public void testHappyPathOidc() throws ParseException {
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  |     browser.goTo("/authenticate");
 | 
					
						
							|  |  |  |     assertEquals("", browser.url());
 | 
					
						
							| 
									
										
										
										
											2022-12-22 16:12:51 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  |     Cookie actorCookie = browser.getCookie("actor");
 | 
					
						
							| 
									
										
										
										
											2022-12-22 16:12:51 -06:00
										 |  |  |     assertEquals(TEST_USER, actorCookie.getValue());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Cookie sessionCookie = browser.getCookie("PLAY_SESSION");
 | 
					
						
							| 
									
										
										
										
											2023-10-17 15:50:32 -05:00
										 |  |  |     String jwtStr = sessionCookie.getValue();
 | 
					
						
							|  |  |  |     JWT jwt = JWTParser.parse(jwtStr);
 | 
					
						
							|  |  |  |     JWTClaimsSet claims = jwt.getJWTClaimsSet();
 | 
					
						
							|  |  |  |     Map<String, String> data = (Map<String, String>) claims.getClaim("data");
 | 
					
						
							|  |  |  |     assertEquals(TEST_TOKEN, data.get("token"));
 | 
					
						
							|  |  |  |     assertEquals(TEST_USER, data.get("actor"));
 | 
					
						
							| 
									
										
										
										
											2023-12-06 11:02:42 +05:30
										 |  |  |     // Default expiration is 24h, so should always be less than current time + 1 day since it stamps
 | 
					
						
							|  |  |  |     // the time before this executes
 | 
					
						
							|  |  |  |     assertTrue(
 | 
					
						
							|  |  |  |         claims
 | 
					
						
							|  |  |  |                 .getExpirationTime()
 | 
					
						
							|  |  |  |                 .compareTo(new Date(System.currentTimeMillis() + (24 * 60 * 60 * 1000)))
 | 
					
						
							|  |  |  |             < 0);
 | 
					
						
							| 
									
										
										
										
											2023-10-17 15:50:32 -05:00
										 |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @Test
 | 
					
						
							|  |  |  |   public void testAPI() throws ParseException {
 | 
					
						
							|  |  |  |     testHappyPathOidc();
 | 
					
						
							|  |  |  |     int requestCount = _gmsServer.getRequestCount();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     browser.goTo("/api/v2/graphql/");
 | 
					
						
							|  |  |  |     assertEquals(++requestCount, _gmsServer.getRequestCount());
 | 
					
						
							| 
									
										
										
										
											2022-12-08 20:27:51 -06:00
										 |  |  |   }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-11 10:45:18 -08:00
										 |  |  |   @Test
 | 
					
						
							| 
									
										
										
										
											2024-01-09 14:15:50 -06:00
										 |  |  |   public void testOidcRedirectToRequestedUrl() {
 | 
					
						
							| 
									
										
										
										
											2023-01-11 10:45:18 -08:00
										 |  |  |     browser.goTo("/authenticate?redirect_uri=%2Fcontainer%2Furn%3Ali%3Acontainer%3ADATABASE");
 | 
					
						
							|  |  |  |     assertEquals("container/urn:li:container:DATABASE", browser.url());
 | 
					
						
							|  |  |  |   }
 | 
					
						
							| 
									
										
										
										
											2024-01-09 14:15:50 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /**
 | 
					
						
							|  |  |  |    * The Redirect Uri parameter is used to store a previous relative location within the app to be able to
 | 
					
						
							|  |  |  |    * take a user back to their expected page. Redirecting to other domains should be blocked.
 | 
					
						
							|  |  |  |    */
 | 
					
						
							|  |  |  |   @Test
 | 
					
						
							|  |  |  |   public void testInvalidRedirectUrl() {
 | 
					
						
							|  |  |  |     browser.goTo("/authenticate?redirect_uri=https%3A%2F%2Fwww.google.com");
 | 
					
						
							|  |  |  |     assertEquals("", browser.url());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     browser.goTo("/authenticate?redirect_uri=file%3A%2F%2FmyFile");
 | 
					
						
							|  |  |  |     assertEquals("", browser.url());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     browser.goTo("/authenticate?redirect_uri=ftp%3A%2F%2FsomeFtp");
 | 
					
						
							|  |  |  |     assertEquals("", browser.url());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     browser.goTo("/authenticate?redirect_uri=localhost%3A9002%2Flogin");
 | 
					
						
							|  |  |  |     assertEquals("", browser.url());
 | 
					
						
							|  |  |  |   }
 | 
					
						
							| 
									
										
										
										
											2019-08-31 20:51:14 -07:00
										 |  |  | }
 |