Skip to content

Commit 3041cd0

Browse files
committed
Introduce a new OpenIdAuthenticationOptions.MaximumRedirections options
1 parent a702fdd commit 3041cd0

File tree

3 files changed

+34
-9
lines changed

3 files changed

+34
-9
lines changed

src/AspNet.Security.OpenId/OpenIdAuthenticationConfiguration.cs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,21 @@ public Retriever([NotNull] HttpClient client, [NotNull] HtmlParser parser)
7272
/// </summary>
7373
public HttpClient HttpClient { get; }
7474

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+
7582
/// <summary>
7683
/// Retrieves the OpenID 2.0 configuration from the specified address.
7784
/// </summary>
7885
/// <param name="address">The address of the discovery document.</param>
7986
/// <param name="retriever">The object used to retrieve the discovery document.</param>
8087
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
8188
/// <returns>An <see cref="OpenIdAuthenticationConfiguration"/> instance.</returns>
82-
public async Task<OpenIdAuthenticationConfiguration> GetConfigurationAsync(
89+
public Task<OpenIdAuthenticationConfiguration> GetConfigurationAsync(
8390
[NotNull] string address, [NotNull] IDocumentRetriever retriever, CancellationToken cancellationToken)
8491
{
8592
if (retriever == null)
@@ -97,21 +104,24 @@ public async Task<OpenIdAuthenticationConfiguration> GetConfigurationAsync(
97104
throw new ArgumentException("The address must be an absolute URI.", nameof(address));
98105
}
99106

100-
using (var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
107+
if (MaximumRedirections < 1)
101108
{
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.");
105110
}
111+
112+
return DiscoverConfigurationAsync(uri, cancellationToken);
106113
}
107114

108115
private async Task<OpenIdAuthenticationConfiguration> DiscoverConfigurationAsync(
109116
[NotNull] Uri address, CancellationToken cancellationToken)
110117
{
111118
Debug.Assert(address != null, "The address shouldn't be null or empty.");
112119

113-
while (!cancellationToken.IsCancellationRequested)
120+
for (var index = 0; index < MaximumRedirections; index++)
114121
{
122+
// Abort the operation if cancellation was requested.
123+
cancellationToken.ThrowIfCancellationRequested();
124+
115125
// application/xrds+xml MUST be the preferred content type to avoid a second round-trip.
116126
// See http://openid.net/specs/yadis-v1.0.pdf (chapter 6.2.4)
117127
var request = new HttpRequestMessage(HttpMethod.Get, address);
@@ -154,7 +164,7 @@ private async Task<OpenIdAuthenticationConfiguration> DiscoverConfigurationAsync
154164
// See http://openid.net/specs/yadis-v1.0.pdf (chapter 6.2.6)
155165
if (response.Headers.Contains(OpenIdAuthenticationConstants.Headers.XrdsLocation))
156166
{
157-
var location = ProcessUnknownDocument(response);
167+
var location = ProcessGenericDocument(response);
158168
if (location != null)
159169
{
160170
// Retry the discovery operation, but using the
@@ -221,7 +231,7 @@ orderby service.Attribute("priority")?.Value
221231
}
222232
}
223233

224-
private Uri ProcessUnknownDocument([NotNull] HttpResponseMessage response)
234+
private Uri ProcessGenericDocument([NotNull] HttpResponseMessage response)
225235
{
226236
Debug.Assert(response != null, "The HTTP response shouldn't be null.");
227237

src/AspNet.Security.OpenId/OpenIdAuthenticationInitializer.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ public void PostConfigure([NotNull] string name, [NotNull] TOptions options)
5454
throw new ArgumentException("The options instance name cannot be null or empty.", nameof(name));
5555
}
5656

57+
if (options.MaximumRedirections < 1)
58+
{
59+
throw new ArgumentException("The maximal number of redirections must be a non-zero positive number.", nameof(options));
60+
}
61+
5762
if (options.DataProtectionProvider == null)
5863
{
5964
options.DataProtectionProvider = _dataProtectionProvider;
@@ -135,7 +140,10 @@ public void PostConfigure([NotNull] string name, [NotNull] TOptions options)
135140

136141
options.ConfigurationManager = new ConfigurationManager<OpenIdAuthenticationConfiguration>(
137142
options.MetadataAddress?.AbsoluteUri ?? options.Authority.AbsoluteUri,
138-
new OpenIdAuthenticationConfiguration.Retriever(options.HttpClient, options.HtmlParser),
143+
new OpenIdAuthenticationConfiguration.Retriever(options.HttpClient, options.HtmlParser)
144+
{
145+
MaximumRedirections = options.MaximumRedirections
146+
},
139147
new HttpDocumentRetriever(options.HttpClient) { RequireHttps = options.RequireHttpsMetadata });
140148
}
141149
}

src/AspNet.Security.OpenId/OpenIdAuthenticationOptions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,12 @@ public OpenIdAuthenticationOptions()
101101
/// Gets or sets the HTML parser used to parse discovery documents.
102102
/// </summary>
103103
public HtmlParser HtmlParser { get; set; }
104+
105+
/// <summary>
106+
/// Gets the maximal number of roundtrips that are allowed
107+
/// before the discovery process is automatically aborted.
108+
/// By default, this property is set to <c>5</c>.
109+
/// </summary>
110+
public int MaximumRedirections { get; set; } = 5;
104111
}
105112
}

0 commit comments

Comments
 (0)