/*
* 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.uma.ws.rs;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import org.gluu.site.ldap.persistence.LdapEntryManager;
import org.slf4j.Logger;
import org.xdi.oxauth.model.common.AuthorizationGrant;
import org.xdi.oxauth.model.common.uma.UmaRPT;
import org.xdi.oxauth.model.config.WebKeysConfiguration;
import org.xdi.oxauth.model.configuration.AppConfiguration;
import org.xdi.oxauth.model.error.ErrorResponseFactory;
import org.xdi.oxauth.model.jwt.Jwt;
import org.xdi.oxauth.model.token.JsonWebResponse;
import org.xdi.oxauth.model.token.JwtSigner;
import org.xdi.oxauth.model.uma.GatRequest;
import org.xdi.oxauth.model.uma.RPTResponse;
import org.xdi.oxauth.model.uma.UmaConstants;
import org.xdi.oxauth.model.uma.UmaErrorResponseType;
import org.xdi.oxauth.service.token.TokenService;
import org.xdi.oxauth.service.uma.RptManager;
import org.xdi.oxauth.service.uma.UmaValidationService;
import org.xdi.oxauth.service.uma.authorization.AuthorizationService;
import org.xdi.oxauth.util.ServerUtil;
import com.google.common.collect.Lists;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiResponse;
import com.wordnik.swagger.annotations.ApiResponses;
/**
* The endpoint at which the requester can obtain UMA metadata configuration.
*
* @author Yuriy Zabrovarnyy
*/
@Path("/requester")
@Api(value = "/requester/rpt", description = "The endpoint at which the requester asks the AM to issue an RPT")
public class CreateRptWS {
@Inject
private Logger log;
@Inject
private ErrorResponseFactory errorResponseFactory;
@Inject
private RptManager rptManager;
@Inject
private UmaValidationService umaValidationService;
@Inject
private TokenService tokenService;
@Inject
private AuthorizationService umaAuthorizationService;
@Inject
private LdapEntryManager ldapEntryManager;
@Inject
private AppConfiguration appConfiguration;
@Inject
private WebKeysConfiguration webKeysConfiguration;
@Path("rpt")
@POST
@Produces({UmaConstants.JSON_MEDIA_TYPE})
@ApiOperation(value = "The endpoint at which the requester asks the AM to issue an RPT",
produces = UmaConstants.JSON_MEDIA_TYPE,
notes = "The endpoint at which the requester asks the AM to issue an RPT")
@ApiResponses(value = {
@ApiResponse(code = 401, message = "Unauthorized")
})
public Response getRpt(@HeaderParam("Authorization") String authorization,
@HeaderParam("Host") String amHost) {
try {
umaValidationService.assertHasAuthorizationScope(authorization);
String validatedAmHost = umaValidationService.validateAmHost(amHost);
UmaRPT rpt = rptManager.createRPT(authorization, validatedAmHost, false);
String rptResponse = rpt.getCode();
final Boolean umaRptAsJwt = appConfiguration.getUmaRptAsJwt();
if (umaRptAsJwt != null && umaRptAsJwt) {
rptResponse = createJwr(rpt, authorization, Lists.<String>newArrayList()).asString();
}
return Response.status(Response.Status.CREATED).
entity(ServerUtil.asJson(new RPTResponse(rptResponse))).
build();
} catch (Exception ex) {
log.error("Exception happened", ex);
if (ex instanceof WebApplicationException) {
throw (WebApplicationException) ex;
}
throw new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.SERVER_ERROR)).build());
}
}
private JsonWebResponse createJwr(UmaRPT rpt, String authorization, List<String> gluuAccessTokenScopes) throws Exception {
final AuthorizationGrant grant = tokenService.getAuthorizationGrant(authorization);
JwtSigner jwtSigner = JwtSigner.newJwtSigner(appConfiguration, webKeysConfiguration, grant.getClient());
Jwt jwt = jwtSigner.newJwt();
jwt.getClaims().setExpirationTime(rpt.getExpirationDate());
jwt.getClaims().setIssuedAt(rpt.getCreationDate());
if (!gluuAccessTokenScopes.isEmpty()) {
jwt.getClaims().setClaim("scopes", gluuAccessTokenScopes);
}
return jwtSigner.sign();
}
@Path("gat")
@POST
@Produces({UmaConstants.JSON_MEDIA_TYPE})
@ApiOperation(value = "The endpoint at which the requester asks the AM to issue an GAT",
produces = UmaConstants.JSON_MEDIA_TYPE,
notes = "The endpoint at which the requester asks the AM to issue an GAT")
@ApiResponses(value = {
@ApiResponse(code = 401, message = "Unauthorized")
})
public Response getGat(@HeaderParam("Authorization") String authorization,
@HeaderParam("Host") String amHost,
GatRequest request,
@Context HttpServletRequest httpRequest) {
try {
umaValidationService.assertHasAuthorizationScope(authorization);
String validatedAmHost = umaValidationService.validateAmHost(amHost);
UmaRPT rpt = rptManager.createRPT(authorization, validatedAmHost, true);
authorizeGat(request, rpt, authorization, httpRequest);
String rptResponse = rpt.getCode();
final Boolean umaRptAsJwt = appConfiguration.getUmaRptAsJwt();
if (umaRptAsJwt != null && umaRptAsJwt) {
rptResponse = createJwr(rpt, authorization, request.getScopes()).asString();
}
return Response.status(Response.Status.CREATED).
entity(ServerUtil.asJson(new RPTResponse(rptResponse))).
build();
} catch (Exception ex) {
log.error("Exception happened", ex);
if (ex instanceof WebApplicationException) {
throw (WebApplicationException) ex;
}
throw new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.SERVER_ERROR)).build());
}
}
private void authorizeGat(GatRequest request, UmaRPT rpt, String authorization, HttpServletRequest httpRequest) {
if (request.getScopes().isEmpty()) {
return; // nothing to authorize
}
AuthorizationGrant grant = tokenService.getAuthorizationGrant(authorization);
if (umaAuthorizationService.allowToAddPermissionForGat(grant, rpt, request.getScopes(), httpRequest, request.getClaims())) {
final List<String> scopes = new ArrayList<String>();
if (rpt.getPermissions() != null) {
scopes.addAll(rpt.getPermissions());
}
scopes.addAll(request.getScopes());
rpt.setPermissions(scopes);
try {
ldapEntryManager.merge(rpt);
return;
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
// throw not authorized exception
throw new WebApplicationException(Response.status(Response.Status.FORBIDDEN)
.entity(errorResponseFactory.getUmaJsonErrorResponse(UmaErrorResponseType.NOT_AUTHORIZED_PERMISSION)).build());
}
}