separated claims processing out into its own service, closes #796

pull/708/merge
Justin Richer 10 years ago
parent b811594ad4
commit 7951ff5086

@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright 2015 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on 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.mitre.uma.service;
import java.util.Collection;
import org.mitre.uma.model.Claim;
/**
*
* Processes claims presented during an UMA transaction.
*
* @author jricher
*
*/
public interface ClaimsProcessingService {
/**
*
* Determine whether or not the claims that have been supplied are
* sufficient to fulfill the requirements given by the claims that
* are required.
*
* @param claimsRequired the required claims to check against
* @param claimsSupplied the supplied claims to test
* @return the unmatched claims (if any), an empty set if the claims are satisfied, never null
*/
public Collection<Claim> claimsAreSatisfied(Collection<Claim> claimsRequired, Collection<Claim> claimsSupplied);
}

@ -0,0 +1,65 @@
/*******************************************************************************
* Copyright 2015 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on 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.mitre.uma.service;
import java.util.Collection;
import java.util.HashSet;
import org.mitre.uma.model.Claim;
import org.springframework.stereotype.Service;
/**
* Tests if all the claims in the required set have a matching
* value in the supplied set.
*
* @author jricher
*
*/
@Service("matchAllClaimsProcessor")
public class MatchAllClaimsProcessor implements ClaimsProcessingService {
@Override
public Collection<Claim> claimsAreSatisfied(Collection<Claim> claimsRequired, Collection<Claim> claimsSupplied) {
Collection<Claim> claimsUnmatched = new HashSet<>(claimsRequired);
// see if each of the required claims has a counterpart in the supplied claims set
for (Claim required : claimsRequired) {
for (Claim supplied : claimsSupplied) {
if (required.getIssuer().containsAll(supplied.getIssuer())) {
// it's from the right issuer
if (required.getName().equals(supplied.getName()) &&
required.getValue().equals(supplied.getValue())) {
// the claim matched, pull it from the set
claimsUnmatched.remove(required);
}
}
}
}
// if there's anything left then the claims aren't satisfied, return the leftovers
return claimsUnmatched;
}
}

@ -18,6 +18,7 @@
package org.mitre.uma.web; package org.mitre.uma.web;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -40,6 +41,7 @@ import org.mitre.openid.connect.view.JsonErrorView;
import org.mitre.uma.model.Claim; import org.mitre.uma.model.Claim;
import org.mitre.uma.model.PermissionTicket; import org.mitre.uma.model.PermissionTicket;
import org.mitre.uma.model.ResourceSet; import org.mitre.uma.model.ResourceSet;
import org.mitre.uma.service.ClaimsProcessingService;
import org.mitre.uma.service.PermissionService; import org.mitre.uma.service.PermissionService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -105,6 +107,9 @@ public class AuthorizationRequestEndpoint {
@Autowired @Autowired
private WebResponseExceptionTranslator providerExceptionHandler; private WebResponseExceptionTranslator providerExceptionHandler;
@Autowired
private ClaimsProcessingService claimsProcessingService;
@RequestMapping(method = RequestMethod.POST, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) @RequestMapping(method = RequestMethod.POST, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
public String authorizationRequest(@RequestBody String jsonString, Model m, Authentication auth) { public String authorizationRequest(@RequestBody String jsonString, Model m, Authentication auth) {
@ -132,37 +137,18 @@ public class AuthorizationRequestEndpoint {
// found the ticket, see if it's any good // found the ticket, see if it's any good
ResourceSet rs = ticket.getPermission().getResourceSet(); ResourceSet rs = ticket.getPermission().getResourceSet();
Collection<Claim> claimsRequired = rs.getClaimsRequired();
Collection<Claim> claimsSupplied = ticket.getClaimsSupplied();
Collection<Claim> claimsUnmatched = new HashSet<>(claimsRequired);
// see if each of the required claims has a counterpart in the supplied claims set
// TODO: move this component to a claims checking service (#796)
for (Claim required : claimsRequired) {
for (Claim supplied : claimsSupplied) {
if (required.getIssuer().containsAll(supplied.getIssuer())) {
// it's from the right issuer
if (required.getName().equals(supplied.getName()) && if (rs.getClaimsRequired() == null || rs.getClaimsRequired().isEmpty()) {
required.getValue().equals(supplied.getValue())) { // the required claims are empty, this resource has no way to be authorized
// the claim matched, pull it from the set m.addAttribute(JsonErrorView.ERROR, "not_authorized");
claimsUnmatched.remove(required); m.addAttribute(JsonErrorView.ERROR_MESSAGE, "This resource set can not be accessed.");
m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
}
}
}
} }
// note that if the required claims are empty we don't want to return a token Collection<Claim> claimsUnmatched = claimsProcessingService.claimsAreSatisfied(rs.getClaimsRequired(), ticket.getClaimsSupplied());
if (!claimsRequired.isEmpty() && claimsUnmatched.isEmpty()) {
// we matched all the claims, create and return the token
if (claimsUnmatched.isEmpty()) {
// TODO: move this whole mess to the OIDCTokenService (#797) // TODO: move this whole mess to the OIDCTokenService (#797)

Loading…
Cancel
Save