use of org.springframework.security.oauth2.provider.approval.Approval in project uaa by cloudfoundry.
the class UaaAuthorizationEndpoint method authorize.
@RequestMapping(value = "/oauth/authorize")
public ModelAndView authorize(Map<String, Object> model, @RequestParam Map<String, String> parameters, SessionStatus sessionStatus, Principal principal, HttpServletRequest request) {
ClientDetails client;
String clientId;
try {
clientId = parameters.get("client_id");
client = loadClientByClientId(clientId);
} catch (NoSuchClientException x) {
throw new InvalidClientException(x.getMessage());
}
// Pull out the authorization request first, using the OAuth2RequestFactory. All further logic should
// query off of the authorization request instead of referring back to the parameters map. The contents of the
// parameters map will be stored without change in the AuthorizationRequest object once it is created.
AuthorizationRequest authorizationRequest;
try {
authorizationRequest = getOAuth2RequestFactory().createAuthorizationRequest(parameters);
} catch (DisallowedIdpException x) {
return switchIdp(model, client, clientId, request);
}
Set<String> responseTypes = authorizationRequest.getResponseTypes();
String grantType = deriveGrantTypeFromResponseType(responseTypes);
if (!supported_response_types.containsAll(responseTypes)) {
throw new UnsupportedResponseTypeException("Unsupported response types: " + responseTypes);
}
if (authorizationRequest.getClientId() == null) {
throw new InvalidClientException("A client id must be provided");
}
String resolvedRedirect = "";
try {
String redirectUriParameter = authorizationRequest.getRequestParameters().get(OAuth2Utils.REDIRECT_URI);
try {
resolvedRedirect = redirectResolver.resolveRedirect(redirectUriParameter, client);
} catch (RedirectMismatchException rme) {
throw new RedirectMismatchException("Invalid redirect " + redirectUriParameter + " did not match one of the registered values");
}
if (!StringUtils.hasText(resolvedRedirect)) {
throw new RedirectMismatchException("A redirectUri must be either supplied or preconfigured in the ClientDetails");
}
boolean isAuthenticated = (principal instanceof Authentication) && ((Authentication) principal).isAuthenticated();
if (!isAuthenticated) {
throw new InsufficientAuthenticationException("User must be authenticated with Spring Security before authorization can be completed.");
}
if (!(responseTypes.size() > 0)) {
return new ModelAndView(new RedirectView(addQueryParameter(addQueryParameter(resolvedRedirect, "error", "invalid_request"), "error_description", "Missing response_type in authorization request")));
}
authorizationRequest.setRedirectUri(resolvedRedirect);
// We intentionally only validate the parameters requested by the client (ignoring any data that may have
// been added to the request by the manager).
oauth2RequestValidator.validateScope(authorizationRequest, client);
// Some systems may allow for approval decisions to be remembered or approved by default. Check for
// such logic here, and set the approved flag on the authorization request accordingly.
authorizationRequest = userApprovalHandler.checkForPreApproval(authorizationRequest, (Authentication) principal);
boolean approved = userApprovalHandler.isApproved(authorizationRequest, (Authentication) principal);
authorizationRequest.setApproved(approved);
// Validation is all done, so we can check for auto approval...
if (authorizationRequest.isApproved()) {
if (responseTypes.contains("token") || responseTypes.contains("id_token")) {
return getImplicitGrantOrHybridResponse(authorizationRequest, (Authentication) principal, grantType);
}
if (responseTypes.contains("code")) {
return new ModelAndView(getAuthorizationCodeResponse(authorizationRequest, (Authentication) principal));
}
}
if ("none".equals(authorizationRequest.getRequestParameters().get("prompt"))) {
return new ModelAndView(new RedirectView(addFragmentComponent(resolvedRedirect, "error=interaction_required")));
} else {
// Place auth request into the model so that it is stored in the session
// for approveOrDeny to use. That way we make sure that auth request comes from the session,
// so any auth request parameters passed to approveOrDeny will be ignored and retrieved from the session.
model.put(AUTHORIZATION_REQUEST, authorizationRequest);
model.put("original_uri", UrlUtils.buildFullRequestUrl(request));
model.put(ORIGINAL_AUTHORIZATION_REQUEST, unmodifiableMap(authorizationRequest));
return getUserApprovalPageResponse(model, authorizationRequest, (Authentication) principal);
}
} catch (RedirectMismatchException e) {
sessionStatus.setComplete();
throw e;
} catch (Exception e) {
sessionStatus.setComplete();
logger.debug("Unable to handle /oauth/authorize, internal error", e);
if ("none".equals(authorizationRequest.getRequestParameters().get("prompt"))) {
return new ModelAndView(new RedirectView(addFragmentComponent(resolvedRedirect, "error=internal_server_error")));
}
throw e;
}
}
use of org.springframework.security.oauth2.provider.approval.Approval in project uaa by cloudfoundry.
the class AccessController method confirm.
@RequestMapping("/oauth/confirm_access")
public String confirm(Map<String, Object> model, final HttpServletRequest request, Principal principal, SessionStatus sessionStatus) {
if (!(principal instanceof Authentication)) {
sessionStatus.setComplete();
throw new InsufficientAuthenticationException("User must be authenticated with before authorizing access.");
}
AuthorizationRequest clientAuthRequest = (AuthorizationRequest) model.remove(UaaAuthorizationEndpoint.AUTHORIZATION_REQUEST);
if (clientAuthRequest == null) {
model.put("error", "No authorization request is present, so we cannot confirm access (we don't know what you are asking for).");
} else {
String clientId = clientAuthRequest.getClientId();
BaseClientDetails client = (BaseClientDetails) clientDetailsService.loadClientByClientId(clientId, IdentityZoneHolder.get().getId());
BaseClientDetails modifiableClient = new BaseClientDetails(client);
modifiableClient.setClientSecret(null);
model.put("auth_request", clientAuthRequest);
model.put("redirect_uri", getRedirectUri(modifiableClient, clientAuthRequest));
Map<String, Object> additionalInfo = client.getAdditionalInformation();
String clientDisplayName = (String) additionalInfo.get(ClientConstants.CLIENT_NAME);
model.put("client_display_name", (clientDisplayName != null) ? clientDisplayName : clientId);
// Find the auto approved scopes for this clients
Set<String> autoApproved = client.getAutoApproveScopes();
Set<String> autoApprovedScopes = new HashSet<>();
if (autoApproved != null) {
if (autoApproved.contains("true")) {
autoApprovedScopes.addAll(client.getScope());
} else {
autoApprovedScopes.addAll(autoApproved);
}
}
List<Approval> filteredApprovals = new ArrayList<Approval>();
// Remove auto approved scopes
List<Approval> approvals = approvalStore.getApprovals(Origin.getUserId((Authentication) principal), clientId, IdentityZoneHolder.get().getId());
for (Approval approval : approvals) {
if (!(autoApprovedScopes.contains(approval.getScope()))) {
filteredApprovals.add(approval);
}
}
ArrayList<String> approvedScopes = new ArrayList<String>();
ArrayList<String> deniedScopes = new ArrayList<String>();
for (Approval approval : filteredApprovals) {
switch(approval.getStatus()) {
case APPROVED:
approvedScopes.add(approval.getScope());
break;
case DENIED:
deniedScopes.add(approval.getScope());
break;
default:
logger.error("Encountered an unknown scope. This is not supposed to happen");
break;
}
}
ArrayList<String> undecidedScopes = new ArrayList<String>();
// Filter the scopes approved/denied from the ones requested
for (String scope : clientAuthRequest.getScope()) {
if (!approvedScopes.contains(scope) && !deniedScopes.contains(scope) && !autoApprovedScopes.contains(scope)) {
undecidedScopes.add(scope);
}
}
List<Map<String, String>> approvedScopeDetails = getScopes(approvedScopes);
model.put("approved_scopes", approvedScopeDetails);
List<Map<String, String>> undecidedScopeDetails = getScopes(undecidedScopes);
model.put("undecided_scopes", undecidedScopeDetails);
List<Map<String, String>> deniedScopeDetails = getScopes(deniedScopes);
model.put("denied_scopes", deniedScopeDetails);
List<Map<String, String>> allScopes = new ArrayList<>();
allScopes.addAll(approvedScopeDetails);
allScopes.addAll(undecidedScopeDetails);
allScopes.addAll(deniedScopeDetails);
model.put("scopes", allScopes);
model.put("message", "To confirm or deny access POST to the following locations with the parameters requested.");
Map<String, Object> options = new HashMap<String, Object>() {
{
put("confirm", new HashMap<String, String>() {
{
put("location", getLocation(request, "oauth/authorize"));
put("path", getPath(request, "oauth/authorize"));
put("key", OAuth2Utils.USER_OAUTH_APPROVAL);
put("value", "true");
}
});
put("deny", new HashMap<String, String>() {
{
put("location", getLocation(request, "oauth/authorize"));
put("path", getPath(request, "oauth/authorize"));
put("key", OAuth2Utils.USER_OAUTH_APPROVAL);
put("value", "false");
}
});
}
};
model.put("options", options);
}
return "access_confirmation";
}
use of org.springframework.security.oauth2.provider.approval.Approval in project uaa by cloudfoundry.
the class UserManagedAuthzApprovalHandler method isApproved.
@Override
public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) {
String approvalParameter1 = OAuth2Utils.USER_OAUTH_APPROVAL;
String flag = authorizationRequest.getApprovalParameters().get(approvalParameter1);
boolean userApproval = flag != null && flag.toLowerCase().equals("true");
if (logger.isDebugEnabled()) {
StringBuilder builder = new StringBuilder("Looking up user approved authorizations for ");
builder.append("client_id=").append(authorizationRequest.getClientId());
builder.append(" and username=").append(userAuthentication.getName());
logger.debug(builder.toString());
}
Collection<String> requestedScopes = authorizationRequest.getScope();
// Factor in auto approved scopes
Set<String> autoApprovedScopes = new HashSet<>();
BaseClientDetails client = (BaseClientDetails) clientDetailsService.retrieve(authorizationRequest.getClientId(), identityZoneManager.getCurrentIdentityZoneId());
if (client != null && requestedScopes != null) {
autoApprovedScopes.addAll(client.getAutoApproveScopes());
autoApprovedScopes = UaaTokenUtils.retainAutoApprovedScopes(requestedScopes, autoApprovedScopes);
}
// TODO: the "true" case is not tested
if (userApproval) {
// Store the scopes that have been approved / denied
Date expiry = computeExpiry();
// Get the approved scopes, calculate the denied scope
Map<String, String> approvalParameters = authorizationRequest.getApprovalParameters();
Set<String> approvedScopes = new HashSet<>(autoApprovedScopes);
boolean foundUserApprovalParameter = false;
for (String approvalParameter : approvalParameters.keySet()) {
if (approvalParameter.startsWith(SCOPE_PREFIX)) {
approvedScopes.add(approvalParameters.get(approvalParameter).substring(SCOPE_PREFIX.length()));
foundUserApprovalParameter = true;
}
}
if (foundUserApprovalParameter) {
authorizationRequest.setScope(approvedScopes);
for (String requestedScope : requestedScopes) {
if (approvedScopes.contains(requestedScope)) {
Approval approval = new Approval().setUserId(getUserId(userAuthentication)).setClientId(authorizationRequest.getClientId()).setScope(requestedScope).setExpiresAt(expiry).setStatus(APPROVED);
approvalStore.addApproval(approval, identityZoneManager.getCurrentIdentityZoneId());
} else {
Approval approval = new Approval().setUserId(getUserId(userAuthentication)).setClientId(authorizationRequest.getClientId()).setScope(requestedScope).setExpiresAt(expiry).setStatus(DENIED);
approvalStore.addApproval(approval, identityZoneManager.getCurrentIdentityZoneId());
}
}
} else {
// Deny all except auto approved scopes
authorizationRequest.setScope(autoApprovedScopes);
for (String requestedScope : requestedScopes) {
if (!autoApprovedScopes.contains(requestedScope)) {
Approval approval = new Approval().setUserId(getUserId(userAuthentication)).setClientId(authorizationRequest.getClientId()).setScope(requestedScope).setExpiresAt(expiry).setStatus(DENIED);
approvalStore.addApproval(approval, identityZoneManager.getCurrentIdentityZoneId());
}
}
}
return userAuthentication.isAuthenticated();
} else {
// Find the stored approvals for that user and client
List<Approval> userApprovals = approvalStore.getApprovals(getUserId(userAuthentication), authorizationRequest.getClientId(), identityZoneManager.getCurrentIdentityZoneId());
// Look at the scopes and see if they have expired
Set<String> approvedScopes = new HashSet<>(autoApprovedScopes);
Set<String> validUserApprovedScopes = new HashSet<>(autoApprovedScopes);
Date today = new Date();
for (Approval approval : userApprovals) {
if (approval.getExpiresAt().after(today)) {
validUserApprovedScopes.add(approval.getScope());
if (approval.getStatus() == APPROVED) {
approvedScopes.add(approval.getScope());
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("Valid user approved/denied scopes are " + validUserApprovedScopes);
}
// this request is approved
if (validUserApprovedScopes.containsAll(requestedScopes) && userAuthentication.isAuthenticated()) {
approvedScopes = UaaTokenUtils.retainAutoApprovedScopes(requestedScopes, approvedScopes);
// Set only the scopes that have been approved by the user
authorizationRequest.setScope(approvedScopes);
return true;
}
}
return false;
}
use of org.springframework.security.oauth2.provider.approval.Approval in project uaa by cloudfoundry.
the class UserManagedAuthzApprovalHandlerTests method onlySomeRequestedScopeMatchesApproval.
@Test
void onlySomeRequestedScopeMatchesApproval() {
AuthorizationRequest request = new AuthorizationRequest("foo", new HashSet<>(Arrays.asList("openid", "cloud_controller.read")));
request.setApproved(false);
approvalStore.addApproval(new Approval().setUserId(userId).setClientId("foo").setScope("cloud_controller.read").setExpiresAt(nextWeek).setStatus(APPROVED), currentIdentityZoneId);
approvalStore.addApproval(new Approval().setUserId(userId).setClientId("foo").setScope("cloud_controller.write").setExpiresAt(nextWeek).setStatus(DENIED), currentIdentityZoneId);
// The request is not approved because the user has not yet approved all
// the scopes requested
assertFalse(handler.isApproved(request, mockAuthentication));
}
use of org.springframework.security.oauth2.provider.approval.Approval in project uaa by cloudfoundry.
the class UserManagedAuthzApprovalHandlerTests method someRequestedScopesMatchApproval.
@Test
void someRequestedScopesMatchApproval() {
AuthorizationRequest request = new AuthorizationRequest("foo", new HashSet<>(Collections.singletonList("openid")));
request.setApproved(false);
approvalStore.addApproval(new Approval().setUserId(userId).setClientId("foo").setScope("openid").setExpiresAt(nextWeek).setStatus(APPROVED), currentIdentityZoneId);
approvalStore.addApproval(new Approval().setUserId(userId).setClientId("foo").setScope("cloud_controller.read").setExpiresAt(nextWeek).setStatus(APPROVED), currentIdentityZoneId);
approvalStore.addApproval(new Approval().setUserId(userId).setClientId("foo").setScope("cloud_controller.write").setExpiresAt(nextWeek).setStatus(APPROVED), currentIdentityZoneId);
// The request is approved because the user has approved all the scopes
// requested
assertTrue(handler.isApproved(request, mockAuthentication));
assertEquals(new HashSet<>(Collections.singletonList("openid")), request.getScope());
}
Aggregations