@@ -72,14 +72,21 @@ public Retriever([NotNull] HttpClient client, [NotNull] HtmlParser parser)
72
72
/// </summary>
73
73
public HttpClient HttpClient { get ; }
74
74
75
+ /// <summary>
76
+ /// Gets the maximal number of roundtrips that are allowed
77
+ /// before the discovery process is automatically aborted.
78
+ /// By default, this property is set to <c>5</c>.
79
+ /// </summary>
80
+ public int MaximumRedirections { get ; set ; } = 5 ;
81
+
75
82
/// <summary>
76
83
/// Retrieves the OpenID 2.0 configuration from the specified address.
77
84
/// </summary>
78
85
/// <param name="address">The address of the discovery document.</param>
79
86
/// <param name="retriever">The object used to retrieve the discovery document.</param>
80
87
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
81
88
/// <returns>An <see cref="OpenIdAuthenticationConfiguration"/> instance.</returns>
82
- public async Task < OpenIdAuthenticationConfiguration > GetConfigurationAsync (
89
+ public Task < OpenIdAuthenticationConfiguration > GetConfigurationAsync (
83
90
[ NotNull ] string address , [ NotNull ] IDocumentRetriever retriever , CancellationToken cancellationToken )
84
91
{
85
92
if ( retriever == null )
@@ -97,21 +104,24 @@ public async Task<OpenIdAuthenticationConfiguration> GetConfigurationAsync(
97
104
throw new ArgumentException ( "The address must be an absolute URI." , nameof ( address ) ) ;
98
105
}
99
106
100
- using ( var cancellationTokenSource = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) )
107
+ if ( MaximumRedirections < 1 )
101
108
{
102
- cancellationTokenSource . CancelAfter ( HttpClient . Timeout ) ;
103
-
104
- return await DiscoverConfigurationAsync ( uri , cancellationTokenSource . Token ) ;
109
+ throw new InvalidOperationException ( "The maximal number of redirections must be a non-zero positive number." ) ;
105
110
}
111
+
112
+ return DiscoverConfigurationAsync ( uri , cancellationToken ) ;
106
113
}
107
114
108
115
private async Task < OpenIdAuthenticationConfiguration > DiscoverConfigurationAsync (
109
116
[ NotNull ] Uri address , CancellationToken cancellationToken )
110
117
{
111
118
Debug . Assert ( address != null , "The address shouldn't be null or empty." ) ;
112
119
113
- while ( ! cancellationToken . IsCancellationRequested )
120
+ for ( var index = 0 ; index < MaximumRedirections ; index ++ )
114
121
{
122
+ // Abort the operation if cancellation was requested.
123
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
124
+
115
125
// application/xrds+xml MUST be the preferred content type to avoid a second round-trip.
116
126
// See http://openid.net/specs/yadis-v1.0.pdf (chapter 6.2.4)
117
127
var request = new HttpRequestMessage ( HttpMethod . Get , address ) ;
@@ -154,7 +164,7 @@ private async Task<OpenIdAuthenticationConfiguration> DiscoverConfigurationAsync
154
164
// See http://openid.net/specs/yadis-v1.0.pdf (chapter 6.2.6)
155
165
if ( response . Headers . Contains ( OpenIdAuthenticationConstants . Headers . XrdsLocation ) )
156
166
{
157
- var location = ProcessUnknownDocument ( response ) ;
167
+ var location = ProcessGenericDocument ( response ) ;
158
168
if ( location != null )
159
169
{
160
170
// Retry the discovery operation, but using the
@@ -221,7 +231,7 @@ orderby service.Attribute("priority")?.Value
221
231
}
222
232
}
223
233
224
- private Uri ProcessUnknownDocument ( [ NotNull ] HttpResponseMessage response )
234
+ private Uri ProcessGenericDocument ( [ NotNull ] HttpResponseMessage response )
225
235
{
226
236
Debug . Assert ( response != null , "The HTTP response shouldn't be null." ) ;
227
237
0 commit comments