/*
* oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
*
* Copyright (c) 2014, Gluu
*/
package org.xdi.oxauth.service.uma.resourceserver;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.Response;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.xdi.oxauth.model.common.uma.UmaRPT;
import org.xdi.oxauth.model.configuration.AppConfiguration;
import org.xdi.oxauth.model.registration.Client;
import org.xdi.oxauth.model.uma.PermissionTicket;
import org.xdi.oxauth.model.uma.UmaPermission;
import org.xdi.oxauth.model.uma.persistence.ResourceSet;
import org.xdi.oxauth.model.uma.persistence.ResourceSetPermission;
import org.xdi.oxauth.service.ClientService;
import org.xdi.oxauth.service.token.TokenService;
import org.xdi.oxauth.service.uma.ResourceSetPermissionManager;
import org.xdi.oxauth.util.ServerUtil;
import org.xdi.util.Pair;
/**
* @author Yuriy Zabrovarnyy
* @version 0.9, 01/07/2013
*/
@Stateless
@Named("umaRsPermissionService")
public class PermissionService {
public static final int DEFAULT_PERMISSION_LIFETIME = 3600;
@Inject
private Logger log;
@Inject
private RsResourceService umaRsResourceService;
@Inject
private TokenService tokenService;
@Inject
private ResourceSetPermissionManager resourceSetPermissionManager;
@Inject
private AppConfiguration appConfiguration;
@Inject
private ClientService clientService;
public Pair<Boolean, Response> hasEnoughPermissionsWithTicketRegistration(UmaRPT p_rpt, List<ResourceSetPermission> p_rptPermissions, RsResourceType p_resourceType, List<RsScopeType> p_scopes) {
final Pair<Boolean, Response> result = new Pair<Boolean, Response>(false, null);
final ResourceSet resource = umaRsResourceService.getResource(p_resourceType);
if (resource == null || StringUtils.isBlank(resource.getId())) {
result.setFirst(false);
result.setSecond(Response.status(Response.Status.INTERNAL_SERVER_ERROR).build());
return result;
}
if (hasEnoughPermissions(p_rpt, p_rptPermissions, resource, p_scopes)) {
result.setFirst(true);
return result;
} else {
// If the RPT is valid but has insufficient authorization data for the type of access sought,
// the resource server SHOULD register a requested permission with the authorization server
// that would suffice for that scope of access (see Section 3.2),
// and then respond with the HTTP 403 (Forbidden) status code,
// along with providing the authorization server's URI in an "as_uri" property in the header,
// and the permission ticket it just received from the AM in the body in a JSON-encoded "ticket" property.
result.setFirst(false);
final String ticket = registerPermission(p_rpt, resource, p_scopes);
// log.debug("Register permissions on AM, permission ticket: " + ticket);
final String entity = ServerUtil.asJsonSilently(new PermissionTicket(ticket));
log.debug("Construct response: HTTP 403 (Forbidden), entity: " + entity);
final Response response = Response.status(Response.Status.FORBIDDEN).
header("host_id", appConfiguration.getIssuer()).
header("as_uri", appConfiguration.getUmaConfigurationEndpoint()).
header("error", "insufficient_scope").
entity(entity).
build();
result.setSecond(response);
return result;
}
}
private boolean hasEnoughPermissions(UmaRPT p_rpt, List<ResourceSetPermission> p_rptPermissions, ResourceSet p_resource, List<RsScopeType> p_scopes) {
if (p_rptPermissions != null && !p_rptPermissions.isEmpty()) {
final List<String> scopeDns = umaRsResourceService.getScopeDns(p_scopes);
for (ResourceSetPermission p : p_rptPermissions) {
if (hasAny(p, scopeDns)) {
return true;
}
}
}
return false;
}
private boolean hasAny(ResourceSetPermission p_p, List<String> p_scopeDns) {
final List<String> scopeDns = p_p.getScopeDns();
if (scopeDns != null && !scopeDns.isEmpty() && p_scopeDns != null && !p_scopeDns.isEmpty()) {
for (String scopeDn : scopeDns) {
if (p_scopeDns.contains(scopeDn)) {
return true;
}
}
}
return false;
}
public Date rptExpirationDate() {
int lifeTime = appConfiguration.getUmaRequesterPermissionTokenLifetime();
if (lifeTime <= 0) {
lifeTime = DEFAULT_PERMISSION_LIFETIME;
}
final Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, lifeTime);
return calendar.getTime();
}
private String registerPermission(UmaRPT p_rpt, ResourceSet p_resource, List<RsScopeType> p_scopes) {
final Date expirationDate = rptExpirationDate();
final UmaPermission r = new UmaPermission();
r.setResourceSetId(p_resource.getId());
r.setExpiresAt(expirationDate);
final String host = appConfiguration.getIssuer();
final ResourceSetPermission permission = resourceSetPermissionManager.createResourceSetPermission(
host, r, expirationDate);
// IMPORTANT : set scope dns before persistence
permission.setScopeDns(umaRsResourceService.getScopeDns(p_scopes));
final Client client = clientService.getClient(p_rpt.getClientId());
resourceSetPermissionManager.addResourceSetPermission(permission, client.getDn());
return permission.getTicket();
}
}