1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
|
//-----------------------------------------------------------------------
// <copyright file="OpenIdXrdsHelper.cs" company="Andrew Arnott">
// Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId {
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.Xrds;
/// <summary>
/// Adds OpenID-specific extension methods to the XrdsDocument class.
/// </summary>
internal static class OpenIdXrdsHelper {
/// <summary>
/// Finds the Relying Party return_to receiving endpoints.
/// </summary>
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <returns>A sequence of Relying Party descriptors for the return_to endpoints.</returns>
/// <remarks>
/// This is useful for Providers to send unsolicited assertions to Relying Parties,
/// or for Provider's to perform RP discovery/verification as part of authentication.
/// </remarks>
internal static IEnumerable<RelyingPartyEndpointDescription> FindRelyingPartyReceivingEndpoints(this XrdsDocument xrds) {
Contract.Requires<ArgumentNullException>(xrds != null);
Contract.Ensures(Contract.Result<IEnumerable<RelyingPartyEndpointDescription>>() != null);
return from service in xrds.FindReturnToServices()
from uri in service.UriElements
select new RelyingPartyEndpointDescription(uri.Uri, service.TypeElementUris);
}
/// <summary>
/// Finds the icons the relying party wants an OP to display as part of authentication,
/// per the UI extension spec.
/// </summary>
/// <param name="xrds">The XrdsDocument to search.</param>
/// <returns>A sequence of the icon URLs in preferred order.</returns>
internal static IEnumerable<Uri> FindRelyingPartyIcons(this XrdsDocument xrds) {
Contract.Requires<ArgumentNullException>(xrds != null);
Contract.Ensures(Contract.Result<IEnumerable<Uri>>() != null);
return from xrd in xrds.XrdElements
from service in xrd.OpenIdRelyingPartyIcons
from uri in service.UriElements
select uri.Uri;
}
/// <summary>
/// Creates the service endpoints described in this document, useful for requesting
/// authentication of one of the OpenID Providers that result from it.
/// </summary>
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <param name="claimedIdentifier">The claimed identifier that was used to discover this XRDS document.</param>
/// <param name="userSuppliedIdentifier">The user supplied identifier.</param>
/// <returns>
/// A sequence of OpenID Providers that can assert ownership of the <paramref name="claimedIdentifier"/>.
/// </returns>
internal static IEnumerable<IdentifierDiscoveryResult> CreateServiceEndpoints(this IEnumerable<XrdElement> xrds, UriIdentifier claimedIdentifier, UriIdentifier userSuppliedIdentifier) {
Contract.Requires<ArgumentNullException>(xrds != null);
Contract.Requires<ArgumentNullException>(claimedIdentifier != null);
Contract.Requires<ArgumentNullException>(userSuppliedIdentifier != null);
Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
var endpoints = new List<IdentifierDiscoveryResult>();
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));
return endpoints;
}
/// <summary>
/// Creates the service endpoints described in this document, useful for requesting
/// authentication of one of the OpenID Providers that result from it.
/// </summary>
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <param name="userSuppliedIdentifier">The user-supplied i-name that was used to discover this XRDS document.</param>
/// <returns>A sequence of OpenID Providers that can assert ownership of the canonical ID given in this document.</returns>
internal static IEnumerable<IdentifierDiscoveryResult> CreateServiceEndpoints(this IEnumerable<XrdElement> xrds, XriIdentifier userSuppliedIdentifier) {
Contract.Requires<ArgumentNullException>(xrds != null);
Contract.Requires<ArgumentNullException>(userSuppliedIdentifier != null);
Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
var endpoints = new List<IdentifierDiscoveryResult>();
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));
return endpoints;
}
/// <summary>
/// Generates OpenID Providers that can authenticate using directed identity.
/// </summary>
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <param name="opIdentifier">The OP Identifier entered (and resolved) by the user. Essentially the user-supplied identifier.</param>
/// <returns>A sequence of the providers that can offer directed identity services.</returns>
private static IEnumerable<IdentifierDiscoveryResult> GenerateOPIdentifierServiceEndpoints(this IEnumerable<XrdElement> xrds, Identifier opIdentifier) {
Contract.Requires<ArgumentNullException>(xrds != null);
Contract.Requires<ArgumentNullException>(opIdentifier != null);
Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
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);
}
/// <summary>
/// Generates the OpenID Providers that are capable of asserting ownership
/// of a particular URI claimed identifier.
/// </summary>
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <param name="claimedIdentifier">The claimed identifier.</param>
/// <param name="userSuppliedIdentifier">The user supplied identifier.</param>
/// <returns>
/// A sequence of the providers that can assert ownership of the given identifier.
/// </returns>
private static IEnumerable<IdentifierDiscoveryResult> GenerateClaimedIdentifierServiceEndpoints(this IEnumerable<XrdElement> xrds, UriIdentifier claimedIdentifier, UriIdentifier userSuppliedIdentifier) {
Contract.Requires<ArgumentNullException>(xrds != null);
Contract.Requires<ArgumentNullException>(claimedIdentifier != null);
Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
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);
}
/// <summary>
/// Generates the OpenID Providers that are capable of asserting ownership
/// of a particular XRI claimed identifier.
/// </summary>
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <param name="userSuppliedIdentifier">The i-name supplied by the user.</param>
/// <returns>A sequence of the providers that can assert ownership of the given identifier.</returns>
private static IEnumerable<IdentifierDiscoveryResult> GenerateClaimedIdentifierServiceEndpoints(this IEnumerable<XrdElement> xrds, XriIdentifier userSuppliedIdentifier) {
// Cannot use code contracts because this method uses yield return.
////Contract.Requires<ArgumentNullException>(xrds != null);
////Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
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);
}
}
}
/// <summary>
/// Enumerates the XRDS service elements that describe OpenID Providers offering directed identity assertions.
/// </summary>
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <returns>A sequence of service elements.</returns>
private static IEnumerable<ServiceElement> FindOPIdentifierServices(this IEnumerable<XrdElement> xrds) {
Contract.Requires<ArgumentNullException>(xrds != null);
Contract.Ensures(Contract.Result<IEnumerable<ServiceElement>>() != null);
return from xrd in xrds
from service in xrd.OpenIdProviderIdentifierServices
select service;
}
/// <summary>
/// Returns the OpenID-compatible services described by a given XRDS document,
/// in priority order.
/// </summary>
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <returns>A sequence of the services offered.</returns>
private static IEnumerable<ServiceElement> FindClaimedIdentifierServices(this IEnumerable<XrdElement> xrds) {
Contract.Requires<ArgumentNullException>(xrds != null);
Contract.Ensures(Contract.Result<IEnumerable<ServiceElement>>() != null);
return from xrd in xrds
from service in xrd.OpenIdClaimedIdentifierServices
select service;
}
/// <summary>
/// Enumerates the XRDS service elements that describe OpenID Relying Party return_to URLs
/// that can receive authentication assertions.
/// </summary>
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <returns>A sequence of service elements.</returns>
private static IEnumerable<ServiceElement> FindReturnToServices(this XrdsDocument xrds) {
Contract.Requires<ArgumentNullException>(xrds != null);
Contract.Ensures(Contract.Result<IEnumerable<ServiceElement>>() != null);
return from xrd in xrds.XrdElements
from service in xrd.OpenIdRelyingPartyReturnToServices
select service;
}
}
}
|