3
3
import static org .junit .jupiter .api .Assertions .assertEquals ;
4
4
import static org .junit .jupiter .api .Assertions .assertNotNull ;
5
5
import static org .junit .jupiter .api .Assertions .assertNull ;
6
+ import static org .junit .jupiter .api .Assertions .assertTrue ;
7
+
8
+ import java .net .URI ;
6
9
7
10
import org .htmlunit .SilentCssErrorHandler ;
8
11
import org .htmlunit .TextPage ;
9
12
import org .htmlunit .WebClient ;
13
+ import org .htmlunit .WebRequest ;
14
+ import org .htmlunit .WebResponse ;
10
15
import org .htmlunit .html .HtmlForm ;
11
16
import org .htmlunit .html .HtmlPage ;
12
17
import org .htmlunit .util .Cookie ;
@@ -21,7 +26,43 @@ public class OidcProxyTestCase {
21
26
public void testOidcProxy () throws Exception {
22
27
23
28
try (final WebClient webClient = createWebClient ()) {
24
- HtmlPage page = webClient .getPage ("http://localhost:8081/web-app" );
29
+ // Disable auto-redirect
30
+ webClient .getOptions ().setRedirectEnabled (false );
31
+ webClient .getOptions ().setThrowExceptionOnFailingStatusCode (false );
32
+
33
+ // This is the protected endpoint redirect to the OIDC provider which is represented by OIDC proxy
34
+ WebResponse webResponse = webClient
35
+ .loadWebResponse (new WebRequest (URI .create ("http://localhost:8081/web-app" ).toURL ()));
36
+
37
+ // Original state cookie created by `quarkus-oidc`
38
+ Cookie stateCookie = getStateCookie (webClient );
39
+ assertNotNull (stateCookie );
40
+ assertEquals (stateCookie .getName (), "q_auth_web-app" );
41
+
42
+ // Confirm the OIDC proxy is the redirect target
43
+ String oidcUrl = webResponse .getResponseHeaderValue ("location" );
44
+ assertTrue (oidcUrl .startsWith ("http://localhost:8081/q/oidc/authorize" ));
45
+ // `quarkus-oidc` expects the OIDC provider redirect the user back to the protected endpoint
46
+ assertTrue (oidcUrl .contains ("redirect_uri=http%3A%2F%2Flocalhost%3A8081%2Fweb-app" ));
47
+ // No OIDC proxy state cookie available yet
48
+ Cookie proxyStateCookie = getProxyStateCookie (webClient );
49
+ assertNull (proxyStateCookie );
50
+
51
+ // This is a redirect from OIDC proxy to Keycloak but expecting a redirect
52
+ // to the OIDC proxy managed local redirect endpoint
53
+ webResponse = webClient .loadWebResponse (new WebRequest (URI .create (oidcUrl ).toURL ()));
54
+ String keycloakUrl = webResponse .getResponseHeaderValue ("location" );
55
+ assertTrue (keycloakUrl .contains ("/protocol/openid-connect/auth" ));
56
+ assertTrue (keycloakUrl .contains ("redirect_uri=http%3A%2F%2Flocalhost%3A8081%2Flocal-redirect" ));
57
+
58
+ // OIDC proxy state cookie must be set by now
59
+ proxyStateCookie = getProxyStateCookie (webClient );
60
+ assertNotNull (proxyStateCookie );
61
+ assertEquals (proxyStateCookie .getName (), "q_proxy_auth" );
62
+ assertEquals (proxyStateCookie .getValue (), stateCookie .getValue ());
63
+
64
+ // This is a challenge from Keycloak
65
+ HtmlPage page = webClient .getPage (keycloakUrl );
25
66
26
67
assertEquals ("Sign in to quarkus" , page .getTitleText ());
27
68
@@ -30,15 +71,44 @@ public void testOidcProxy() throws Exception {
30
71
loginForm .getInputByName ("username" ).setValueAttribute ("alice" );
31
72
loginForm .getInputByName ("password" ).setValueAttribute ("alice" );
32
73
33
- TextPage textPage = loginForm .getButtonByName ("login" ).click ();
74
+ webResponse = loginForm .getButtonByName ("login" ).click ().getWebResponse ();
75
+
76
+ // This is a redirect from Keycloak to the OIDC proxy managed local redirect endpoint
77
+ String localRedirectUrl = webResponse .getResponseHeaderValue ("location" );
78
+ assertTrue (localRedirectUrl .startsWith ("http://localhost:8081/local-redirect" ));
79
+
80
+ // This is a redirect from the OIDC proxy managed local redirect endpoint to the protected endpoint
81
+ webResponse = webClient .loadWebResponse (new WebRequest (URI .create (localRedirectUrl ).toURL ()));
82
+ String webAppRedirectUrl = webResponse .getResponseHeaderValue ("location" );
83
+ assertTrue (webAppRedirectUrl .startsWith ("http://localhost:8081/web-app" ));
84
+
85
+ // No session cookie is available yet
86
+ assertNull (getSessionCookie (webClient ));
87
+
88
+ // Original state cookie is still expected
89
+ assertNotNull (getStateCookie (webClient ));
90
+ // But the OIDC proxy state cookie must be gone by now
91
+ assertNull (getProxyStateCookie (webClient ));
92
+
93
+ webClient .getOptions ().setRedirectEnabled (true );
94
+
95
+ // Access the protected endpoint, complete the code flow, get the response
96
+ TextPage textPage = webClient .getPage (webAppRedirectUrl );
34
97
35
98
assertEquals ("web-app: ID alice, service: Bearer alice" , textPage .getContent ());
36
99
100
+ // Session cookie is ready
37
101
assertNotNull (getSessionCookie (webClient ));
38
102
103
+ // Both state cookies must be null
104
+ assertNull (getStateCookie (webClient ));
105
+ assertNull (getProxyStateCookie (webClient ));
106
+
107
+ // Logout
39
108
textPage = webClient .getPage ("http://localhost:8081/web-app/logout" );
40
109
assertEquals ("You have been logged out" , textPage .getContent ());
41
110
111
+ // Session cookie must be null
42
112
assertNull (getSessionCookie (webClient ));
43
113
44
114
webClient .getCookieManager ().clearCookies ();
@@ -55,4 +125,12 @@ private WebClient createWebClient() {
55
125
private Cookie getSessionCookie (WebClient webClient ) {
56
126
return webClient .getCookieManager ().getCookie ("q_session_web-app" );
57
127
}
128
+
129
+ private Cookie getStateCookie (WebClient webClient ) {
130
+ return webClient .getCookieManager ().getCookie ("q_auth_web-app" );
131
+ }
132
+
133
+ private Cookie getProxyStateCookie (WebClient webClient ) {
134
+ return webClient .getCookieManager ().getCookie ("q_proxy_auth" );
135
+ }
58
136
}
0 commit comments