36
36
import org .springframework .security .oauth2 .jwt .JwtEncoder ;
37
37
import org .springframework .security .oauth2 .jwt .NimbusJwsEncoder ;
38
38
import org .springframework .security .oauth2 .server .authorization .InMemoryOAuth2AuthorizationService ;
39
+ import org .springframework .security .oauth2 .server .authorization .InMemoryOAuth2AuthorizationConsentService ;
39
40
import org .springframework .security .oauth2 .server .authorization .JwtEncodingContext ;
40
41
import org .springframework .security .oauth2 .server .authorization .OAuth2AuthorizationService ;
41
42
import org .springframework .security .oauth2 .server .authorization .OAuth2TokenCustomizer ;
43
+ import org .springframework .security .oauth2 .server .authorization .OAuth2AuthorizationConsentService ;
42
44
import org .springframework .security .oauth2 .server .authorization .authentication .OAuth2AuthorizationCodeAuthenticationProvider ;
43
45
import org .springframework .security .oauth2 .server .authorization .authentication .OAuth2ClientAuthenticationProvider ;
44
46
import org .springframework .security .oauth2 .server .authorization .authentication .OAuth2ClientCredentialsAuthenticationProvider ;
@@ -107,6 +109,7 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
107
109
this .oidcProviderConfigurationEndpointMatcher .matches (request ) ||
108
110
this .authorizationServerMetadataEndpointMatcher .matches (request ) ||
109
111
this .oidcClientRegistrationEndpointMatcher .matches (request );
112
+ private String consentPage ;
110
113
111
114
/**
112
115
* Sets the repository of registered clients.
@@ -132,6 +135,18 @@ public OAuth2AuthorizationServerConfigurer<B> authorizationService(OAuth2Authori
132
135
return this ;
133
136
}
134
137
138
+ /**
139
+ * Sets the authorization consent service.
140
+ *
141
+ * @param authorizationConsentService the authorization service
142
+ * @return the {@link OAuth2AuthorizationServerConfigurer} for further configuration
143
+ */
144
+ public OAuth2AuthorizationServerConfigurer <B > authorizationConsentService (OAuth2AuthorizationConsentService authorizationConsentService ) {
145
+ Assert .notNull (authorizationConsentService , "authorizationConsentService cannot be null" );
146
+ this .getBuilder ().setSharedObject (OAuth2AuthorizationConsentService .class , authorizationConsentService );
147
+ return this ;
148
+ }
149
+
135
150
/**
136
151
* Sets the provider settings.
137
152
*
@@ -144,6 +159,43 @@ public OAuth2AuthorizationServerConfigurer<B> providerSettings(ProviderSettings
144
159
return this ;
145
160
}
146
161
162
+ /**
163
+ * Specify the URL to redirect Resource Owners to if consent is required during
164
+ * the {@code authorization_code} flow. A default consent page will be generated when
165
+ * this attribute is not specified.
166
+ *
167
+ * If a URL is specified, users are required to process the specified URL to generate
168
+ * a consent page. The query string will contain the following parameters:
169
+ *
170
+ * <ul>
171
+ * <li>{@code client_id} the client identifier</li>
172
+ * <li>{@code scope} the space separated list of scopes present in the authorization request</li>
173
+ * <li>{@code state} a CSRF protection token</li>
174
+ * </ul>
175
+ *
176
+ * In general, the consent page should create a form that submits
177
+ * a request with the following requirements:
178
+ *
179
+ * <ul>
180
+ * <li>It must be an HTTP POST</li>
181
+ * <li>It must be submitted to {@link ProviderSettings#authorizationEndpoint()}</li>
182
+ * <li>It must include the received {@code client_id} as an HTTP parameter</li>
183
+ * <li>It must include the received {@code state} as an HTTP parameter</li>
184
+ * <li>It must include the list of {@code scope}s the {@code Resource Owners}
185
+ * consents to as an HTTP parameter</li>
186
+ * <li>It must include the {@code consent_action} parameter, with value either
187
+ * {@code approve} or {@code cancel} as an HTTP parameter</li>
188
+ * </ul>
189
+ *
190
+ *
191
+ * @param consentPage the consent page to redirect to if consent is required (e.g. "/consent")
192
+ * @return the {@link OAuth2AuthorizationServerConfigurer} for further configuration
193
+ */
194
+ public OAuth2AuthorizationServerConfigurer <B > consentPage (String consentPage ) {
195
+ this .consentPage = consentPage ;
196
+ return this ;
197
+ }
198
+
147
199
/**
148
200
* Returns a {@link RequestMatcher} for the authorization server endpoints.
149
201
*
@@ -263,7 +315,12 @@ public void configure(B builder) {
263
315
new OAuth2AuthorizationEndpointFilter (
264
316
getRegisteredClientRepository (builder ),
265
317
getAuthorizationService (builder ),
266
- providerSettings .authorizationEndpoint ());
318
+ getAuthorizationConsentService (builder ),
319
+ providerSettings .authorizationEndpoint ()
320
+ );
321
+ if (this .consentPage != null ) {
322
+ authorizationEndpointFilter .setUserConsentUri (this .consentPage );
323
+ }
267
324
builder .addFilterBefore (postProcess (authorizationEndpointFilter ), AbstractPreAuthenticatedProcessingFilter .class );
268
325
269
326
OAuth2TokenEndpointFilter tokenEndpointFilter =
@@ -347,6 +404,18 @@ private static <B extends HttpSecurityBuilder<B>> OAuth2AuthorizationService get
347
404
return authorizationService ;
348
405
}
349
406
407
+ private static <B extends HttpSecurityBuilder <B >> OAuth2AuthorizationConsentService getAuthorizationConsentService (B builder ) {
408
+ OAuth2AuthorizationConsentService authorizationConsentService = builder .getSharedObject (OAuth2AuthorizationConsentService .class );
409
+ if (authorizationConsentService == null ) {
410
+ authorizationConsentService = getOptionalBean (builder , OAuth2AuthorizationConsentService .class );
411
+ if (authorizationConsentService == null ) {
412
+ authorizationConsentService = new InMemoryOAuth2AuthorizationConsentService ();
413
+ }
414
+ builder .setSharedObject (OAuth2AuthorizationConsentService .class , authorizationConsentService );
415
+ }
416
+ return authorizationConsentService ;
417
+ }
418
+
350
419
private static <B extends HttpSecurityBuilder <B >> JwtEncoder getJwtEncoder (B builder ) {
351
420
JwtEncoder jwtEncoder = builder .getSharedObject (JwtEncoder .class );
352
421
if (jwtEncoder == null ) {
0 commit comments