1
1
/*
2
- * Copyright 2002-2018 the original author or authors.
2
+ * Copyright 2002-2019 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
15
15
*/
16
16
package org .springframework .security .oauth2 .jwt ;
17
17
18
- import java .net .URI ;
19
- import java .util .Collections ;
20
18
import java .util .Map ;
21
19
22
- import org .springframework .core .ParameterizedTypeReference ;
23
- import org .springframework .http .RequestEntity ;
24
- import org .springframework .http .ResponseEntity ;
25
20
import org .springframework .security .oauth2 .core .OAuth2TokenValidator ;
26
21
import org .springframework .util .Assert ;
27
- import org .springframework .web .client .HttpClientErrorException ;
28
- import org .springframework .web .client .RestTemplate ;
29
- import org .springframework .web .util .UriComponentsBuilder ;
30
22
31
23
import static org .springframework .security .oauth2 .jwt .NimbusReactiveJwtDecoder .withJwkSetUri ;
32
24
33
25
/**
34
26
* Allows creating a {@link ReactiveJwtDecoder} from an
35
- * <a href="https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig">OpenID Provider Configuration</a>.
27
+ * <a href="https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig">OpenID Provider Configuration</a> or
28
+ * <a href="https://tools.ietf.org/html/rfc8414#section-3.1">Authorization Server Metadata Request</a> based on provided
29
+ * issuer and method invoked.
36
30
*
37
31
* @author Josh Cummings
38
32
* @since 5.1
39
33
*/
40
34
public final class ReactiveJwtDecoders {
41
- private static final String OIDC_METADATA_PATH = "/.well-known/openid-configuration" ;
42
- private static final String OAUTH_METADATA_PATH = "/.well-known/oauth-authorization-server" ;
43
- private static final RestTemplate rest = new RestTemplate ();
44
- private static final ParameterizedTypeReference <Map <String , Object >> typeReference =
45
- new ParameterizedTypeReference <Map <String , Object >>() {};
46
35
47
36
/**
48
37
* Creates a {@link ReactiveJwtDecoder} using the provided
@@ -57,7 +46,7 @@ public final class ReactiveJwtDecoders {
57
46
*/
58
47
public static ReactiveJwtDecoder fromOidcIssuerLocation (String oidcIssuerLocation ) {
59
48
Assert .hasText (oidcIssuerLocation , "oidcIssuerLocation cannot be empty" );
60
- Map <String , Object > configuration = getConfiguration ( oidcIssuerLocation , oidc ( URI . create (oidcIssuerLocation )) );
49
+ Map <String , Object > configuration = JwtDecoderProviderConfigurationUtils . getConfigurationForOidcIssuerLocation (oidcIssuerLocation );
61
50
return withProviderConfiguration (configuration , oidcIssuerLocation );
62
51
}
63
52
@@ -90,60 +79,27 @@ public static ReactiveJwtDecoder fromOidcIssuerLocation(String oidcIssuerLocatio
90
79
* Note that the second endpoint is the equivalent of calling
91
80
* {@link ReactiveJwtDecoders#fromOidcIssuerLocation(String)}
92
81
*
93
- * @param issuer
82
+ * @param issuer the <a href="https://openid.net/specs/openid-connect-core-1_0.html#IssuerIdentifier">Issuer</a>
94
83
* @return a {@link ReactiveJwtDecoder} that was initialized by one of the described endpoints
95
84
*/
96
85
public static ReactiveJwtDecoder fromIssuerLocation (String issuer ) {
97
86
Assert .hasText (issuer , "issuer cannot be empty" );
98
- URI uri = URI .create (issuer );
99
- Map <String , Object > configuration = getConfiguration (issuer , oidc (uri ), oidcRfc8414 (uri ), oauth (uri ));
87
+ Map <String , Object > configuration = JwtDecoderProviderConfigurationUtils .getConfigurationForIssuerLocation (issuer );
100
88
return withProviderConfiguration (configuration , issuer );
101
89
}
102
90
103
- private static URI oidc (URI issuer ) {
104
- return UriComponentsBuilder .fromUri (issuer )
105
- .replacePath (issuer .getPath () + OIDC_METADATA_PATH ).build (Collections .emptyMap ());
106
- }
107
-
108
- private static URI oidcRfc8414 (URI issuer ) {
109
- return UriComponentsBuilder .fromUri (issuer )
110
- .replacePath (OIDC_METADATA_PATH + issuer .getPath ()).build (Collections .emptyMap ());
111
- }
112
-
113
- private static URI oauth (URI issuer ) {
114
- return UriComponentsBuilder .fromUri (issuer )
115
- .replacePath (OAUTH_METADATA_PATH + issuer .getPath ()).build (Collections .emptyMap ());
116
- }
117
-
118
- private static Map <String , Object > getConfiguration (String issuer , URI ... uris ) {
119
- String errorMessage = "Unable to resolve the Configuration with the provided Issuer of " +
120
- "\" " + issuer + "\" " ;
121
- for (URI uri : uris ) {
122
- try {
123
- RequestEntity <Void > request = RequestEntity .get (uri ).build ();
124
- ResponseEntity <Map <String , Object >> response = rest .exchange (request , typeReference );
125
- return response .getBody ();
126
- } catch (RuntimeException e ) {
127
- if (!(e instanceof HttpClientErrorException &&
128
- ((HttpClientErrorException ) e ).getStatusCode ().is4xxClientError ())) {
129
- throw new IllegalArgumentException (errorMessage , e );
130
- }
131
- // else try another endpoint
132
- }
133
- }
134
- throw new IllegalArgumentException (errorMessage );
135
- }
136
-
91
+ /**
92
+ * Build {@link ReactiveJwtDecoder} from
93
+ * <a href="https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse">OpenID Provider
94
+ * Configuration Response</a> and <a href="https://tools.ietf.org/html/rfc8414#section-3.2">Authorization Server Metadata
95
+ * Response</a>.
96
+ *
97
+ * @param configuration the configuration values
98
+ * @param issuer the <a href="https://openid.net/specs/openid-connect-core-1_0.html#IssuerIdentifier">Issuer</a>
99
+ * @return {@link ReactiveJwtDecoder}
100
+ */
137
101
private static ReactiveJwtDecoder withProviderConfiguration (Map <String , Object > configuration , String issuer ) {
138
- String metadataIssuer = "(unavailable)" ;
139
- if (configuration .containsKey ("issuer" )) {
140
- metadataIssuer = configuration .get ("issuer" ).toString ();
141
- }
142
- if (!issuer .equals (metadataIssuer )) {
143
- throw new IllegalStateException ("The Issuer \" " + metadataIssuer + "\" provided in the configuration did not "
144
- + "match the requested issuer \" " + issuer + "\" " );
145
- }
146
-
102
+ JwtDecoderProviderConfigurationUtils .validateIssuer (configuration , issuer );
147
103
OAuth2TokenValidator <Jwt > jwtValidator = JwtValidators .createDefaultWithIssuer (issuer );
148
104
NimbusReactiveJwtDecoder jwtDecoder = withJwkSetUri (configuration .get ("jwks_uri" ).toString ()).build ();
149
105
jwtDecoder .setJwtValidator (jwtValidator );
0 commit comments