/// <summary>
        /// Parses the <paramref name="uri"/> as a reference to a local resource.
        /// Returns null if the specified <paramref name="uri"/> is invalid.
        /// </summary>
        /// <param name="uri">The URI.</param>
        /// <param name="serverConfiguration">The server configuration.</param>
        /// <returns>ScimResourceReference.</returns>
        public static ScimResourceReference ToScimResourceReference(this Uri uri, ScimServerConfiguration serverConfiguration)
        {
            var scimPathBase = AmbientRequestService.BasePath;
            var uriPaths     = (string.IsNullOrWhiteSpace(scimPathBase)
                ? uri.AbsolutePath
                : uri.AbsolutePath.Replace(scimPathBase, ""))
                               .TrimStart('/')
                               .Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

            if (uriPaths.Length < 2)
            {
                return(null);
            }

            var resourceEndpoint = uriPaths[0];
            var resourceId       = uriPaths[1];

            var resourceDefinition = serverConfiguration
                                     .GetResourceTypeDefinitions(AmbientRequestService.ProtocolVersion)
                                     .SingleOrDefault(rtd => rtd.Endpoint.IndexOf(resourceEndpoint, StringComparison.OrdinalIgnoreCase) >= 0);

            if (resourceDefinition == null)
            {
                return(null); // invalid uri
            }
            return(new ScimResourceReference(resourceDefinition, resourceId));
        }
Exemple #2
0
        /// <summary>
        /// Parses the <paramref name="uri"/> as a reference to a local resource. 
        /// Returns null if the specified <paramref name="uri"/> is invalid.
        /// </summary>
        /// <param name="uri">The URI.</param>
        /// <param name="serverConfiguration">The server configuration.</param>
        /// <returns>ScimResourceReference.</returns>
        public static ScimResourceReference ToScimResourceReference(this Uri uri, ScimServerConfiguration serverConfiguration)
        {
            var scimPathBase = AmbientRequestService.BasePath;
            var uriPaths = (string.IsNullOrWhiteSpace(scimPathBase)
                ? uri.AbsolutePath
                : uri.AbsolutePath.Replace(scimPathBase, ""))
                .TrimStart('/')
                .Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

            if (uriPaths.Length < 2)
                return null;

            var resourceEndpoint = uriPaths[0];
            var resourceId = uriPaths[1];
            
            var resourceDefinition = serverConfiguration
                .GetResourceTypeDefinitions(AmbientRequestService.ProtocolVersion)
                .SingleOrDefault(rtd => rtd.Endpoint.IndexOf(resourceEndpoint, StringComparison.OrdinalIgnoreCase) >= 0);

            if (resourceDefinition == null)
                return null; // invalid uri

            return new ScimResourceReference(resourceDefinition, resourceId);
        }
        public static Uri EnforceScimUri(Uri uri, IScimTypeAttributeDefinition attributeDefinition, ScimServerConfiguration serverConfiguration)
        {
            /*
             * SCIM 2.0 Specification
             * referenceTypes  A multi-valued array of JSON strings that indicate
             *               the SCIM resource types that may be referenced.  Valid values
             *               are as follows:
             *
             +  A SCIM resource type (e.g., "User" or "Group"),
             +
             +  "external" - indicating that the resource is an external
             +                  resource (e.g., a photo), or
             +
             +  "uri" - indicating that the reference is to a service
             +                  endpoint or an identifier (e.g., a schema URN).
             */

            if (attributeDefinition.ReferenceTypes != null && attributeDefinition.ReferenceTypes.Any())
            {
                IScimResourceTypeDefinition resourceDefinition = null;
                foreach (var referenceType in attributeDefinition.ReferenceTypes)
                {
                    if (referenceType.Equals(ScimConstants.ReferenceTypes.External, StringComparison.OrdinalIgnoreCase))
                    {
                        // do not accept relative URIs for an attribute which is defined as an external reference type
                        if (!uri.IsAbsoluteUri)
                        {
                            continue;
                        }

                        return(uri);
                    }

                    if (referenceType.Equals(ScimConstants.ReferenceTypes.Uri, StringComparison.OrdinalIgnoreCase))
                    {
                        if (uri.ToString().StartsWith(ScimConstants.Defaults.URNPrefix, StringComparison.OrdinalIgnoreCase))
                        {
                            return(uri); // uri is an identifier, possibly schema
                        }
                        // uri MUST be a valid SCIM resource
                        resourceDefinition = serverConfiguration
                                             .GetResourceTypeDefinitions(AmbientRequestService.ProtocolVersion)
                                             .SingleOrDefault(rtd => uri.AbsolutePath.IndexOf(rtd.Endpoint, StringComparison.OrdinalIgnoreCase) >= 0);

                        if (resourceDefinition != null)
                        {
                            break;
                        }

                        continue;
                    }

                    // uri MUST be a valid SCIM resource that's within the allowed referenceTypes
                    resourceDefinition = serverConfiguration
                                         .GetResourceTypeDefinitions(AmbientRequestService.ProtocolVersion)
                                         .SingleOrDefault(
                        rtd =>
                        rtd.Name.Equals(referenceType, StringComparison.OrdinalIgnoreCase) &&
                        uri.AbsolutePath.IndexOf(rtd.Endpoint, StringComparison.OrdinalIgnoreCase) >= 0);

                    if (resourceDefinition != null)
                    {
                        break;
                    }
                }

                // invalid URI for the associated reference types
                if (resourceDefinition == null)
                {
                    return(uri); // allow validation to handle invalid uri's
                }
                return(BuildScimUri(uri));
            }

            /*
             *  Relative URIs should be resolved as specified in
             *  Section 5.2 of [RFC3986].  However, the base URI for relative URI
             *  resolution MUST include all URI components and path segments up to,
             *  but not including, the Endpoint URI (the SCIM service provider root
             *  endpoint)
             */
            return(BuildScimUri(uri));
        }