//----------------------------------------------------------------------- // // Copyright (c) Outercurve Foundation. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.OpenId { using System; using System.Collections.Generic; using System.Linq; using DotNetOpenAuth.Logging; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OpenId.RelyingParty; using DotNetOpenAuth.Xrds; using Validation; /// /// Adds OpenID-specific extension methods to the XrdsDocument class. /// internal static class OpenIdXrdsHelperRelyingParty { /// /// Creates the service endpoints described in this document, useful for requesting /// authentication of one of the OpenID Providers that result from it. /// /// The XrdsDocument instance to use in this process. /// The claimed identifier that was used to discover this XRDS document. /// The user supplied identifier. /// /// A sequence of OpenID Providers that can assert ownership of the . /// internal static IEnumerable CreateServiceEndpoints(this IEnumerable xrds, UriIdentifier claimedIdentifier, UriIdentifier userSuppliedIdentifier) { Requires.NotNull(xrds, "xrds"); Requires.NotNull(claimedIdentifier, "claimedIdentifier"); Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier"); var endpoints = new List(); endpoints.AddRange(xrds.GenerateOPIdentifierServiceEndpoints(userSuppliedIdentifier)); endpoints.AddRange(xrds.GenerateClaimedIdentifierServiceEndpoints(claimedIdentifier, userSuppliedIdentifier)); Logger.Yadis.DebugFormat("Total services discovered in XRDS: {0}", endpoints.Count); Logger.Yadis.Debug(endpoints.ToStringDeferred(true).ToString()); return endpoints; } /// /// Creates the service endpoints described in this document, useful for requesting /// authentication of one of the OpenID Providers that result from it. /// /// The XrdsDocument instance to use in this process. /// The user-supplied i-name that was used to discover this XRDS document. /// A sequence of OpenID Providers that can assert ownership of the canonical ID given in this document. internal static IEnumerable CreateServiceEndpoints(this IEnumerable xrds, XriIdentifier userSuppliedIdentifier) { Requires.NotNull(xrds, "xrds"); Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier"); var endpoints = new List(); endpoints.AddRange(xrds.GenerateOPIdentifierServiceEndpoints(userSuppliedIdentifier)); endpoints.AddRange(xrds.GenerateClaimedIdentifierServiceEndpoints(userSuppliedIdentifier)); Logger.Yadis.DebugFormat("Total services discovered in XRDS: {0}", endpoints.Count); Logger.Yadis.Debug(endpoints.ToStringDeferred(true).ToString()); return endpoints; } /// /// Generates OpenID Providers that can authenticate using directed identity. /// /// The XrdsDocument instance to use in this process. /// The OP Identifier entered (and resolved) by the user. Essentially the user-supplied identifier. /// A sequence of the providers that can offer directed identity services. private static IEnumerable GenerateOPIdentifierServiceEndpoints(this IEnumerable xrds, Identifier opIdentifier) { Requires.NotNull(xrds, "xrds"); Requires.NotNull(opIdentifier, "opIdentifier"); return from service in xrds.FindOPIdentifierServices() from uri in service.UriElements let protocol = Protocol.FindBestVersion(p => p.OPIdentifierServiceTypeURI, service.TypeElementUris) let providerDescription = new ProviderEndpointDescription(uri.Uri, service.TypeElementUris) select IdentifierDiscoveryResult.CreateForProviderIdentifier(opIdentifier, providerDescription, service.Priority, uri.Priority); } /// /// Generates the OpenID Providers that are capable of asserting ownership /// of a particular URI claimed identifier. /// /// The XrdsDocument instance to use in this process. /// The claimed identifier. /// The user supplied identifier. /// /// A sequence of the providers that can assert ownership of the given identifier. /// private static IEnumerable GenerateClaimedIdentifierServiceEndpoints(this IEnumerable xrds, UriIdentifier claimedIdentifier, UriIdentifier userSuppliedIdentifier) { Requires.NotNull(xrds, "xrds"); Requires.NotNull(claimedIdentifier, "claimedIdentifier"); return from service in xrds.FindClaimedIdentifierServices() from uri in service.UriElements where uri.Uri != null let providerEndpoint = new ProviderEndpointDescription(uri.Uri, service.TypeElementUris) select IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimedIdentifier, userSuppliedIdentifier, service.ProviderLocalIdentifier, providerEndpoint, service.Priority, uri.Priority); } /// /// Generates the OpenID Providers that are capable of asserting ownership /// of a particular XRI claimed identifier. /// /// The XrdsDocument instance to use in this process. /// The i-name supplied by the user. /// A sequence of the providers that can assert ownership of the given identifier. private static IEnumerable GenerateClaimedIdentifierServiceEndpoints(this IEnumerable xrds, XriIdentifier userSuppliedIdentifier) { // Cannot use code contracts because this method uses yield return. ////Requires.NotNull(xrds, "xrds"); //// ErrorUtilities.VerifyArgumentNotNull(xrds, "xrds"); foreach (var service in xrds.FindClaimedIdentifierServices()) { foreach (var uri in service.UriElements) { // spec section 7.3.2.3 on Claimed Id -> CanonicalID substitution if (service.Xrd.CanonicalID == null) { Logger.Yadis.WarnFormat(XrdsStrings.MissingCanonicalIDElement, userSuppliedIdentifier); break; // skip on to next service } ErrorUtilities.VerifyProtocol(service.Xrd.IsCanonicalIdVerified, XrdsStrings.CIDVerificationFailed, userSuppliedIdentifier); // In the case of XRI names, the ClaimedId is actually the CanonicalID. var claimedIdentifier = new XriIdentifier(service.Xrd.CanonicalID); var providerEndpoint = new ProviderEndpointDescription(uri.Uri, service.TypeElementUris); yield return IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimedIdentifier, userSuppliedIdentifier, service.ProviderLocalIdentifier, providerEndpoint, service.Priority, uri.Priority); } } } /// /// Enumerates the XRDS service elements that describe OpenID Providers offering directed identity assertions. /// /// The XrdsDocument instance to use in this process. /// A sequence of service elements. private static IEnumerable FindOPIdentifierServices(this IEnumerable xrds) { Requires.NotNull(xrds, "xrds"); return from xrd in xrds from service in xrd.OpenIdProviderIdentifierServices select service; } /// /// Returns the OpenID-compatible services described by a given XRDS document, /// in priority order. /// /// The XrdsDocument instance to use in this process. /// A sequence of the services offered. private static IEnumerable FindClaimedIdentifierServices(this IEnumerable xrds) { Requires.NotNull(xrds, "xrds"); return from xrd in xrds from service in xrd.OpenIdClaimedIdentifierServices select service; } } }