20
20
21
21
import org .springframework .security .oauth2 .core .OAuth2TokenValidator ;
22
22
import org .springframework .util .Assert ;
23
+ import org .springframework .web .client .RestOperations ;
24
+
23
25
24
26
/**
25
27
* Allows creating a {@link JwtDecoder} from an <a href=
@@ -52,10 +54,29 @@ private JwtDecoders() {
52
54
*/
53
55
@ SuppressWarnings ("unchecked" )
54
56
public static <T extends JwtDecoder > T fromOidcIssuerLocation (String oidcIssuerLocation ) {
57
+ return fromOidcIssuerLocation (oidcIssuerLocation , null );
58
+ }
59
+
60
+ /**
61
+ * Creates a {@link JwtDecoder} using the provided <a href=
62
+ * "https://openid.net/specs/openid-connect-core-1_0.html#IssuerIdentifier">Issuer</a>
63
+ * by making an <a href=
64
+ * "https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest">OpenID
65
+ * Provider Configuration Request</a> and using the values in the <a href=
66
+ * "https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse">OpenID
67
+ * Provider Configuration Response</a> to initialize the {@link JwtDecoder}.
68
+ * @param oidcIssuerLocation the <a href=
69
+ * "https://openid.net/specs/openid-connect-core-1_0.html#IssuerIdentifier">Issuer</a>
70
+ * @param restOperations customized {@link RestOperations}
71
+ * @return a {@link JwtDecoder} that was initialized by the OpenID Provider
72
+ * Configuration.
73
+ */
74
+ public static <T extends JwtDecoder > T fromOidcIssuerLocation (String oidcIssuerLocation ,
75
+ RestOperations restOperations ) {
55
76
Assert .hasText (oidcIssuerLocation , "oidcIssuerLocation cannot be empty" );
56
77
Map <String , Object > configuration = JwtDecoderProviderConfigurationUtils
57
78
.getConfigurationForOidcIssuerLocation (oidcIssuerLocation );
58
- return (T ) withProviderConfiguration (configuration , oidcIssuerLocation );
79
+ return (T ) withProviderConfiguration (configuration , oidcIssuerLocation , restOperations );
59
80
}
60
81
61
82
/**
@@ -88,8 +109,46 @@ public static <T extends JwtDecoder> T fromOidcIssuerLocation(String oidcIssuerL
88
109
*/
89
110
@ SuppressWarnings ("unchecked" )
90
111
public static <T extends JwtDecoder > T fromIssuerLocation (String issuer ) {
112
+ return fromIssuerLocation (issuer , null );
113
+ }
114
+
115
+ /**
116
+ * Creates a {@link JwtDecoder} using the provided <a href=
117
+ * "https://openid.net/specs/openid-connect-core-1_0.html#IssuerIdentifier">Issuer</a>
118
+ * by querying three different discovery endpoints serially, using the values in the
119
+ * first successful response to initialize. If an endpoint returns anything other than
120
+ * a 200 or a 4xx, the method will exit without attempting subsequent endpoints.
121
+ *
122
+ * The three endpoints are computed as follows, given that the {@code issuer} is
123
+ * composed of a {@code host} and a {@code path}:
124
+ *
125
+ * <ol>
126
+ * <li>{@code host/.well-known/openid-configuration/path}, as defined in
127
+ * <a href="https://tools.ietf.org/html/rfc8414#section-5">RFC 8414's Compatibility
128
+ * Notes</a>.</li>
129
+ * <li>{@code issuer/.well-known/openid-configuration}, as defined in <a href=
130
+ * "https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest">
131
+ * OpenID Provider Configuration</a>.</li>
132
+ * <li>{@code host/.well-known/oauth-authorization-server/path}, as defined in
133
+ * <a href="https://tools.ietf.org/html/rfc8414#section-3.1">Authorization Server
134
+ * Metadata Request</a>.</li>
135
+ * </ol>
136
+ *
137
+ * Note that the second endpoint is the equivalent of calling
138
+ * {@link JwtDecoders#fromOidcIssuerLocation(String)}
139
+ * @param issuer the <a href=
140
+ * "https://openid.net/specs/openid-connect-core-1_0.html#IssuerIdentifier">Issuer</a>
141
+ * @param restOperations customized {@link RestOperations}
142
+ * @return a {@link JwtDecoder} that was initialized by one of the described endpoints
143
+ */
144
+ @ SuppressWarnings ("unchecked" )
145
+ public static <T extends JwtDecoder > T fromIssuerLocation (String issuer , RestOperations restOperations ) {
91
146
Assert .hasText (issuer , "issuer cannot be empty" );
92
- NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder .withIssuerLocation (issuer ).build ();
147
+ NimbusJwtDecoder .JwkSetUriJwtDecoderBuilder builder = NimbusJwtDecoder .withIssuerLocation (issuer );
148
+ if (restOperations != null ) {
149
+ builder = builder .restOperations (restOperations );
150
+ }
151
+ NimbusJwtDecoder jwtDecoder = builder .build ();
93
152
OAuth2TokenValidator <Jwt > jwtValidator = JwtValidators .createDefaultWithIssuer (issuer );
94
153
jwtDecoder .setJwtValidator (jwtValidator );
95
154
return (T ) jwtDecoder ;
@@ -104,15 +163,20 @@ public static <T extends JwtDecoder> T fromIssuerLocation(String issuer) {
104
163
* @param configuration the configuration values
105
164
* @param issuer the <a href=
106
165
* "https://openid.net/specs/openid-connect-core-1_0.html#IssuerIdentifier">Issuer</a>
166
+ * @param restOperations customized {@link RestOperations}
107
167
* @return {@link JwtDecoder}
108
168
*/
109
- private static JwtDecoder withProviderConfiguration (Map <String , Object > configuration , String issuer ) {
169
+ private static JwtDecoder withProviderConfiguration (Map <String , Object > configuration , String issuer ,
170
+ RestOperations restOperations ) {
110
171
JwtDecoderProviderConfigurationUtils .validateIssuer (configuration , issuer );
111
172
OAuth2TokenValidator <Jwt > jwtValidator = JwtValidators .createDefaultWithIssuer (issuer );
112
173
String jwkSetUri = configuration .get ("jwks_uri" ).toString ();
113
- NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder .withJwkSetUri (jwkSetUri )
114
- .jwtProcessorCustomizer (JwtDecoderProviderConfigurationUtils ::addJWSAlgorithms )
115
- .build ();
174
+ NimbusJwtDecoder .JwkSetUriJwtDecoderBuilder builder = NimbusJwtDecoder .withJwkSetUri (jwkSetUri )
175
+ .jwtProcessorCustomizer (JwtDecoderProviderConfigurationUtils ::addJWSAlgorithms );
176
+ if (restOperations != null ) {
177
+ builder = builder .restOperations (restOperations );
178
+ }
179
+ NimbusJwtDecoder jwtDecoder = builder .build ();
116
180
jwtDecoder .setJwtValidator (jwtValidator );
117
181
return jwtDecoder ;
118
182
}
0 commit comments