55import com .nimbusds .oauth2 .sdk .AccessTokenResponse ;
66import com .nimbusds .oauth2 .sdk .AuthorizationGrant ;
77import com .nimbusds .oauth2 .sdk .ClientCredentialsGrant ;
8+ import com .nimbusds .oauth2 .sdk .GeneralException ;
89import com .nimbusds .oauth2 .sdk .ParseException ;
910import com .nimbusds .oauth2 .sdk .RefreshTokenGrant ;
1011import com .nimbusds .oauth2 .sdk .TokenErrorResponse ;
1314import com .nimbusds .oauth2 .sdk .auth .ClientAuthentication ;
1415import com .nimbusds .oauth2 .sdk .auth .ClientSecretBasic ;
1516import com .nimbusds .oauth2 .sdk .auth .Secret ;
17+ import com .nimbusds .oauth2 .sdk .http .HTTPRequest ;
18+ import com .nimbusds .oauth2 .sdk .http .HTTPResponse ;
1619import com .nimbusds .oauth2 .sdk .id .ClientID ;
20+ import com .nimbusds .oauth2 .sdk .id .Issuer ;
1721import com .nimbusds .oauth2 .sdk .token .AccessToken ;
1822import com .nimbusds .oauth2 .sdk .token .RefreshToken ;
23+ import com .nimbusds .openid .connect .sdk .op .OIDCProviderMetadata ;
1924import java .io .IOException ;
2025import java .net .URI ;
26+ import java .net .URL ;
2127import java .time .Duration ;
2228import java .time .Instant ;
29+ import net .minidev .json .JSONObject ;
2330import org .slf4j .Logger ;
2431import org .slf4j .LoggerFactory ;
2532
@@ -66,7 +73,7 @@ private void renewToken(SecurityServiceConfig config) {
6673 private TokenRequest createTokenRequest (SecurityServiceConfig config ) {
6774 final ClientAuthentication clientAuth = getClientAuthentication (config );
6875
69- URI tokenEndpoint = URI . create (config . getTokenEndpoint () );
76+ final URI tokenEndpoint = resolveTokenEndpointUri (config );
7077
7178 TokenRequest request ;
7279 if (refreshToken == null ) {
@@ -80,6 +87,59 @@ private TokenRequest createTokenRequest(SecurityServiceConfig config) {
8087 return request ;
8188 }
8289
90+ /*
91+ * We cannot use OIDCProviderMetadata.resolve directly, because it validates the provided
92+ * config endpoint with the issuer endpoint. However, because Wanaku typically uses the
93+ * OIDC Proxy, they are not the same (which causes it to throw a GeneralException).
94+ * This mimics the resolve logic, but ignores the validation and other things we don't
95+ * need.
96+ */
97+ private static Issuer resolveIssuer (SecurityServiceConfig config ) {
98+ // The OpenID provider issuer URL
99+ Issuer issuer = new Issuer (config .getTokenEndpoint ());
100+
101+ try {
102+ final URL openIdConfigUrl = OIDCProviderMetadata .resolveURL (issuer );
103+
104+ HTTPRequest httpRequest = new HTTPRequest (HTTPRequest .Method .GET , openIdConfigUrl );
105+ HTTPResponse httpResponse = httpRequest .send ();
106+
107+ if (httpResponse .getStatusCode () != 200 ) {
108+ throw new ServiceAuthException ("Unable to download OpenID Provider metadata from " + openIdConfigUrl
109+ + ": Status code " + httpResponse .getStatusCode ());
110+ }
111+
112+ JSONObject jsonObject = httpResponse .getBodyAsJSONObject ();
113+
114+ OIDCProviderMetadata op = OIDCProviderMetadata .parse (jsonObject );
115+
116+ return op .getIssuer ();
117+ } catch (GeneralException e ) {
118+ throw new ServiceAuthException ("Unable to resolve token endpoint URI: " + e .getMessage (), e );
119+ } catch (IOException e ) {
120+ throw new ServiceAuthException ("I/O error while resolving token endpoint URI: " + e .getMessage (), e );
121+ }
122+ }
123+
124+ private static URI resolveTokenEndpointUri (SecurityServiceConfig config ) {
125+
126+ /* We cannot use Wanaku's base address because it's typically behind the OIDC
127+ * proxy. Therefore, we first need to resolve the issuer address, and then
128+ * use the issuer address to resolve the OIDC metadata.
129+ */
130+ Issuer issuer = new Issuer (resolveIssuer (config ));
131+
132+ try {
133+ final OIDCProviderMetadata resolvedOp = OIDCProviderMetadata .resolve (issuer );
134+
135+ return resolvedOp .getTokenEndpointURI ();
136+ } catch (GeneralException e ) {
137+ throw new ServiceAuthException ("Unable to resolve token endpoint URI: " + e .getMessage (), e );
138+ } catch (IOException e ) {
139+ throw new ServiceAuthException ("I/O error while resolving token endpoint URI: " + e .getMessage (), e );
140+ }
141+ }
142+
83143 /**
84144 * Creates client authentication for OAuth2 requests.
85145 *
0 commit comments