/* * 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.idgen.ws.rs; import java.io.IOException; import java.util.Arrays; import java.util.List; import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.xdi.oxauth.model.common.Id; import org.xdi.oxauth.model.common.IdType; import org.xdi.oxauth.model.common.uma.UmaRPT; import org.xdi.oxauth.model.configuration.AppConfiguration; import org.xdi.oxauth.model.uma.persistence.ResourceSetPermission; import org.xdi.oxauth.service.token.TokenService; import org.xdi.oxauth.service.uma.RptManager; import org.xdi.oxauth.service.uma.resourceserver.PermissionService; import org.xdi.oxauth.service.uma.resourceserver.RsResourceType; import org.xdi.oxauth.service.uma.resourceserver.RsScopeType; import org.xdi.oxauth.util.ServerUtil; import org.xdi.util.Pair; import com.wordnik.swagger.annotations.Api; import com.wordnik.swagger.annotations.ApiOperation; import com.wordnik.swagger.annotations.ApiParam; /** * @author Yuriy Zabrovarnyy * @version 0.9, 24/06/2013 */ @Path("/id") @Api(value = "/id", description = "ID Generation") public class IdGenRestWebService { @Inject private AppConfiguration appConfiguration; @Inject private Logger log; @Inject private IdGenService idGenService; @Inject private TokenService tokenService; @Inject private PermissionService umaRsPermissionService; @Inject private RptManager rptManager; @GET @Path("/{prefix}/{type}/") @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Generates ID for given prefix and type.", notes = "Generates ID for given prefix and type. ", response = Response.class, responseContainer = "String" ) public Response generateJsonInum( @PathParam("prefix") @ApiParam(value="Prefix for id. E.g. if prefix is @!1111 and server will generate id: !0000 then ID returned by service would be: @!1111!0000", required = true) String prefix, @PathParam("type") @ApiParam(value="Type of id", required = true, allowableValues = "PEOPLE, ORGANIZATION, APPLIANCE, GROUP, SERVER, ATTRIBUTE, TRUST_RELATIONSHIP, CLIENTS") String type, @HeaderParam("Authorization") String p_authorization) { return generateId(prefix, type, p_authorization, MediaType.APPLICATION_JSON); } @GET @Path("/{prefix}/{type}/") @Produces(MediaType.TEXT_PLAIN) @ApiOperation( value = "Generates ID for given prefix and type.", notes = "Generates ID for given prefix and type. ", response = Response.class, responseContainer = "String" ) public Response generateTextInum(@PathParam("prefix") String prefix, @PathParam("type") String type, @HeaderParam("Authorization") String p_authorization) { return generateId(prefix, type, p_authorization, MediaType.TEXT_PLAIN); } @GET @Path("/{prefix}/{type}/") @Produces(MediaType.TEXT_XML) @ApiOperation( value = "Generates ID for given prefix and type.", notes = "Generates ID for given prefix and type. ", response = Response.class, responseContainer = "String" ) public Response generateXmlInum( @PathParam("prefix") @ApiParam(value="Prefix for id. E.g. if prefix is @!1111 and server will generate id: !0000 then ID returned by service would be: @!1111!0000", required = true) String prefix, @PathParam("type") @ApiParam(value="Type of id", required = true, allowableValues = "PEOPLE, ORGANIZATION, APPLIANCE, GROUP, SERVER, ATTRIBUTE, TRUST_RELATIONSHIP, CLIENTS") String type, @HeaderParam("Authorization") String p_authorization) { return generateId(prefix, type, p_authorization, MediaType.TEXT_XML); } @GET @Path("/{prefix}/{type}/") @Produces(MediaType.TEXT_HTML) @ApiOperation( value = "Generates ID for given prefix and type.", notes = "Generates ID for given prefix and type. ", response = Response.class, responseContainer = "String" ) public Response generateHtmlInum( @PathParam("prefix") @ApiParam(value="Prefix for id. E.g. if prefix is @!1111 and server will generate id: !0000 then ID returned by service would be: @!1111!0000", required = true) String prefix, @PathParam("type") @ApiParam(value="Type of id", required = true, allowableValues = "PEOPLE, ORGANIZATION, APPLIANCE, GROUP, SERVER, ATTRIBUTE, TRUST_RELATIONSHIP, CLIENTS") String type, @HeaderParam("Authorization") String p_authorization) { return generateId(prefix, type, p_authorization, MediaType.TEXT_HTML); } private Pair<Boolean, Response> hasEnoughPermissions(String p_authorization, List<RsScopeType> p_scopes) { final String rptString = tokenService.getTokenFromAuthorizationParameter(p_authorization); if (StringUtils.isNotBlank(rptString)) { final UmaRPT rpt = rptManager.getRPTByCode(rptString); if (rpt != null) { rpt.checkExpired(); if (rpt.isValid()) { final List<ResourceSetPermission> rptPermissions = rptManager.getRptPermissions(rpt); return umaRsPermissionService.hasEnoughPermissionsWithTicketRegistration(rpt, rptPermissions, RsResourceType.ID_GENERATION, p_scopes); } } } // If the client does not present an RPT with the request, // the resource server MUST return an HTTP 401 (Unauthorized) status code, // along with providing the authorization server's URI in an "as_uri" property // to facilitate authorization server configuration data discovery, // including discovery of the endpoint where the client can request an RPT (Section 3.4.1). log.debug("Client does not present RPT. Return HTTP 401 (Unauthorized)\n with reference to AM as_uri: {}", appConfiguration.getUmaConfigurationEndpoint()); return new Pair<Boolean, Response>(false, unauthorizedResponse()); } private Response generateId(String prefix, String type, String p_authorization, String p_mediaType) { try { final Pair<Boolean, Response> pair = hasEnoughPermissions(p_authorization, Arrays.asList(RsScopeType.GENERATE_ID)); if (pair.getFirst()) { final String entity = generateIdEntity(prefix, type, p_mediaType); return Response.status(Response.Status.OK).entity(entity).build(); } else { log.debug("RPT doesn't have enough permissions, access FORBIDDEN. Returns HTTP 403 (Forbidden)."); return pair.getSecond(); } } catch (Exception e) { log.error(e.getMessage(), e); } return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } private String generateIdEntity(String prefix, String type, String p_mediaType) throws IOException { final String id = generateId(prefix, type); if (p_mediaType.equals(MediaType.APPLICATION_JSON)) { return ServerUtil.asJson(new Id(id)); } else if (p_mediaType.equals(MediaType.TEXT_PLAIN)) { return id; } else if (p_mediaType.equals(MediaType.TEXT_HTML)) { return "<html><title>" + IdType.fromString(type).getHtmlText() + "</title><body><h1>" + type + ": " + id + "</h1></body></html> "; } else if (p_mediaType.equals(MediaType.TEXT_XML)) { return "<?xml version=\"1.0\"?><inum type='" + IdType.fromString(type).getValue() + "'>" + id + "</inum>"; } return ""; } private String generateId(String prefix, String type) { final String id = idGenService.generateId(type, prefix); log.trace("Generated id: {}, prefix: {}, type: {}", id, prefix, type); return id; } public Response unauthorizedResponse() { return Response.status(Response.Status.UNAUTHORIZED). header("host_id", appConfiguration.getIssuer()). header("as_uri", appConfiguration.getUmaConfigurationEndpoint()). build(); } }