#772 Signout FormPost test (#1358)

This commit is contained in:
Chris Ross 2017-08-11 11:50:25 -07:00 committed by GitHub
parent 4eb1306692
commit 0c82d94a54
2 changed files with 91 additions and 35 deletions

View File

@ -182,27 +182,39 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
}
[Fact]
public async Task SignOutWithDefaultRedirectUri()
public async Task SignOutFormPostWithDefaultRedirectUri()
{
var configuration = TestServerBuilder.CreateDefaultOpenIdConnectConfiguration();
var server = TestServerBuilder.CreateServer(o =>
var settings = new TestSettings(o =>
{
o.AuthenticationMethod = OpenIdConnectRedirectBehavior.FormPost;
o.Authority = TestServerBuilder.DefaultAuthority;
o.ClientId = "Test Id";
o.Configuration = configuration;
});
var server = settings.CreateTestServer();
var transaction = await server.SendAsync(DefaultHost + TestServerBuilder.Signout);
Assert.Equal(HttpStatusCode.OK, transaction.Response.StatusCode);
settings.ValidateSignoutFormPost(transaction,
OpenIdConnectParameterNames.PostLogoutRedirectUri);
}
[Fact]
public async Task SignOutRedirectWithDefaultRedirectUri()
{
var settings = new TestSettings(o =>
{
o.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet;
o.Authority = TestServerBuilder.DefaultAuthority;
o.ClientId = "Test Id";
});
var server = settings.CreateTestServer();
var transaction = await server.SendAsync(DefaultHost + TestServerBuilder.Signout);
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
Assert.True(transaction.Response.Headers.Location.AbsoluteUri.StartsWith(configuration.EndSessionEndpoint));
var query = transaction.Response.Headers.Location.Query.Substring(1).Split('&')
.Select(each => each.Split('='))
.ToDictionary(pair => pair[0], pair => pair[1]);
string redirectUri;
Assert.True(query.TryGetValue("post_logout_redirect_uri", out redirectUri));
Assert.Equal(UrlEncoder.Default.Encode("https://example.com/signout-callback-oidc"), redirectUri, true);
settings.ValidateSignoutRedirect(transaction.Response.Headers.Location,
OpenIdConnectParameterNames.PostLogoutRedirectUri);
}
[Fact]

View File

@ -80,6 +80,44 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
return formInputs;
}
public IDictionary<string, string> ValidateSignoutFormPost(TestTransaction transaction, params string[] parametersToValidate)
{
IDictionary<string, string> formInputs = null;
var errors = new List<string>();
var xdoc = XDocument.Parse(transaction.ResponseText.Replace("doctype", "DOCTYPE"));
var forms = xdoc.Descendants("form");
if (forms.Count() != 1)
{
errors.Add("Only one form element is expected in response body.");
}
else
{
formInputs = forms.Single()
.Elements("input")
.ToDictionary(elem => elem.Attribute("name").Value,
elem => elem.Attribute("value").Value);
ValidateParameters(formInputs, parametersToValidate, errors, htmlEncoded: false);
}
if (errors.Any())
{
var buf = new StringBuilder();
buf.AppendLine($"The signout form post is not valid.");
// buf.AppendLine();
foreach (var error in errors)
{
buf.AppendLine(error);
}
Debug.WriteLine(buf.ToString());
Assert.True(false, buf.ToString());
}
return formInputs;
}
public IDictionary<string, string> ValidateChallengeRedirect(Uri redirectUri, params string[] parametersToValidate) =>
ValidateRedirectCore(redirectUri, OpenIdConnectRequestType.Authentication, parametersToValidate);
@ -156,6 +194,9 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
case OpenIdConnectParameterNames.VersionTelemetry:
ValidateVersionTelemetry(actualValues, errors, htmlEncoded);
break;
case OpenIdConnectParameterNames.PostLogoutRedirectUri:
ValidatePostLogoutRedirectUri(actualValues, errors, htmlEncoded);
break;
default:
throw new InvalidOperationException($"Unknown parameter \"{paramToValidate}\".");
}
@ -186,42 +227,45 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
}
}
private void ValidateClientId(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
ValidateQueryParameter(OpenIdConnectParameterNames.ClientId, _options.ClientId, actualQuery, errors, htmlEncoded);
private void ValidateClientId(IDictionary<string, string> actualParams, ICollection<string> errors, bool htmlEncoded) =>
ValidateParameter(OpenIdConnectParameterNames.ClientId, _options.ClientId, actualParams, errors, htmlEncoded);
private void ValidateResponseType(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
ValidateQueryParameter(OpenIdConnectParameterNames.ResponseType, _options.ResponseType, actualQuery, errors, htmlEncoded);
private void ValidateResponseType(IDictionary<string, string> actualParams, ICollection<string> errors, bool htmlEncoded) =>
ValidateParameter(OpenIdConnectParameterNames.ResponseType, _options.ResponseType, actualParams, errors, htmlEncoded);
private void ValidateResponseMode(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
ValidateQueryParameter(OpenIdConnectParameterNames.ResponseMode, _options.ResponseMode, actualQuery, errors, htmlEncoded);
private void ValidateResponseMode(IDictionary<string, string> actualParams, ICollection<string> errors, bool htmlEncoded) =>
ValidateParameter(OpenIdConnectParameterNames.ResponseMode, _options.ResponseMode, actualParams, errors, htmlEncoded);
private void ValidateScope(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
ValidateQueryParameter(OpenIdConnectParameterNames.Scope, string.Join(" ", _options.Scope), actualQuery, errors, htmlEncoded);
private void ValidateScope(IDictionary<string, string> actualParams, ICollection<string> errors, bool htmlEncoded) =>
ValidateParameter(OpenIdConnectParameterNames.Scope, string.Join(" ", _options.Scope), actualParams, errors, htmlEncoded);
private void ValidateRedirectUri(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
ValidateQueryParameter(OpenIdConnectParameterNames.RedirectUri, TestServerBuilder.TestHost + _options.CallbackPath, actualQuery, errors, htmlEncoded);
private void ValidateRedirectUri(IDictionary<string, string> actualParams, ICollection<string> errors, bool htmlEncoded) =>
ValidateParameter(OpenIdConnectParameterNames.RedirectUri, TestServerBuilder.TestHost + _options.CallbackPath, actualParams, errors, htmlEncoded);
private void ValidateResource(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
ValidateQueryParameter(OpenIdConnectParameterNames.RedirectUri, _options.Resource, actualQuery, errors, htmlEncoded);
private void ValidateResource(IDictionary<string, string> actualParams, ICollection<string> errors, bool htmlEncoded) =>
ValidateParameter(OpenIdConnectParameterNames.RedirectUri, _options.Resource, actualParams, errors, htmlEncoded);
private void ValidateState(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
ValidateQueryParameter(OpenIdConnectParameterNames.State, ExpectedState, actualQuery, errors, htmlEncoded);
private void ValidateState(IDictionary<string, string> actualParams, ICollection<string> errors, bool htmlEncoded) =>
ValidateParameter(OpenIdConnectParameterNames.State, ExpectedState, actualParams, errors, htmlEncoded);
private void ValidateSkuTelemetry(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
ValidateQueryParameter(OpenIdConnectParameterNames.SkuTelemetry, "ID_NET", actualQuery, errors, htmlEncoded);
private void ValidateSkuTelemetry(IDictionary<string, string> actualParams, ICollection<string> errors, bool htmlEncoded) =>
ValidateParameter(OpenIdConnectParameterNames.SkuTelemetry, "ID_NET", actualParams, errors, htmlEncoded);
private void ValidateVersionTelemetry(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
ValidateQueryParameter(OpenIdConnectParameterNames.VersionTelemetry, typeof(OpenIdConnectMessage).GetTypeInfo().Assembly.GetName().Version.ToString(), actualQuery, errors, htmlEncoded);
private void ValidateVersionTelemetry(IDictionary<string, string> actualParams, ICollection<string> errors, bool htmlEncoded) =>
ValidateParameter(OpenIdConnectParameterNames.VersionTelemetry, typeof(OpenIdConnectMessage).GetTypeInfo().Assembly.GetName().Version.ToString(), actualParams, errors, htmlEncoded);
private void ValidateQueryParameter(
private void ValidatePostLogoutRedirectUri(IDictionary<string, string> actualParams, ICollection<string> errors, bool htmlEncoded) =>
ValidateParameter(OpenIdConnectParameterNames.PostLogoutRedirectUri, "https://example.com/signout-callback-oidc", actualParams, errors, htmlEncoded);
private void ValidateParameter(
string parameterName,
string expectedValue,
IDictionary<string, string> actualQuery,
IDictionary<string, string> actualParams,
ICollection<string> errors,
bool htmlEncoded)
{
string actualValue;
if (actualQuery.TryGetValue(parameterName, out actualValue))
if (actualParams.TryGetValue(parameterName, out actualValue))
{
if (htmlEncoded)
{
@ -230,12 +274,12 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
if (actualValue != expectedValue)
{
errors.Add($"Query parameter {parameterName}'s expected value is {expectedValue} but its actual value is {actualValue}");
errors.Add($"Parameter {parameterName}'s expected value is '{expectedValue}' but its actual value is '{actualValue}'");
}
}
else
{
errors.Add($"Query parameter {parameterName} is missing");
errors.Add($"Parameter {parameterName} is missing");
}
}
}