diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java index 4b2beaee4..ee06800bf 100644 --- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java +++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at @@ -10,23 +10,14 @@ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ - package org.springframework.security.oauth2.provider.endpoint; -import java.net.URI; -import java.security.Principal; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - import org.springframework.http.ResponseEntity; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException; import org.springframework.security.oauth2.common.exceptions.ClientAuthenticationException; @@ -51,6 +42,7 @@ import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; import org.springframework.security.oauth2.provider.implicit.ImplicitTokenRequest; import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.web.HttpSessionRequiredException; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -68,6 +60,16 @@ import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; +import java.net.URI; +import java.security.Principal; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + /** *

* Implementation of the Authorization Endpoint from the OAuth2 specification. Accepts authorization requests, and @@ -86,8 +88,11 @@ * */ @FrameworkEndpoint -@SessionAttributes("authorizationRequest") +@SessionAttributes({AuthorizationEndpoint.AUTHORIZATION_REQUEST_ATTR_NAME, AuthorizationEndpoint.ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME}) public class AuthorizationEndpoint extends AbstractEndpoint { + static final String AUTHORIZATION_REQUEST_ATTR_NAME = "authorizationRequest"; + + static final String ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME = "org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.ORIGINAL_AUTHORIZATION_REQUEST"; private AuthorizationCodeServices authorizationCodeServices = new InMemoryAuthorizationCodeServices(); @@ -174,10 +179,10 @@ public ModelAndView authorize(Map model, @RequestParam Map model, @RequestParam Map unmodifiableMap(AuthorizationRequest authorizationRequest) { + Map authorizationRequestMap = new HashMap(); + + authorizationRequestMap.put(OAuth2Utils.CLIENT_ID, authorizationRequest.getClientId()); + authorizationRequestMap.put(OAuth2Utils.STATE, authorizationRequest.getState()); + authorizationRequestMap.put(OAuth2Utils.REDIRECT_URI, authorizationRequest.getRedirectUri()); + if (authorizationRequest.getResponseTypes() != null) { + authorizationRequestMap.put(OAuth2Utils.RESPONSE_TYPE, + Collections.unmodifiableSet(new HashSet(authorizationRequest.getResponseTypes()))); + } + if (authorizationRequest.getScope() != null) { + authorizationRequestMap.put(OAuth2Utils.SCOPE, + Collections.unmodifiableSet(new HashSet(authorizationRequest.getScope()))); + } + authorizationRequestMap.put("approved", authorizationRequest.isApproved()); + if (authorizationRequest.getResourceIds() != null) { + authorizationRequestMap.put("resourceIds", + Collections.unmodifiableSet(new HashSet(authorizationRequest.getResourceIds()))); + } + if (authorizationRequest.getAuthorities() != null) { + authorizationRequestMap.put("authorities", + Collections.unmodifiableSet(new HashSet(authorizationRequest.getAuthorities()))); + } + + return Collections.unmodifiableMap(authorizationRequestMap); + } + @RequestMapping(value = "/oauth/authorize", method = RequestMethod.POST, params = OAuth2Utils.USER_OAUTH_APPROVAL) public View approveOrDeny(@RequestParam Map approvalParameters, Map model, SessionStatus sessionStatus, Principal principal) { @@ -199,13 +231,20 @@ public View approveOrDeny(@RequestParam Map approvalParameters, "User must be authenticated with Spring Security before authorizing an access token."); } - AuthorizationRequest authorizationRequest = (AuthorizationRequest) model.get("authorizationRequest"); + AuthorizationRequest authorizationRequest = (AuthorizationRequest) model.get(AUTHORIZATION_REQUEST_ATTR_NAME); if (authorizationRequest == null) { sessionStatus.setComplete(); throw new InvalidRequestException("Cannot approve uninitialized authorization request."); } + // Check to ensure the Authorization Request was not modified during the user approval step + @SuppressWarnings("unchecked") + Map originalAuthorizationRequest = (Map) model.get(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME); + if (isAuthorizationRequestModified(authorizationRequest, originalAuthorizationRequest)) { + throw new InvalidRequestException("Changes were detected from the original authorization request."); + } + try { Set responseTypes = authorizationRequest.getResponseTypes(); @@ -238,6 +277,52 @@ public View approveOrDeny(@RequestParam Map approvalParameters, } + private boolean isAuthorizationRequestModified( + AuthorizationRequest authorizationRequest, Map originalAuthorizationRequest) { + if (!ObjectUtils.nullSafeEquals( + authorizationRequest.getClientId(), + originalAuthorizationRequest.get(OAuth2Utils.CLIENT_ID))) { + return true; + } + if (!ObjectUtils.nullSafeEquals( + authorizationRequest.getState(), + originalAuthorizationRequest.get(OAuth2Utils.STATE))) { + return true; + } + if (!ObjectUtils.nullSafeEquals( + authorizationRequest.getRedirectUri(), + originalAuthorizationRequest.get(OAuth2Utils.REDIRECT_URI))) { + return true; + } + if (!ObjectUtils.nullSafeEquals( + authorizationRequest.getResponseTypes(), + originalAuthorizationRequest.get(OAuth2Utils.RESPONSE_TYPE))) { + return true; + } + if (!ObjectUtils.nullSafeEquals( + authorizationRequest.getScope(), + originalAuthorizationRequest.get(OAuth2Utils.SCOPE))) { + return true; + } + if (!ObjectUtils.nullSafeEquals( + authorizationRequest.isApproved(), + originalAuthorizationRequest.get("approved"))) { + return true; + } + if (!ObjectUtils.nullSafeEquals( + authorizationRequest.getResourceIds(), + originalAuthorizationRequest.get("resourceIds"))) { + return true; + } + if (!ObjectUtils.nullSafeEquals( + authorizationRequest.getAuthorities(), + originalAuthorizationRequest.get("authorities"))) { + return true; + } + + return false; + } + // We need explicit approval from the user. private ModelAndView getUserApprovalPageResponse(Map model, AuthorizationRequest authorizationRequest, Authentication principal) { @@ -529,7 +614,7 @@ private AuthorizationRequest getAuthorizationRequestForError(ServletWebRequest w // If it's already there then we are in the approveOrDeny phase and we can use the saved request AuthorizationRequest authorizationRequest = (AuthorizationRequest) sessionAttributeStore.retrieveAttribute( - webRequest, "authorizationRequest"); + webRequest, AUTHORIZATION_REQUEST_ATTR_NAME); if (authorizationRequest != null) { return authorizationRequest; } diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java index 85a0a6cd6..e42a8c838 100644 --- a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java +++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpointTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2011 the original author or authors. + * Copyright 2006-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at @@ -16,6 +16,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.AUTHORIZATION_REQUEST_ATTR_NAME; +import static org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME; import java.util.Arrays; import java.util.Collections; @@ -29,6 +31,7 @@ import org.junit.Test; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; @@ -152,8 +155,9 @@ public void testStartAuthorizationCodeFlowForClientCredentialsFails() throws Exc @Test public void testAuthorizationCodeWithFragment() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put("authorizationRequest", - getAuthorizationRequest("foo", "http://anywhere.com#bar", null, null, Collections.singleton("code"))); + AuthorizationRequest request = getAuthorizationRequest("foo", "http://anywhere.com#bar", null, null, Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, request); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(request)); View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, principal); assertEquals("http://anywhere.com?code=thecode#bar", ((RedirectView) result).getUrl()); @@ -162,9 +166,9 @@ public void testAuthorizationCodeWithFragment() throws Exception { @Test public void testAuthorizationCodeWithQueryParams() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put( - "authorizationRequest", - getAuthorizationRequest("foo", "http://anywhere.com?foo=bar", null, null, Collections.singleton("code"))); + AuthorizationRequest request = getAuthorizationRequest("foo", "http://anywhere.com?foo=bar", null, null, Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, request); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(request)); View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, principal); assertEquals("http://anywhere.com?foo=bar&code=thecode", ((RedirectView) result).getUrl()); @@ -173,8 +177,9 @@ public void testAuthorizationCodeWithQueryParams() throws Exception { @Test public void testAuthorizationCodeWithTrickyState() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put("authorizationRequest", - getAuthorizationRequest("foo", "http://anywhere.com", " =?s", null, Collections.singleton("code"))); + AuthorizationRequest request = getAuthorizationRequest("foo", "http://anywhere.com", " =?s", null, Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, request); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(request)); View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, principal); assertEquals("http://anywhere.com?code=thecode&state=%20%3D?s", ((RedirectView) result).getUrl()); @@ -183,10 +188,10 @@ public void testAuthorizationCodeWithTrickyState() throws Exception { @Test public void testAuthorizationCodeWithMultipleQueryParams() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put( - "authorizationRequest", - getAuthorizationRequest("foo", "http://anywhere.com?foo=bar&bar=foo", null, null, - Collections.singleton("code"))); + AuthorizationRequest request = getAuthorizationRequest("foo", "http://anywhere.com?foo=bar&bar=foo", null, null, + Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, request); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(request)); View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, principal); assertEquals("http://anywhere.com?foo=bar&bar=foo&code=thecode", ((RedirectView) result).getUrl()); @@ -195,10 +200,10 @@ public void testAuthorizationCodeWithMultipleQueryParams() throws Exception { @Test public void testAuthorizationCodeWithTrickyQueryParams() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put( - "authorizationRequest", - getAuthorizationRequest("foo", "http://anywhere.com?foo=b =&bar=f $", null, null, - Collections.singleton("code"))); + AuthorizationRequest request = getAuthorizationRequest("foo", "http://anywhere.com?foo=b =&bar=f $", null, null, + Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, request); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(request)); View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, principal); String url = ((RedirectView) result).getUrl(); @@ -211,10 +216,10 @@ public void testAuthorizationCodeWithTrickyQueryParams() throws Exception { @Test public void testAuthorizationCodeWithTrickyEncodedQueryParams() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put( - "authorizationRequest", - getAuthorizationRequest("foo", "http://anywhere.com/path?foo=b%20%3D&bar=f%20$", null, null, - Collections.singleton("code"))); + AuthorizationRequest request = getAuthorizationRequest( + "foo", "http://anywhere.com/path?foo=b%20%3D&bar=f%20$", null, null, Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, request); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(request)); View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, principal); assertEquals("http://anywhere.com/path?foo=b%20%3D&bar=f%20$&code=thecode", ((RedirectView) result).getUrl()); @@ -223,10 +228,10 @@ public void testAuthorizationCodeWithTrickyEncodedQueryParams() throws Exception @Test public void testAuthorizationCodeWithMoreTrickyEncodedQueryParams() throws Exception { endpoint.setAuthorizationCodeServices(new StubAuthorizationCodeServices()); - model.put( - "authorizationRequest", - getAuthorizationRequest("foo", "http://anywhere?t=a%3Db%26ep%3Dtest%2540test.me", null, null, - Collections.singleton("code"))); + AuthorizationRequest request = getAuthorizationRequest( + "foo", "http://anywhere?t=a%3Db%26ep%3Dtest%2540test.me", null, null, Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, request); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(request)); View result = endpoint.approveOrDeny(Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, "true"), model, sessionStatus, principal); assertEquals("http://anywhere?t=a%3Db%26ep%3Dtest%2540test.me&code=thecode", ((RedirectView) result).getUrl()); @@ -508,15 +513,17 @@ public void testApproveOrDeny() throws Exception { request.setApproved(true); Map approvalParameters = new HashMap(); approvalParameters.put("user_oauth_approval", "true"); - model.put("authorizationRequest", request); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, request); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(request)); View result = endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); assertTrue("Wrong view: " + result, ((RedirectView) result).getUrl().startsWith("http://anywhere.com")); } @Test public void testApprovalDenied() throws Exception { - model.put("authorizationRequest", - getAuthorizationRequest("foo", "http://anywhere.com", null, null, Collections.singleton("code"))); + AuthorizationRequest request = getAuthorizationRequest("foo", "http://anywhere.com", null, null, Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, request); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(request)); Map approvalParameters = new HashMap(); approvalParameters.put("user_oauth_approval", "false"); View result = endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); @@ -541,7 +548,7 @@ public void testRedirectUriOptionalForAuthorization() throws Exception { .getRequestParameters(), sessionStatus, principal); // RedirectUri parameter should be null (SECOAUTH-333), however the resolvedRedirectUri not AuthorizationRequest authorizationRequest = (AuthorizationRequest) result.getModelMap().get( - "authorizationRequest"); + AUTHORIZATION_REQUEST_ATTR_NAME); assertNull(authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI)); assertEquals("http://anywhere.com", authorizationRequest.getRedirectUri()); } @@ -556,9 +563,107 @@ public void testApproveOrDenyWithOAuth2RequestWithoutRedirectUri() throws Except request.setApproved(true); Map approvalParameters = new HashMap(); approvalParameters.put("user_oauth_approval", "true"); - model.put("authorizationRequest", request); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, request); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(request)); + endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); + + } + + @Test(expected = InvalidRequestException.class) + public void testApproveWithModifiedClientId() throws Exception { + AuthorizationRequest authorizationRequest = getAuthorizationRequest( + "foo", "http://anywhere.com", "state-1234", "read", Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, authorizationRequest); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(authorizationRequest)); + authorizationRequest.setClientId("bar"); // Modify authorization request + Map approvalParameters = new HashMap(); + approvalParameters.put("user_oauth_approval", "true"); + endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); + } + + @Test(expected = InvalidRequestException.class) + public void testApproveWithModifiedState() throws Exception { + AuthorizationRequest authorizationRequest = getAuthorizationRequest( + "foo", "http://anywhere.com", "state-1234", "read", Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, authorizationRequest); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(authorizationRequest)); + authorizationRequest.setState("state-5678"); // Modify authorization request + Map approvalParameters = new HashMap(); + approvalParameters.put("user_oauth_approval", "true"); + endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); + } + + @Test(expected = InvalidRequestException.class) + public void testApproveWithModifiedRedirectUri() throws Exception { + AuthorizationRequest authorizationRequest = getAuthorizationRequest( + "foo", "http://anywhere.com", "state-1234", "read", Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, authorizationRequest); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(authorizationRequest)); + authorizationRequest.setRedirectUri("http://somewhere.com"); // Modify authorization request + Map approvalParameters = new HashMap(); + approvalParameters.put("user_oauth_approval", "true"); + endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); + } + + @Test(expected = InvalidRequestException.class) + public void testApproveWithModifiedResponseTypes() throws Exception { + AuthorizationRequest authorizationRequest = getAuthorizationRequest( + "foo", "http://anywhere.com", "state-1234", "read", Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, authorizationRequest); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(authorizationRequest)); + authorizationRequest.setResponseTypes(Collections.singleton("implicit")); // Modify authorization request + Map approvalParameters = new HashMap(); + approvalParameters.put("user_oauth_approval", "true"); endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); + } + @Test(expected = InvalidRequestException.class) + public void testApproveWithModifiedScope() throws Exception { + AuthorizationRequest authorizationRequest = getAuthorizationRequest( + "foo", "http://anywhere.com", "state-1234", "read", Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, authorizationRequest); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(authorizationRequest)); + authorizationRequest.setScope(Arrays.asList("read", "write")); // Modify authorization request + Map approvalParameters = new HashMap(); + approvalParameters.put("user_oauth_approval", "true"); + endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); + } + + @Test(expected = InvalidRequestException.class) + public void testApproveWithModifiedApproved() throws Exception { + AuthorizationRequest authorizationRequest = getAuthorizationRequest( + "foo", "http://anywhere.com", "state-1234", "read", Collections.singleton("code")); + authorizationRequest.setApproved(false); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, authorizationRequest); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(authorizationRequest)); + authorizationRequest.setApproved(true); // Modify authorization request + Map approvalParameters = new HashMap(); + approvalParameters.put("user_oauth_approval", "true"); + endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); + } + + @Test(expected = InvalidRequestException.class) + public void testApproveWithModifiedResourceIds() throws Exception { + AuthorizationRequest authorizationRequest = getAuthorizationRequest( + "foo", "http://anywhere.com", "state-1234", "read", Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, authorizationRequest); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(authorizationRequest)); + authorizationRequest.setResourceIds(Collections.singleton("resource-other")); // Modify authorization request + Map approvalParameters = new HashMap(); + approvalParameters.put("user_oauth_approval", "true"); + endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); + } + + @Test(expected = InvalidRequestException.class) + public void testApproveWithModifiedAuthorities() throws Exception { + AuthorizationRequest authorizationRequest = getAuthorizationRequest( + "foo", "http://anywhere.com", "state-1234", "read", Collections.singleton("code")); + model.put(AUTHORIZATION_REQUEST_ATTR_NAME, authorizationRequest); + model.put(ORIGINAL_AUTHORIZATION_REQUEST_ATTR_NAME, endpoint.unmodifiableMap(authorizationRequest)); + authorizationRequest.setAuthorities(AuthorityUtils.commaSeparatedStringToAuthorityList("authority-other")); // Modify authorization request + Map approvalParameters = new HashMap(); + approvalParameters.put("user_oauth_approval", "true"); + endpoint.approveOrDeny(approvalParameters, model, sessionStatus, principal); } private class StubAuthorizationCodeServices implements AuthorizationCodeServices {