Polish authorization consent

Issue gh-340 gh-280
This commit is contained in:
Joe Grandja
2021-07-06 06:34:35 -04:00
parent 08ba07d676
commit 4517022f36
5 changed files with 20 additions and 23 deletions

View File

@@ -158,7 +158,7 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
*
* <ul>
* <li>{@code client_id} - the client identifier</li>
* <li>{@code scope} - the space separated list of scopes present in the authorization request</li>
* <li>{@code scope} - a space-delimited list of scopes present in the authorization request</li>
* <li>{@code state} - a CSRF protection token</li>
* </ul>
*
@@ -172,11 +172,9 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
* <li>It must include the received {@code state} as an HTTP parameter</li>
* <li>It must include the list of {@code scope}s the {@code Resource Owner}
* consented to as an HTTP parameter</li>
* <li>It must include the {@code consent_action} parameter, with a value either
* {@code approve} or {@code cancel} as an HTTP parameter</li>
* </ul>
*
* @param consentPage the consent page to redirect to if consent is required (e.g. "/oauth2/consent")
* @param consentPage the URI of the custom consent page to redirect to if consent is required (e.g. "/oauth2/consent")
* @return the {@link OAuth2AuthorizationServerConfigurer} for further configuration
*/
public OAuth2AuthorizationServerConfigurer<B> consentPage(String consentPage) {
@@ -296,7 +294,7 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
authenticationManager,
providerSettings.authorizationEndpoint());
if (StringUtils.hasText(this.consentPage)) {
authorizationEndpointFilter.setUserConsentUri(this.consentPage);
authorizationEndpointFilter.setConsentPage(this.consentPage);
}
builder.addFilterBefore(postProcess(authorizationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);

View File

@@ -90,7 +90,7 @@ public class OAuth2AuthorizationEndpointFilter extends OncePerRequestFilter {
private final RequestMatcher authorizationEndpointMatcher;
private final AuthenticationConverter authenticationConverter;
private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
private String userConsentUri;
private String consentPage;
/**
* Constructs an {@code OAuth2AuthorizationEndpointFilter} using the provided parameters.
@@ -168,11 +168,11 @@ public class OAuth2AuthorizationEndpointFilter extends OncePerRequestFilter {
* Specify the URI to redirect Resource Owners to if consent is required. A default consent
* page will be generated when this attribute is not specified.
*
* @param userConsentUri the URI of the custom consent page to redirect to if consent is required (e.g. "/oauth2/consent")
* @param consentPage the URI of the custom consent page to redirect to if consent is required (e.g. "/oauth2/consent")
* @see org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer#consentPage(String)
*/
public final void setUserConsentUri(String userConsentUri) {
this.userConsentUri = userConsentUri;
public final void setConsentPage(String consentPage) {
this.consentPage = consentPage;
}
@Override
@@ -230,24 +230,24 @@ public class OAuth2AuthorizationEndpointFilter extends OncePerRequestFilter {
.toUriString();
this.redirectStrategy.sendRedirect(request, response, redirectUri);
} else {
UserConsentPage.displayConsent(request, response, clientId, principal, requestedScopes, authorizedScopes, state);
DefaultConsentPage.displayConsent(request, response, clientId, principal, requestedScopes, authorizedScopes, state);
}
}
private boolean hasConsentUri() {
return StringUtils.hasText(this.userConsentUri);
return StringUtils.hasText(this.consentPage);
}
private String resolveConsentUri(HttpServletRequest request) {
if (UrlUtils.isAbsoluteUrl(this.userConsentUri)) {
return this.userConsentUri;
if (UrlUtils.isAbsoluteUrl(this.consentPage)) {
return this.consentPage;
}
RedirectUrlBuilder urlBuilder = new RedirectUrlBuilder();
urlBuilder.setScheme(request.getScheme());
urlBuilder.setServerName(request.getServerName());
urlBuilder.setPort(request.getServerPort());
urlBuilder.setContextPath(request.getContextPath());
urlBuilder.setPathInfo(this.userConsentUri);
urlBuilder.setPathInfo(this.consentPage);
return urlBuilder.getUrl();
}
@@ -427,7 +427,7 @@ public class OAuth2AuthorizationEndpointFilter extends OncePerRequestFilter {
/**
* For internal use only.
*/
private static class UserConsentPage {
private static class DefaultConsentPage {
private static final MediaType TEXT_HTML_UTF8 = new MediaType("text", "html", StandardCharsets.UTF_8);
private static void displayConsent(HttpServletRequest request, HttpServletResponse response,
@@ -485,7 +485,7 @@ public class OAuth2AuthorizationEndpointFilter extends OncePerRequestFilter {
for (String scope : scopesToAuthorize) {
builder.append(" <div class=\"form-group form-check py-1\">");
builder.append(" <input class=\"form-check-input\" type=\"checkbox\" name=\"scope\" value=\"" + scope + "\" id=\"" + scope + "\" checked>");
builder.append(" <input class=\"form-check-input\" type=\"checkbox\" name=\"scope\" value=\"" + scope + "\" id=\"" + scope + "\">");
builder.append(" <label class=\"form-check-label\" for=\"" + scope + "\">" + scope + "</label>");
builder.append(" </div>");
}

View File

@@ -501,7 +501,7 @@ public class OAuth2AuthorizationCodeGrantTests {
private static String scopeCheckbox(String scope) {
return MessageFormat.format(
"<input class=\"form-check-input\" type=\"checkbox\" name=\"scope\" value=\"{0}\" id=\"{0}\" checked>",
"<input class=\"form-check-input\" type=\"checkbox\" name=\"scope\" value=\"{0}\" id=\"{0}\">",
scope
);
}

View File

@@ -285,7 +285,7 @@ public class OAuth2AuthorizationEndpointFilterTests {
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);
this.filter.setUserConsentUri("/oauth2/custom-consent");
this.filter.setConsentPage("/oauth2/custom-consent");
this.filter.doFilter(request, response, filterChain);
verify(this.authenticationManager).authenticate(any());
@@ -471,7 +471,7 @@ public class OAuth2AuthorizationEndpointFilterTests {
private static String scopeCheckbox(String scope) {
return MessageFormat.format(
"<input class=\"form-check-input\" type=\"checkbox\" name=\"scope\" value=\"{0}\" id=\"{0}\" checked>",
"<input class=\"form-check-input\" type=\"checkbox\" name=\"scope\" value=\"{0}\" id=\"{0}\">",
scope
);
}

View File

@@ -42,8 +42,7 @@
type="checkbox"
name="scope"
th:value="${scope.scope}"
th:id="${scope.scope}"
checked>
th:id="${scope.scope}">
<label class="form-check-label font-weight-bold" th:for="${scope.scope}" th:text="${scope.scope}"></label>
<p class="text-primary" th:text="${scope.description}"></p>
</div>
@@ -60,12 +59,12 @@
</div>
<div class="form-group pt-3">
<button class="btn btn-primary btn-lg" type="submit" name="consent_action" value="approve">
<button class="btn btn-primary btn-lg" type="submit">
Submit Consent
</button>
</div>
<div class="form-group">
<button class="btn btn-link regular" type="submit" name="consent_action" value="cancel">
<button class="btn btn-link regular" type="submit">
Cancel
</button>
</div>