001/* 002 * Copyright 2015-2016 UnboundID Corp. 003 * 004 * This program is free software; you can redistribute it and/or modify 005 * it under the terms of the GNU General Public License (GPLv2 only) 006 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 007 * as published by the Free Software Foundation. 008 * 009 * This program is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 * GNU General Public License for more details. 013 * 014 * You should have received a copy of the GNU General Public License 015 * along with this program; if not, see <http://www.gnu.org/licenses>. 016 */ 017 018package com.unboundid.scim2.server.providers; 019 020import com.unboundid.scim2.common.exceptions.NotImplementedException; 021import com.unboundid.scim2.common.exceptions.ScimException; 022import com.unboundid.scim2.common.utils.ApiConstants; 023import com.unboundid.scim2.server.utils.ServerUtils; 024 025import javax.ws.rs.container.ContainerRequestContext; 026import javax.ws.rs.container.ContainerRequestFilter; 027import javax.ws.rs.container.PreMatching; 028import javax.ws.rs.core.MultivaluedMap; 029import javax.ws.rs.core.Response; 030import javax.ws.rs.core.SecurityContext; 031import javax.ws.rs.core.UriBuilder; 032import javax.ws.rs.ext.Provider; 033import java.io.IOException; 034import java.util.Collection; 035import java.util.Collections; 036import java.util.List; 037 038/** 039 * A ContainerRequestFilter implementation to resolve the /Me alias to the 040 * path of the resource that represents the authenticated subject. This 041 * implementation will use the user principal within the SecurityContext 042 * as the resource ID and assumes the resource is part of the /Users resource 043 * type. 044 */ 045@Provider 046@PreMatching 047public class AuthenticatedSubjectAliasFilter implements ContainerRequestFilter 048{ 049 /** 050 * {@inheritDoc} 051 */ 052 public void filter(final ContainerRequestContext requestContext) 053 throws IOException 054 { 055 String requestPath = requestContext.getUriInfo().getPath(); 056 for(String alias : getAliases()) 057 { 058 if(requestPath.startsWith(alias + "/") || requestPath.equals(alias)) 059 { 060 String authSubjectPath; 061 try 062 { 063 authSubjectPath = getAuthenticatedSubjectPath( 064 requestContext.getSecurityContext()); 065 UriBuilder newRequestUri = 066 requestContext.getUriInfo().getBaseUriBuilder(); 067 newRequestUri.path(authSubjectPath + 068 requestPath.substring(alias.length())); 069 MultivaluedMap<String, String> queryParams = 070 requestContext.getUriInfo().getQueryParameters(); 071 for (String key : queryParams.keySet()) 072 { 073 List<String> values = queryParams.get(key); 074 newRequestUri.queryParam(key, values.toArray()); 075 } 076 077 requestContext.setRequestUri(newRequestUri.build()); 078 } 079 catch (ScimException e) 080 { 081 requestContext.abortWith( 082 ServerUtils.setAcceptableType(Response. 083 status(e.getScimError().getStatus()). 084 entity(e.getScimError()), 085 requestContext.getAcceptableMediaTypes()).build()); 086 } 087 break; 088 } 089 } 090 } 091 092 /** 093 * Get the path of the resource the represents the authenticated subject. 094 * 095 * @param securityContext The request's security context. 096 * @return The path relative to the base URI. 097 * @throws ScimException if an error occurs while resolving the path. 098 */ 099 protected String getAuthenticatedSubjectPath( 100 final SecurityContext securityContext) 101 throws ScimException 102 { 103 if(securityContext == null || securityContext.getUserPrincipal() == null) 104 { 105 throw new NotImplementedException("/Me not supported"); 106 } 107 108 return "Users/"+ securityContext.getUserPrincipal().toString(); 109 } 110 111 /** 112 * Get the aliases for the authenticated subject. 113 * 114 * @return The aliases for the authenticated subject. 115 */ 116 protected Collection<String> getAliases() 117 { 118 return Collections.singleton(ApiConstants.ME_ENDPOINT); 119 } 120}