/*
* 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;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static javax.ws.rs.core.Response.Status.UNAUTHORIZED;
import static org.xdi.oxauth.model.uma.UmaErrorResponseType.ACCESS_DENIED;
import static org.xdi.oxauth.model.uma.UmaErrorResponseType.INVALID_TOKEN;
import static org.xdi.oxauth.model.uma.UmaErrorResponseType.UNAUTHORIZED_CLIENT;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Set;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import org.gluu.site.ldap.persistence.exception.EntryPersistenceException;
import org.slf4j.Logger;
import org.xdi.oxauth.model.common.AuthorizationGrant;
import org.xdi.oxauth.model.common.AuthorizationGrantList;
import org.xdi.oxauth.model.common.uma.UmaRPT;
import org.xdi.oxauth.model.configuration.AppConfiguration;
import org.xdi.oxauth.model.error.ErrorResponseFactory;
import org.xdi.oxauth.model.uma.UmaErrorResponseType;
import org.xdi.oxauth.model.uma.UmaPermission;
import org.xdi.oxauth.model.uma.UmaScopeType;
import org.xdi.oxauth.model.uma.persistence.ResourceSet;
import org.xdi.oxauth.model.uma.persistence.ResourceSetPermission;
import org.xdi.oxauth.service.token.TokenService;
import org.xdi.util.StringHelper;
/**
* @author Yuriy Zabrovarnyy
* @version 0.9, 04/02/2013
*/
@Named
@Stateless
public class UmaValidationService {
@Inject
private Logger log;
@Inject
private ErrorResponseFactory errorResponseFactory;
@Inject
private TokenService tokenService;
@Inject
private AuthorizationGrantList authorizationGrantList;
@Inject
private ResourceSetService resourceSetService;
@Inject
private ScopeService umaScopeService;
@Inject
private AppConfiguration appConfiguration;
public String validateAmHost(String host) {
if (StringHelper.isEmpty(host)) {
log.error("AM host is invalid");
throw new WebApplicationException(Response.status(BAD_REQUEST)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.INVALID_REQUEST)).build());
}
String hostUri;
try {
int index = host.indexOf("://");
if (index != -1) {
hostUri = (new URI(host)).getHost();
} else {
hostUri = (new URI("https://" + host)).getHost();
}
} catch (URISyntaxException ex) {
log.error("Failed to parse AM host: '{}'", ex, host);
throw new WebApplicationException(Response.status(BAD_REQUEST)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.INVALID_REQUEST)).build());
}
try {
URI umaBaseEndpoint = new URI(appConfiguration.getBaseEndpoint());
if (!StringHelper.equalsIgnoreCase(hostUri, umaBaseEndpoint.getHost())) {
log.error("Get request for another AM: '{}'. Expected: '{}'", hostUri, umaBaseEndpoint.getHost());
throw new WebApplicationException(Response.status(BAD_REQUEST)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.INVALID_REQUEST)).build());
}
} catch (URISyntaxException ex) {
log.error("Failed to parse AM host: '{}'", ex, hostUri);
throw new WebApplicationException(Response.status(BAD_REQUEST)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.INVALID_REQUEST)).build());
}
return StringHelper.toLowerCase(hostUri).trim();
}
// public String validateHost(String host) {
// if (StringHelper.isEmpty(host)) {
// log.error("Host is invalid");
// throw new WebApplicationException(Response.status(BAD_REQUEST)
// .entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.INVALID_REQUEST)).build());
// }
//
// String hostUri;
// try {
// int index = host.indexOf("://");
// if (index != -1) {
// hostUri = (new URI(host)).getHost();
// } else {
// hostUri = (new URI("https://" + host)).getHost();
// }
// } catch (URISyntaxException ex) {
// log.error("Failed to parse host: '{}'", ex, host);
// throw new WebApplicationException(Response.status(BAD_REQUEST)
// .entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.INVALID_REQUEST)).build());
// }
//
// return StringHelper.toLowerCase(hostUri).trim();
// }
public AuthorizationGrant assertHasProtectionScope(String authorization) {
return validateAuthorization(authorization, UmaScopeType.PROTECTION);
}
public AuthorizationGrant assertHasAuthorizationScope(String authorization) {
return validateAuthorization(authorization, UmaScopeType.AUTHORIZATION);
}
private AuthorizationGrant validateAuthorization(String authorization, UmaScopeType umaScopeType) {
log.trace("Validate authorization: {}", authorization);
if (StringHelper.isEmpty(authorization)) {
throw new WebApplicationException(Response.status(UNAUTHORIZED)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UNAUTHORIZED_CLIENT)).build());
}
String token = tokenService.getTokenFromAuthorizationParameter(authorization);
if (StringHelper.isEmpty(token)) {
log.debug("Token is invalid");
throw new WebApplicationException(Response.status(UNAUTHORIZED)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UNAUTHORIZED_CLIENT)).build());
}
AuthorizationGrant authorizationGrant = authorizationGrantList.getAuthorizationGrantByAccessToken(token);
if (authorizationGrant == null) {
throw new WebApplicationException(Response.status(UNAUTHORIZED)
.entity(errorResponseFactory.getUmaJsonErrorResponse(ACCESS_DENIED)).build());
}
if (!authorizationGrant.isValid()) {
throw new WebApplicationException(Response.status(UNAUTHORIZED)
.entity(errorResponseFactory.getUmaJsonErrorResponse(INVALID_TOKEN)).build());
}
Set<String> scopes = authorizationGrant.getScopes();
if (!scopes.contains(umaScopeType.getValue())) {
throw new WebApplicationException(Response.status(Response.Status.NOT_ACCEPTABLE)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.INVALID_CLIENT_SCOPE)).build());
}
return authorizationGrant;
}
public void validateRPT(UmaRPT rpt) {
if (rpt == null) {
throw new WebApplicationException(Response.status(UNAUTHORIZED)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.NOT_AUTHORIZED_PERMISSION)).build());
}
rpt.checkExpired();
if (!rpt.isValid()) {
throw new WebApplicationException(Response.status(UNAUTHORIZED)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.NOT_AUTHORIZED_PERMISSION)).build());
}
}
public void validateResourceSetPermission(ResourceSetPermission resourceSetPermission) {
if (resourceSetPermission == null || "invalidated".equalsIgnoreCase(resourceSetPermission.getAmHost())) {
throw new WebApplicationException(Response.status(BAD_REQUEST)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.INVALID_TICKET)).build());
}
resourceSetPermission.checkExpired();
if (!resourceSetPermission.isValid()) {
throw new WebApplicationException(Response.status(BAD_REQUEST)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.EXPIRED_TICKET)).build());
}
}
public void validateResourceSet(UmaPermission resourceSetPermissionRequest) {
String resourceSetId = resourceSetPermissionRequest.getResourceSetId();
if (StringHelper.isEmpty(resourceSetId)) {
log.error("Resource set id is empty");
throw new WebApplicationException(Response.status(BAD_REQUEST)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.INVALID_RESOURCE_SET_ID)).build());
}
ResourceSet resourceSet;
try {
ResourceSet exampleResourceSet = new ResourceSet();
exampleResourceSet.setDn(resourceSetService.getBaseDnForResourceSet());
exampleResourceSet.setId(resourceSetId);
List<ResourceSet> resourceSets = resourceSetService.findResourceSets(exampleResourceSet);
if (resourceSets.size() != 1) {
log.error("Resource set isn't registered or there are two resource set with same Id");
throw new WebApplicationException(Response.status(BAD_REQUEST)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.INVALID_RESOURCE_SET_ID)).build());
}
resourceSet = resourceSets.get(0);
} catch (EntryPersistenceException ex) {
log.error("Resource set isn't registered");
throw new WebApplicationException(Response.status(BAD_REQUEST)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.INVALID_RESOURCE_SET_ID)).build());
}
final List<String> scopeUrls = umaScopeService.getScopeUrlsByDns(resourceSet.getScopes());
if (!scopeUrls.containsAll(resourceSetPermissionRequest.getScopes())) {
log.error("At least one of the scope isn't registered");
throw new WebApplicationException(Response.status(BAD_REQUEST)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.INVALID_RESOURCE_SET_SCOPE)).build());
}
}
}