Update OpenId Connect Challenge Tests
1. Expand the test coverage: add tests covers events work flow. 2. Move OpenID connect challenge tests to their own class. 3. Further refactory the test settings and utilities.
This commit is contained in:
parent
62f0f6e857
commit
abc1b37ee1
|
|
@ -1,70 +0,0 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
||||
{
|
||||
/// <summary>
|
||||
/// This formatter creates an easy to read string of the format: "'key1' 'value1' ..."
|
||||
/// </summary>
|
||||
public class AuthenticationPropertiesFormaterKeyValue : ISecureDataFormat<AuthenticationProperties>
|
||||
{
|
||||
string _protectedString = Guid.NewGuid().ToString();
|
||||
|
||||
public string Protect(AuthenticationProperties data)
|
||||
{
|
||||
if (data == null || data.Items.Count == 0)
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
foreach(var item in data.Items)
|
||||
{
|
||||
sb.Append(Uri.EscapeDataString(item.Key) + " " + Uri.EscapeDataString(item.Value) + " ");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
public string Protect(AuthenticationProperties data, string purpose)
|
||||
{
|
||||
return Protect(data);
|
||||
}
|
||||
|
||||
public AuthenticationProperties Unprotect(string protectedText)
|
||||
{
|
||||
if (string.IsNullOrEmpty(protectedText))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (protectedText == "null")
|
||||
{
|
||||
return new AuthenticationProperties();
|
||||
}
|
||||
|
||||
string[] items = protectedText.Split(' ');
|
||||
if (items.Length % 2 != 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var propeties = new AuthenticationProperties();
|
||||
for (int i = 0; i < items.Length - 1; i+=2)
|
||||
{
|
||||
propeties.Items.Add(items[i], items[i + 1]);
|
||||
}
|
||||
|
||||
return propeties;
|
||||
}
|
||||
|
||||
public AuthenticationProperties Unprotect(string protectedText, string purpose)
|
||||
{
|
||||
return Unprotect(protectedText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
||||
{
|
||||
/// <summary>
|
||||
/// This helper class is used to check that query string parameters are as expected.
|
||||
/// </summary>
|
||||
public class ExpectedQueryValues
|
||||
{
|
||||
public ExpectedQueryValues(string authority, OpenIdConnectConfiguration configuration = null)
|
||||
{
|
||||
Authority = authority;
|
||||
Configuration = configuration ?? TestUtilities.DefaultOpenIdConnectConfiguration;
|
||||
}
|
||||
|
||||
public static ExpectedQueryValues Defaults(string authority)
|
||||
{
|
||||
var result = new ExpectedQueryValues(authority);
|
||||
result.Scope = OpenIdConnectScope.OpenIdProfile;
|
||||
result.ResponseType = OpenIdConnectResponseType.CodeIdToken;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void CheckValues(string query, IEnumerable<string> parameters)
|
||||
{
|
||||
var errors = new List<string>();
|
||||
if (!query.StartsWith(ExpectedAuthority))
|
||||
{
|
||||
errors.Add("ExpectedAuthority: " + ExpectedAuthority);
|
||||
}
|
||||
|
||||
foreach(var str in parameters)
|
||||
{
|
||||
if (str == OpenIdConnectParameterNames.ClientId)
|
||||
{
|
||||
if (!query.Contains(ExpectedClientId))
|
||||
errors.Add("ExpectedClientId: " + ExpectedClientId);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str == OpenIdConnectParameterNames.RedirectUri)
|
||||
{
|
||||
if(!query.Contains(ExpectedRedirectUri))
|
||||
errors.Add("ExpectedRedirectUri: " + ExpectedRedirectUri);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str == OpenIdConnectParameterNames.Resource)
|
||||
{
|
||||
if(!query.Contains(ExpectedResource))
|
||||
errors.Add("ExpectedResource: " + ExpectedResource);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str == OpenIdConnectParameterNames.ResponseMode)
|
||||
{
|
||||
if(!query.Contains(ExpectedResponseMode))
|
||||
errors.Add("ExpectedResponseMode: " + ExpectedResponseMode);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str == OpenIdConnectParameterNames.Scope)
|
||||
{
|
||||
if (!query.Contains(ExpectedScope))
|
||||
errors.Add("ExpectedScope: " + ExpectedScope);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str == OpenIdConnectParameterNames.State)
|
||||
{
|
||||
if (!query.Contains(ExpectedState))
|
||||
errors.Add("ExpectedState: " + ExpectedState);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.Count > 0)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("query string not as expected: " + Environment.NewLine + query + Environment.NewLine);
|
||||
foreach (var str in errors)
|
||||
{
|
||||
sb.AppendLine(str);
|
||||
}
|
||||
|
||||
Debug.WriteLine(sb.ToString());
|
||||
Assert.True(false, sb.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public UrlEncoder Encoder { get; set; } = UrlEncoder.Default;
|
||||
|
||||
public string Authority { get; set; }
|
||||
|
||||
public string ClientId { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
public string RedirectUri { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
public OpenIdConnectRequestType RequestType { get; set; } = OpenIdConnectRequestType.Authentication;
|
||||
|
||||
public string Resource { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
public string ResponseMode { get; set; } = OpenIdConnectResponseMode.FormPost;
|
||||
|
||||
public string ResponseType { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
public string Scope { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
public string State { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
public string ExpectedAuthority
|
||||
{
|
||||
get
|
||||
{
|
||||
if (RequestType == OpenIdConnectRequestType.Token)
|
||||
{
|
||||
return Configuration?.EndSessionEndpoint ?? Authority + @"/oauth2/token";
|
||||
}
|
||||
else if (RequestType == OpenIdConnectRequestType.Logout)
|
||||
{
|
||||
return Configuration?.TokenEndpoint ?? Authority + @"/oauth2/logout";
|
||||
}
|
||||
|
||||
return Configuration?.AuthorizationEndpoint ?? Authority + (@"/oauth2/authorize");
|
||||
}
|
||||
}
|
||||
|
||||
public OpenIdConnectConfiguration Configuration { get; set; }
|
||||
|
||||
public string ExpectedClientId
|
||||
{
|
||||
get { return OpenIdConnectParameterNames.ClientId + "=" + Encoder.Encode(ClientId); }
|
||||
}
|
||||
|
||||
public string ExpectedRedirectUri
|
||||
{
|
||||
get { return OpenIdConnectParameterNames.RedirectUri + "=" + Encoder.Encode(RedirectUri); }
|
||||
}
|
||||
|
||||
public string ExpectedResource
|
||||
{
|
||||
get { return OpenIdConnectParameterNames.Resource + "=" + Encoder.Encode(Resource); }
|
||||
}
|
||||
|
||||
public string ExpectedResponseMode
|
||||
{
|
||||
get { return OpenIdConnectParameterNames.ResponseMode + "=" + Encoder.Encode(ResponseMode); }
|
||||
}
|
||||
|
||||
public string ExpectedScope
|
||||
{
|
||||
get { return OpenIdConnectParameterNames.Scope + "=" + Encoder.Encode(Scope); }
|
||||
}
|
||||
|
||||
public string ExpectedState
|
||||
{
|
||||
get { return Encoder.Encode(State); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect.Infrastructre
|
||||
{
|
||||
internal class TestDefaultValues
|
||||
{
|
||||
public static readonly string DefaultAuthority = @"https://example.com/common";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
||||
{
|
||||
internal class MockOpenIdConnectMessage : OpenIdConnectMessage
|
||||
{
|
||||
public string TestAuthorizeEndpoint { get; set; }
|
||||
|
||||
public string TestLogoutRequest { get; set; }
|
||||
|
||||
public override string CreateAuthenticationRequestUrl()
|
||||
{
|
||||
return TestAuthorizeEndpoint ?? base.CreateAuthenticationRequestUrl();
|
||||
}
|
||||
|
||||
public override string CreateLogoutRequestUrl()
|
||||
{
|
||||
return TestLogoutRequest ?? base.CreateLogoutRequestUrl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,322 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
||||
{
|
||||
public class OpenIdConnectChallengeTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task ChallengeIsIssuedCorrectly()
|
||||
{
|
||||
var settings = new TestSettings(
|
||||
opt => opt.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet);
|
||||
|
||||
var server = settings.CreateTestServer();
|
||||
var transaction = await TestTransaction.SendAsync(server, ChallengeEndpoint);
|
||||
|
||||
var res = transaction.Response;
|
||||
Assert.Equal(HttpStatusCode.Redirect, res.StatusCode);
|
||||
Assert.NotNull(res.Headers.Location);
|
||||
|
||||
settings.ValidateChallengeRedirect(
|
||||
res.Headers.Location,
|
||||
OpenIdConnectParameterNames.ClientId,
|
||||
OpenIdConnectParameterNames.ResponseType,
|
||||
OpenIdConnectParameterNames.ResponseMode,
|
||||
OpenIdConnectParameterNames.Scope,
|
||||
OpenIdConnectParameterNames.RedirectUri);
|
||||
}
|
||||
|
||||
/*
|
||||
Example of a form post
|
||||
<body>
|
||||
<form name=\ "form\" method=\ "post\" action=\ "https://login.microsoftonline.com/common/oauth2/authorize\">
|
||||
<input type=\ "hidden\" name=\ "client_id\" value=\ "51e38103-238f-410f-a5d5-61991b203e50\" />
|
||||
<input type=\ "hidden\" name=\ "redirect_uri\" value=\ "https://example.com/signin-oidc\" />
|
||||
<input type=\ "hidden\" name=\ "response_type\" value=\ "id_token\" />
|
||||
<input type=\ "hidden\" name=\ "scope\" value=\ "openid profile\" />
|
||||
<input type=\ "hidden\" name=\ "response_mode\" value=\ "form_post\" />
|
||||
<input type=\ "hidden\" name=\ "nonce\" value=\ "636072461997914230.NTAwOGE1MjQtM2VhYS00ZDU0LWFkYzYtNmZiYWE2MDRkODg3OTlkMDFmOWUtOTMzNC00ZmI2LTg1Y2YtOWM4OTlhNjY0Yjli\" />
|
||||
<input type=\ "hidden\" name=\ "state\" value=\
|
||||
"CfDJ8Jh1NKaF0T5AnK4qsqzzIs89srKe4iEaBWd29MNph4Ki887QKgkD24wjhZ0ciH-ar6A_jUmRI2O5haXN2-YXbC0ZRuRAvNsx5LqbPTdh4MJBIwXWkG_rM0T0tI3h5Y2pDttWSaku6a_nzFLUYBrKfsE7sDLVoTDrzzOcHrRQhdztqOOeNUuu2wQXaKwlOtNI21ShtN9EVxvSGFOxUUOwVih4nFdF40fBcbsuPpcpCPkLARQaFRJSYsNKiP7pcFMnRwzZhnISHlyGKkzwJ1DIx7nsmdiQFBGljimw5GnYAs-5ru9L3w8NnPjkl96OyQ8MJOcayMDmOY26avs2sYP_Zw0\" />
|
||||
<noscript>Click here to finish the process: <input type=\"submit\" /></noscript>
|
||||
</form>
|
||||
<script>
|
||||
document.form.submit();
|
||||
</script>
|
||||
</body>
|
||||
*/
|
||||
[Fact]
|
||||
public async Task ChallengeIssueedCorrectlyForFormPost()
|
||||
{
|
||||
var settings = new TestSettings(
|
||||
opt => opt.AuthenticationMethod = OpenIdConnectRedirectBehavior.FormPost);
|
||||
|
||||
var server = settings.CreateTestServer();
|
||||
var transaction = await TestTransaction.SendAsync(server, ChallengeEndpoint);
|
||||
|
||||
var res = transaction.Response;
|
||||
Assert.Equal(HttpStatusCode.OK, res.StatusCode);
|
||||
Assert.Equal("text/html", transaction.Response.Content.Headers.ContentType.MediaType);
|
||||
|
||||
var body = await res.Content.ReadAsStringAsync();
|
||||
settings.ValidateChallengeFormPost(
|
||||
body,
|
||||
OpenIdConnectParameterNames.ClientId,
|
||||
OpenIdConnectParameterNames.ResponseType,
|
||||
OpenIdConnectParameterNames.ResponseMode,
|
||||
OpenIdConnectParameterNames.Scope,
|
||||
OpenIdConnectParameterNames.RedirectUri);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("sample_user_state")]
|
||||
[InlineData(null)]
|
||||
public async Task ChallengeCanSetUserStateThroughProperties(string userState)
|
||||
{
|
||||
var settings = new TestSettings();
|
||||
|
||||
var properties = new AuthenticationProperties();
|
||||
properties.Items.Add(OpenIdConnectDefaults.UserstatePropertiesKey, userState);
|
||||
|
||||
var server = TestServerBuilder.CreateServer(settings.Options, handler: null, properties: properties);
|
||||
var transaction = await TestTransaction.SendAsync(server, TestDefaultValues.TestHost + TestServerBuilder.ChallengeWithProperties);
|
||||
|
||||
var res = transaction.Response;
|
||||
Assert.Equal(HttpStatusCode.Redirect, res.StatusCode);
|
||||
Assert.NotNull(res.Headers.Location);
|
||||
|
||||
var values = settings.ValidateChallengeRedirect(res.Headers.Location);
|
||||
var actualState = values[OpenIdConnectParameterNames.State];
|
||||
var actualProperties = settings.Options.StateDataFormat.Unprotect(actualState);
|
||||
|
||||
Assert.Equal(userState ?? string.Empty, actualProperties.Items[OpenIdConnectDefaults.UserstatePropertiesKey]);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("sample_user_state")]
|
||||
[InlineData(null)]
|
||||
public async Task OnRedirectToIdentityProviderEventCanSetState(string userState)
|
||||
{
|
||||
var settings = new TestSettings(opt =>
|
||||
{
|
||||
opt.Events = new OpenIdConnectEvents()
|
||||
{
|
||||
OnRedirectToIdentityProvider = context =>
|
||||
{
|
||||
context.ProtocolMessage.State = userState;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
var server = settings.CreateTestServer();
|
||||
var transaction = await TestTransaction.SendAsync(server, ChallengeEndpoint);
|
||||
|
||||
var res = transaction.Response;
|
||||
Assert.Equal(HttpStatusCode.Redirect, res.StatusCode);
|
||||
Assert.NotNull(res.Headers.Location);
|
||||
|
||||
var values = settings.ValidateChallengeRedirect(res.Headers.Location);
|
||||
var actualState = values[OpenIdConnectParameterNames.State];
|
||||
var actualProperties = settings.Options.StateDataFormat.Unprotect(actualState);
|
||||
|
||||
if (userState != null)
|
||||
{
|
||||
Assert.Equal(userState, actualProperties.Items[OpenIdConnectDefaults.UserstatePropertiesKey]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.False(actualProperties.Items.ContainsKey(OpenIdConnectDefaults.UserstatePropertiesKey));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OnRedirectToIdentityProviderEventIsHit()
|
||||
{
|
||||
var eventIsHit = false;
|
||||
var settings = new TestSettings(
|
||||
opts =>
|
||||
{
|
||||
opts.Events = new OpenIdConnectEvents()
|
||||
{
|
||||
OnRedirectToIdentityProvider = context =>
|
||||
{
|
||||
eventIsHit = true;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
var server = settings.CreateTestServer();
|
||||
var transaction = await TestTransaction.SendAsync(server, ChallengeEndpoint);
|
||||
|
||||
Assert.True(eventIsHit);
|
||||
|
||||
var res = transaction.Response;
|
||||
Assert.Equal(HttpStatusCode.Redirect, res.StatusCode);
|
||||
Assert.NotNull(res.Headers.Location);
|
||||
|
||||
settings.ValidateChallengeRedirect(
|
||||
res.Headers.Location,
|
||||
OpenIdConnectParameterNames.ClientId,
|
||||
OpenIdConnectParameterNames.ResponseType,
|
||||
OpenIdConnectParameterNames.ResponseMode,
|
||||
OpenIdConnectParameterNames.Scope,
|
||||
OpenIdConnectParameterNames.RedirectUri);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task OnRedirectToIdentityProviderEventCanReplaceValues()
|
||||
{
|
||||
var newClientId = Guid.NewGuid().ToString();
|
||||
|
||||
var settings = new TestSettings(
|
||||
opts =>
|
||||
{
|
||||
opts.Events = new OpenIdConnectEvents()
|
||||
{
|
||||
OnRedirectToIdentityProvider = context =>
|
||||
{
|
||||
context.ProtocolMessage.ClientId = newClientId;
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
var server = settings.CreateTestServer();
|
||||
var transaction = await TestTransaction.SendAsync(server, ChallengeEndpoint);
|
||||
|
||||
var res = transaction.Response;
|
||||
Assert.Equal(HttpStatusCode.Redirect, res.StatusCode);
|
||||
Assert.NotNull(res.Headers.Location);
|
||||
|
||||
settings.ValidateChallengeRedirect(
|
||||
res.Headers.Location,
|
||||
OpenIdConnectParameterNames.ResponseType,
|
||||
OpenIdConnectParameterNames.ResponseMode,
|
||||
OpenIdConnectParameterNames.Scope,
|
||||
OpenIdConnectParameterNames.RedirectUri);
|
||||
|
||||
var actual = res.Headers.Location.Query.Trim('?').Split('&').Single(seg => seg.StartsWith($"{OpenIdConnectParameterNames.ClientId}="));
|
||||
Assert.Equal($"{OpenIdConnectParameterNames.ClientId}={newClientId}", actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OnRedirectToIdentityProviderEventCanReplaceMessage()
|
||||
{
|
||||
var newMessage = new MockOpenIdConnectMessage
|
||||
{
|
||||
TestAuthorizeEndpoint = $"http://example.com/{Guid.NewGuid()}/oauth2/signin"
|
||||
};
|
||||
|
||||
var settings = new TestSettings(
|
||||
opts =>
|
||||
{
|
||||
opts.Events = new OpenIdConnectEvents()
|
||||
{
|
||||
OnRedirectToIdentityProvider = context =>
|
||||
{
|
||||
context.ProtocolMessage = newMessage;
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
var server = settings.CreateTestServer();
|
||||
var transaction = await TestTransaction.SendAsync(server, ChallengeEndpoint);
|
||||
|
||||
var res = transaction.Response;
|
||||
Assert.Equal(HttpStatusCode.Redirect, res.StatusCode);
|
||||
Assert.NotNull(res.Headers.Location);
|
||||
|
||||
// The CreateAuthenticationRequestUrl method is overridden MockOpenIdConnectMessage where
|
||||
// query string is not generated and the authorization endpoint is replaced.
|
||||
Assert.Equal(newMessage.TestAuthorizeEndpoint, res.Headers.Location.AbsoluteUri);
|
||||
}
|
||||
[Fact]
|
||||
public async Task OnRedirectToIdentityProviderEventHandlesResponse()
|
||||
{
|
||||
var settings = new TestSettings(
|
||||
opts =>
|
||||
{
|
||||
opts.Events = new OpenIdConnectEvents()
|
||||
{
|
||||
OnRedirectToIdentityProvider = context =>
|
||||
{
|
||||
context.HandleResponse();
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
var server = settings.CreateTestServer();
|
||||
var transaction = await TestTransaction.SendAsync(server, ChallengeEndpoint);
|
||||
|
||||
var res = transaction.Response;
|
||||
Assert.Equal(HttpStatusCode.OK, res.StatusCode);
|
||||
Assert.Null(res.Headers.Location);
|
||||
}
|
||||
|
||||
// This test can be further refined. When one auth middleware skips, the authentication responsibility
|
||||
// will be flowed to the next one. A dummy auth middleware can be added to ensure the correct logic.
|
||||
[Fact]
|
||||
public async Task OnRedirectToIdentityProviderEventSkipResponse()
|
||||
{
|
||||
var settings = new TestSettings(
|
||||
opts =>
|
||||
{
|
||||
opts.Events = new OpenIdConnectEvents()
|
||||
{
|
||||
OnRedirectToIdentityProvider = context =>
|
||||
{
|
||||
context.SkipToNextMiddleware();
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
var server = settings.CreateTestServer();
|
||||
var transaction = await TestTransaction.SendAsync(server, ChallengeEndpoint);
|
||||
|
||||
var res = transaction.Response;
|
||||
Assert.Equal(HttpStatusCode.OK, res.StatusCode);
|
||||
Assert.Null(res.Headers.Location);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ChallengeSetsNonceAndStateCookies()
|
||||
{
|
||||
var settings = new TestSettings();
|
||||
var server = settings.CreateTestServer();
|
||||
var transaction = await TestTransaction.SendAsync(server, ChallengeEndpoint);
|
||||
|
||||
var firstCookie = transaction.SetCookie.First();
|
||||
Assert.Contains(OpenIdConnectDefaults.CookieNoncePrefix, firstCookie);
|
||||
Assert.Contains("expires", firstCookie);
|
||||
|
||||
var secondCookie = transaction.SetCookie.Skip(1).First();
|
||||
Assert.StartsWith(".AspNetCore.Correlation.OpenIdConnect.", secondCookie);
|
||||
Assert.Contains("expires", secondCookie);
|
||||
}
|
||||
|
||||
private static string ChallengeEndpoint => TestDefaultValues.TestHost + TestServerBuilder.Challenge;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect.Infrastructre;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
|
|
|
|||
|
|
@ -2,24 +2,11 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||
using Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect.Infrastructre;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -29,318 +16,47 @@ namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
|||
{
|
||||
static string noncePrefix = "OpenIdConnect." + "Nonce.";
|
||||
static string nonceDelimiter = ".";
|
||||
const string Challenge = "/challenge";
|
||||
const string ChallengeWithOutContext = "/challengeWithOutContext";
|
||||
const string ChallengeWithProperties = "/challengeWithProperties";
|
||||
const string DefaultHost = @"https://example.com";
|
||||
const string ExpectedAuthorizeRequest = @"https://example.com/common/oauth2/signin";
|
||||
const string ExpectedLogoutRequest = @"https://example.com/common/oauth2/logout";
|
||||
const string Logout = "/logout";
|
||||
const string Signin = "/signin";
|
||||
const string Signout = "/signout";
|
||||
|
||||
[Fact]
|
||||
public async Task ChallengeWillIssueHtmlFormWhenEnabled()
|
||||
{
|
||||
var server = CreateServer(new OpenIdConnectOptions
|
||||
{
|
||||
Authority = TestDefaultValues.DefaultAuthority,
|
||||
ClientId = "Test Id",
|
||||
Configuration = TestUtilities.DefaultOpenIdConnectConfiguration,
|
||||
AuthenticationMethod = OpenIdConnectRedirectBehavior.FormPost
|
||||
});
|
||||
var transaction = await SendAsync(server, DefaultHost + Challenge);
|
||||
Assert.Equal(HttpStatusCode.OK, transaction.Response.StatusCode);
|
||||
Assert.Equal("text/html", transaction.Response.Content.Headers.ContentType.MediaType);
|
||||
Assert.Contains("form", transaction.ResponseText);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ChallengeWillSetDefaults()
|
||||
{
|
||||
var stateDataFormat = new AuthenticationPropertiesFormaterKeyValue();
|
||||
var queryValues = ExpectedQueryValues.Defaults(TestDefaultValues.DefaultAuthority);
|
||||
queryValues.State = OpenIdConnectDefaults.AuthenticationPropertiesKey + "=" + stateDataFormat.Protect(new AuthenticationProperties());
|
||||
var server = CreateServer(GetOptions(DefaultParameters(), queryValues));
|
||||
|
||||
var transaction = await SendAsync(server, DefaultHost + Challenge);
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
queryValues.CheckValues(transaction.Response.Headers.Location.AbsoluteUri, DefaultParameters());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ChallengeWillSetNonceAndStateCookies()
|
||||
{
|
||||
var server = CreateServer(new OpenIdConnectOptions
|
||||
{
|
||||
Authority = TestDefaultValues.DefaultAuthority,
|
||||
ClientId = "Test Id",
|
||||
Configuration = TestUtilities.DefaultOpenIdConnectConfiguration
|
||||
});
|
||||
var transaction = await SendAsync(server, DefaultHost + Challenge);
|
||||
|
||||
var firstCookie = transaction.SetCookie.First();
|
||||
Assert.Contains(OpenIdConnectDefaults.CookieNoncePrefix, firstCookie);
|
||||
Assert.Contains("expires", firstCookie);
|
||||
|
||||
var secondCookie = transaction.SetCookie.Skip(1).First();
|
||||
Assert.StartsWith(".AspNetCore.Correlation.OpenIdConnect.", secondCookie);
|
||||
Assert.Contains("expires", secondCookie);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ChallengeWillUseOptionsProperties()
|
||||
{
|
||||
var queryValues = new ExpectedQueryValues(TestDefaultValues.DefaultAuthority);
|
||||
var server = CreateServer(GetOptions(DefaultParameters(), queryValues));
|
||||
|
||||
var transaction = await SendAsync(server, DefaultHost + Challenge);
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
queryValues.CheckValues(transaction.Response.Headers.Location.AbsoluteUri, DefaultParameters());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests RedirectForAuthenticationContext replaces the OpenIdConnectMesssage correctly.
|
||||
/// </summary>
|
||||
/// <returns>Task</returns>
|
||||
[Fact]
|
||||
public async Task ChallengeSettingMessage()
|
||||
{
|
||||
var configuration = new OpenIdConnectConfiguration
|
||||
{
|
||||
AuthorizationEndpoint = ExpectedAuthorizeRequest,
|
||||
};
|
||||
|
||||
var queryValues = new ExpectedQueryValues(TestDefaultValues.DefaultAuthority, configuration)
|
||||
{
|
||||
RequestType = OpenIdConnectRequestType.Authentication
|
||||
};
|
||||
var server = CreateServer(GetProtocolMessageOptions());
|
||||
var transaction = await SendAsync(server, DefaultHost + Challenge);
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
queryValues.CheckValues(transaction.Response.Headers.Location.AbsoluteUri, new string[] { });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests RedirectForSignOutContext replaces the OpenIdConnectMesssage correctly.
|
||||
/// </summary>
|
||||
/// summary>
|
||||
/// <returns>Task</returns>
|
||||
[Fact]
|
||||
public async Task SignOutSettingMessage()
|
||||
{
|
||||
var configuration = new OpenIdConnectConfiguration
|
||||
var setting = new TestSettings(opt =>
|
||||
{
|
||||
EndSessionEndpoint = ExpectedLogoutRequest
|
||||
};
|
||||
|
||||
var queryValues = new ExpectedQueryValues(TestDefaultValues.DefaultAuthority, configuration)
|
||||
{
|
||||
RequestType = OpenIdConnectRequestType.Logout
|
||||
};
|
||||
var server = CreateServer(GetProtocolMessageOptions());
|
||||
var transaction = await SendAsync(server, DefaultHost + Signout);
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
queryValues.CheckValues(transaction.Response.Headers.Location.AbsoluteUri, new string[] { });
|
||||
}
|
||||
|
||||
private static OpenIdConnectOptions GetProtocolMessageOptions()
|
||||
{
|
||||
var options = new OpenIdConnectOptions();
|
||||
var fakeOpenIdRequestMessage = new FakeOpenIdConnectMessage(ExpectedAuthorizeRequest, ExpectedLogoutRequest);
|
||||
options.AutomaticChallenge = true;
|
||||
options.Events = new OpenIdConnectEvents()
|
||||
{
|
||||
OnRedirectToIdentityProvider = (context) =>
|
||||
opt.Configuration = new OpenIdConnectConfiguration
|
||||
{
|
||||
context.ProtocolMessage = fakeOpenIdRequestMessage;
|
||||
return Task.FromResult(0);
|
||||
},
|
||||
OnRedirectToIdentityProviderForSignOut = (context) =>
|
||||
{
|
||||
context.ProtocolMessage = fakeOpenIdRequestMessage;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
};
|
||||
options.ClientId = "Test Id";
|
||||
options.Configuration = TestUtilities.DefaultOpenIdConnectConfiguration;
|
||||
return options;
|
||||
}
|
||||
|
||||
private class FakeOpenIdConnectMessage : OpenIdConnectMessage
|
||||
{
|
||||
private readonly string _authorizeRequest;
|
||||
private readonly string _logoutRequest;
|
||||
|
||||
public FakeOpenIdConnectMessage(string authorizeRequest, string logoutRequest)
|
||||
{
|
||||
_authorizeRequest = authorizeRequest;
|
||||
_logoutRequest = logoutRequest;
|
||||
}
|
||||
|
||||
public override string CreateAuthenticationRequestUrl()
|
||||
{
|
||||
return _authorizeRequest;
|
||||
}
|
||||
|
||||
public override string CreateLogoutRequestUrl()
|
||||
{
|
||||
return _logoutRequest;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests for users who want to add 'state'. There are two ways to do it.
|
||||
/// 1. Users set 'state' (OpenIdConnectMessage.State) in the event. The runtime appends to that state.
|
||||
/// 2. Users add to the AuthenticationProperties (context.AuthenticationProperties), values will be serialized.
|
||||
/// </summary>
|
||||
/// <param name="userSetsState"></param>
|
||||
/// <returns></returns>
|
||||
[Theory, MemberData("StateDataSet")]
|
||||
public async Task ChallengeSettingState(string userState, string challenge)
|
||||
{
|
||||
var queryValues = new ExpectedQueryValues(TestDefaultValues.DefaultAuthority);
|
||||
var stateDataFormat = new AuthenticationPropertiesFormaterKeyValue();
|
||||
var properties = new AuthenticationProperties();
|
||||
if (challenge == ChallengeWithProperties)
|
||||
{
|
||||
properties.Items.Add("item1", Guid.NewGuid().ToString());
|
||||
}
|
||||
|
||||
var options = GetOptions(DefaultParameters(new string[] { OpenIdConnectParameterNames.State }), queryValues, stateDataFormat);
|
||||
options.AutomaticChallenge = challenge.Equals(ChallengeWithOutContext);
|
||||
options.Events = new OpenIdConnectEvents()
|
||||
{
|
||||
OnRedirectToIdentityProvider = context =>
|
||||
{
|
||||
context.ProtocolMessage.State = userState;
|
||||
context.ProtocolMessage.RedirectUri = queryValues.RedirectUri;
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
|
||||
};
|
||||
var server = CreateServer(options, null, properties);
|
||||
|
||||
var transaction = await SendAsync(server, DefaultHost + challenge);
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
|
||||
if (challenge != ChallengeWithProperties)
|
||||
{
|
||||
if (userState != null)
|
||||
{
|
||||
properties.Items.Add(OpenIdConnectDefaults.UserstatePropertiesKey, userState);
|
||||
}
|
||||
properties.Items.Add(OpenIdConnectDefaults.RedirectUriForCodePropertiesKey, queryValues.RedirectUri);
|
||||
}
|
||||
|
||||
queryValues.State = stateDataFormat.Protect(properties);
|
||||
queryValues.CheckValues(transaction.Response.Headers.Location.AbsoluteUri, DefaultParameters(new string[] { OpenIdConnectParameterNames.State }));
|
||||
}
|
||||
|
||||
public static TheoryData<string, string> StateDataSet
|
||||
{
|
||||
get
|
||||
{
|
||||
var dataset = new TheoryData<string, string>();
|
||||
dataset.Add(Guid.NewGuid().ToString(), Challenge);
|
||||
dataset.Add(null, Challenge);
|
||||
dataset.Add(Guid.NewGuid().ToString(), ChallengeWithOutContext);
|
||||
dataset.Add(null, ChallengeWithOutContext);
|
||||
dataset.Add(Guid.NewGuid().ToString(), ChallengeWithProperties);
|
||||
dataset.Add(null, ChallengeWithProperties);
|
||||
|
||||
return dataset;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ChallengeWillUseEvents()
|
||||
{
|
||||
var queryValues = new ExpectedQueryValues(TestDefaultValues.DefaultAuthority);
|
||||
var queryValuesSetInEvent = new ExpectedQueryValues(TestDefaultValues.DefaultAuthority);
|
||||
var options = GetOptions(DefaultParameters(), queryValues);
|
||||
options.Events = new OpenIdConnectEvents()
|
||||
{
|
||||
OnRedirectToIdentityProvider = context =>
|
||||
{
|
||||
context.ProtocolMessage.ClientId = queryValuesSetInEvent.ClientId;
|
||||
context.ProtocolMessage.RedirectUri = queryValuesSetInEvent.RedirectUri;
|
||||
context.ProtocolMessage.Resource = queryValuesSetInEvent.Resource;
|
||||
context.ProtocolMessage.Scope = queryValuesSetInEvent.Scope;
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
};
|
||||
var server = CreateServer(options);
|
||||
|
||||
var transaction = await SendAsync(server, DefaultHost + Challenge);
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
queryValuesSetInEvent.CheckValues(transaction.Response.Headers.Location.AbsoluteUri, DefaultParameters());
|
||||
}
|
||||
|
||||
private OpenIdConnectOptions GetOptions(List<string> parameters, ExpectedQueryValues queryValues, ISecureDataFormat<AuthenticationProperties> secureDataFormat = null)
|
||||
{
|
||||
var options = new OpenIdConnectOptions();
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
if (param.Equals(OpenIdConnectParameterNames.ClientId))
|
||||
options.ClientId = queryValues.ClientId;
|
||||
else if (param.Equals(OpenIdConnectParameterNames.Resource))
|
||||
options.Resource = queryValues.Resource;
|
||||
else if (param.Equals(OpenIdConnectParameterNames.Scope))
|
||||
{
|
||||
options.Scope.Clear();
|
||||
|
||||
foreach (var scope in queryValues.Scope.Split(' '))
|
||||
{
|
||||
options.Scope.Add(scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
options.Authority = queryValues.Authority;
|
||||
options.Configuration = queryValues.Configuration;
|
||||
options.StateDataFormat = secureDataFormat ?? new AuthenticationPropertiesFormaterKeyValue();
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private List<string> DefaultParameters(string[] additionalParams = null)
|
||||
{
|
||||
var parameters =
|
||||
new List<string>
|
||||
{
|
||||
OpenIdConnectParameterNames.ClientId,
|
||||
OpenIdConnectParameterNames.Resource,
|
||||
OpenIdConnectParameterNames.ResponseMode,
|
||||
OpenIdConnectParameterNames.Scope,
|
||||
EndSessionEndpoint = "https://example.com/signout_test/signout_request"
|
||||
};
|
||||
});
|
||||
|
||||
if (additionalParams != null)
|
||||
parameters.AddRange(additionalParams);
|
||||
var server = setting.CreateTestServer();
|
||||
|
||||
return parameters;
|
||||
}
|
||||
var transaction = await TestTransaction.SendAsync(server, DefaultHost + TestServerBuilder.Signout);
|
||||
var res = transaction.Response;
|
||||
|
||||
private static void DefaultChallengeOptions(OpenIdConnectOptions options)
|
||||
{
|
||||
options.AuthenticationScheme = "OpenIdConnectHandlerTest";
|
||||
options.AutomaticChallenge = true;
|
||||
options.ClientId = Guid.NewGuid().ToString();
|
||||
options.ConfigurationManager = TestUtilities.DefaultOpenIdConnectConfigurationManager;
|
||||
options.StateDataFormat = new AuthenticationPropertiesFormaterKeyValue();
|
||||
Assert.Equal(HttpStatusCode.Redirect, res.StatusCode);
|
||||
Assert.NotNull(res.Headers.Location);
|
||||
|
||||
setting.ValidateSignoutRedirect(transaction.Response.Headers.Location);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SignOutWithDefaultRedirectUri()
|
||||
{
|
||||
var configuration = TestUtilities.DefaultOpenIdConnectConfiguration;
|
||||
var server = CreateServer(new OpenIdConnectOptions
|
||||
var configuration = TestDefaultValues.CreateDefaultOpenIdConnectConfiguration();
|
||||
var server = TestServerBuilder.CreateServer(new OpenIdConnectOptions
|
||||
{
|
||||
Authority = TestDefaultValues.DefaultAuthority,
|
||||
ClientId = "Test Id",
|
||||
Configuration = configuration
|
||||
});
|
||||
|
||||
var transaction = await SendAsync(server, DefaultHost + Signout);
|
||||
var transaction = await TestTransaction.SendAsync(server, DefaultHost + TestServerBuilder.Signout);
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
Assert.Equal(configuration.EndSessionEndpoint, transaction.Response.Headers.Location.AbsoluteUri);
|
||||
}
|
||||
|
|
@ -348,8 +64,8 @@ namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
|||
[Fact]
|
||||
public async Task SignOutWithCustomRedirectUri()
|
||||
{
|
||||
var configuration = TestUtilities.DefaultOpenIdConnectConfiguration;
|
||||
var server = CreateServer(new OpenIdConnectOptions
|
||||
var configuration = TestDefaultValues.CreateDefaultOpenIdConnectConfiguration();
|
||||
var server = TestServerBuilder.CreateServer(new OpenIdConnectOptions
|
||||
{
|
||||
Authority = TestDefaultValues.DefaultAuthority,
|
||||
ClientId = "Test Id",
|
||||
|
|
@ -357,7 +73,7 @@ namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
|||
PostLogoutRedirectUri = "https://example.com/logout"
|
||||
});
|
||||
|
||||
var transaction = await SendAsync(server, DefaultHost + Signout);
|
||||
var transaction = await TestTransaction.SendAsync(server, DefaultHost + TestServerBuilder.Signout);
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
Assert.Contains(UrlEncoder.Default.Encode("https://example.com/logout"), transaction.Response.Headers.Location.AbsoluteUri);
|
||||
}
|
||||
|
|
@ -365,8 +81,8 @@ namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
|||
[Fact]
|
||||
public async Task SignOutWith_Specific_RedirectUri_From_Authentication_Properites()
|
||||
{
|
||||
var configuration = TestUtilities.DefaultOpenIdConnectConfiguration;
|
||||
var server = CreateServer(new OpenIdConnectOptions
|
||||
var configuration = TestDefaultValues.CreateDefaultOpenIdConnectConfiguration();
|
||||
var server = TestServerBuilder.CreateServer(new OpenIdConnectOptions
|
||||
{
|
||||
Authority = TestDefaultValues.DefaultAuthority,
|
||||
ClientId = "Test Id",
|
||||
|
|
@ -374,136 +90,13 @@ namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
|||
PostLogoutRedirectUri = "https://example.com/logout"
|
||||
});
|
||||
|
||||
var transaction = await SendAsync(server, "https://example.com/signout_with_specific_redirect_uri");
|
||||
var transaction = await TestTransaction.SendAsync(server, "https://example.com/signout_with_specific_redirect_uri");
|
||||
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
|
||||
Assert.Contains(UrlEncoder.Default.Encode("http://www.example.com/specific_redirect_uri"), transaction.Response.Headers.Location.AbsoluteUri);
|
||||
}
|
||||
|
||||
private static TestServer CreateServer(OpenIdConnectOptions options, Func<HttpContext, Task> handler = null, AuthenticationProperties properties = null)
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseCookieAuthentication(new CookieAuthenticationOptions
|
||||
{
|
||||
AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme
|
||||
});
|
||||
app.UseOpenIdConnectAuthentication(options);
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
var req = context.Request;
|
||||
var res = context.Response;
|
||||
|
||||
if (req.Path == new PathString(Challenge))
|
||||
{
|
||||
await context.Authentication.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme);
|
||||
}
|
||||
else if (req.Path == new PathString(ChallengeWithProperties))
|
||||
{
|
||||
await context.Authentication.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, properties);
|
||||
}
|
||||
else if (req.Path == new PathString(ChallengeWithOutContext))
|
||||
{
|
||||
res.StatusCode = 401;
|
||||
}
|
||||
else if (req.Path == new PathString(Signin))
|
||||
{
|
||||
// REVIEW: this used to just be res.SignIn()
|
||||
await context.Authentication.SignInAsync(OpenIdConnectDefaults.AuthenticationScheme, new ClaimsPrincipal());
|
||||
}
|
||||
else if (req.Path == new PathString(Signout))
|
||||
{
|
||||
await context.Authentication.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
|
||||
}
|
||||
else if (req.Path == new PathString("/signout_with_specific_redirect_uri"))
|
||||
{
|
||||
await context.Authentication.SignOutAsync(
|
||||
OpenIdConnectDefaults.AuthenticationScheme,
|
||||
new AuthenticationProperties() { RedirectUri = "http://www.example.com/specific_redirect_uri" });
|
||||
}
|
||||
else if (handler != null)
|
||||
{
|
||||
await handler(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
await next();
|
||||
}
|
||||
});
|
||||
})
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddAuthentication();
|
||||
services.Configure<SharedAuthenticationOptions>(authOptions =>
|
||||
{
|
||||
authOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
});
|
||||
});
|
||||
return new TestServer(builder);
|
||||
}
|
||||
|
||||
private static async Task<Transaction> SendAsync(TestServer server, string uri, string cookieHeader = null)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, uri);
|
||||
if (!string.IsNullOrEmpty(cookieHeader))
|
||||
{
|
||||
request.Headers.Add("Cookie", cookieHeader);
|
||||
}
|
||||
|
||||
var transaction = new Transaction
|
||||
{
|
||||
Request = request,
|
||||
Response = await server.CreateClient().SendAsync(request),
|
||||
};
|
||||
|
||||
if (transaction.Response.Headers.Contains("Set-Cookie"))
|
||||
{
|
||||
transaction.SetCookie = transaction.Response.Headers.GetValues("Set-Cookie").ToList();
|
||||
}
|
||||
|
||||
transaction.ResponseText = await transaction.Response.Content.ReadAsStringAsync();
|
||||
if (transaction.Response.Content != null &&
|
||||
transaction.Response.Content.Headers.ContentType != null &&
|
||||
transaction.Response.Content.Headers.ContentType.MediaType == "text/xml")
|
||||
{
|
||||
transaction.ResponseElement = XElement.Parse(transaction.ResponseText);
|
||||
}
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
private class Transaction
|
||||
{
|
||||
public HttpRequestMessage Request { get; set; }
|
||||
|
||||
public HttpResponseMessage Response { get; set; }
|
||||
|
||||
public IList<string> SetCookie { get; set; }
|
||||
|
||||
public string ResponseText { get; set; }
|
||||
|
||||
public XElement ResponseElement { get; set; }
|
||||
|
||||
public string AuthenticationCookieValue
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SetCookie != null && SetCookie.Count > 0)
|
||||
{
|
||||
var authCookie = SetCookie.SingleOrDefault(c => c.Contains(".AspNetCore.Cookie="));
|
||||
if (authCookie != null)
|
||||
{
|
||||
return authCookie.Substring(0, authCookie.IndexOf(';'));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
// Test Cases for calculating the expiration time of cookie from cookie name
|
||||
[Fact]
|
||||
public void NonceCookieExpirationTime()
|
||||
{
|
||||
DateTime utcNow = DateTime.UtcNow;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.IdentityModel.Protocols;
|
||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
||||
{
|
||||
internal class TestDefaultValues
|
||||
{
|
||||
public static readonly string DefaultAuthority = @"https://login.microsoftonline.com/common";
|
||||
|
||||
public static readonly string TestHost = @"https://example.com";
|
||||
|
||||
public static OpenIdConnectOptions CreateOpenIdConnectOptions() =>
|
||||
new OpenIdConnectOptions
|
||||
{
|
||||
Authority = TestDefaultValues.DefaultAuthority,
|
||||
ClientId = Guid.NewGuid().ToString(),
|
||||
Configuration = TestDefaultValues.CreateDefaultOpenIdConnectConfiguration()
|
||||
};
|
||||
|
||||
public static OpenIdConnectOptions CreateOpenIdConnectOptions(Action<OpenIdConnectOptions> update)
|
||||
{
|
||||
var options = CreateOpenIdConnectOptions();
|
||||
|
||||
if (update != null)
|
||||
{
|
||||
update(options);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
public static OpenIdConnectConfiguration CreateDefaultOpenIdConnectConfiguration() =>
|
||||
new OpenIdConnectConfiguration()
|
||||
{
|
||||
AuthorizationEndpoint = DefaultAuthority + "/oauth2/authorize",
|
||||
EndSessionEndpoint = DefaultAuthority + "/oauth2/endsessionendpoint",
|
||||
TokenEndpoint = DefaultAuthority + "/oauth2/token"
|
||||
};
|
||||
|
||||
public static IConfigurationManager<OpenIdConnectConfiguration> CreateDefaultOpenIdConnectConfigurationManager() =>
|
||||
new StaticConfigurationManager<OpenIdConnectConfiguration>(CreateDefaultOpenIdConnectConfiguration());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
||||
{
|
||||
internal class TestServerBuilder
|
||||
{
|
||||
public static readonly string Challenge = "/challenge";
|
||||
public static readonly string ChallengeWithOutContext = "/challengeWithOutContext";
|
||||
public static readonly string ChallengeWithProperties = "/challengeWithProperties";
|
||||
public static readonly string Signin = "/signin";
|
||||
public static readonly string Signout = "/signout";
|
||||
|
||||
public static TestServer CreateServer(OpenIdConnectOptions options)
|
||||
{
|
||||
return CreateServer(options, handler: null, properties: null);
|
||||
}
|
||||
|
||||
public static TestServer CreateServer(
|
||||
OpenIdConnectOptions options,
|
||||
Func<HttpContext, Task> handler,
|
||||
AuthenticationProperties properties)
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseCookieAuthentication(new CookieAuthenticationOptions
|
||||
{
|
||||
AuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme
|
||||
});
|
||||
|
||||
app.UseOpenIdConnectAuthentication(options);
|
||||
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
var req = context.Request;
|
||||
var res = context.Response;
|
||||
|
||||
if (req.Path == new PathString(Challenge))
|
||||
{
|
||||
await context.Authentication.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme);
|
||||
}
|
||||
else if (req.Path == new PathString(ChallengeWithProperties))
|
||||
{
|
||||
await context.Authentication.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, properties);
|
||||
}
|
||||
else if (req.Path == new PathString(ChallengeWithOutContext))
|
||||
{
|
||||
res.StatusCode = 401;
|
||||
}
|
||||
else if (req.Path == new PathString(Signin))
|
||||
{
|
||||
// REVIEW: this used to just be res.SignIn()
|
||||
await context.Authentication.SignInAsync(OpenIdConnectDefaults.AuthenticationScheme, new ClaimsPrincipal());
|
||||
}
|
||||
else if (req.Path == new PathString(Signout))
|
||||
{
|
||||
await context.Authentication.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
|
||||
}
|
||||
else if (req.Path == new PathString("/signout_with_specific_redirect_uri"))
|
||||
{
|
||||
await context.Authentication.SignOutAsync(
|
||||
OpenIdConnectDefaults.AuthenticationScheme,
|
||||
new AuthenticationProperties() { RedirectUri = "http://www.example.com/specific_redirect_uri" });
|
||||
}
|
||||
else if (handler != null)
|
||||
{
|
||||
await handler(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
await next();
|
||||
}
|
||||
});
|
||||
})
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddAuthentication();
|
||||
services.Configure<SharedAuthenticationOptions>(authOptions => authOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
});
|
||||
|
||||
return new TestServer(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
||||
{
|
||||
/// <summary>
|
||||
/// This helper class is used to check that query string parameters are as expected.
|
||||
/// </summary>
|
||||
internal class TestSettings
|
||||
{
|
||||
private readonly OpenIdConnectOptions _options;
|
||||
|
||||
public TestSettings() : this(configure: null)
|
||||
{
|
||||
}
|
||||
|
||||
public TestSettings(Action<OpenIdConnectOptions> configure)
|
||||
{
|
||||
_options = TestDefaultValues.CreateOpenIdConnectOptions(configure);
|
||||
}
|
||||
|
||||
public TestSettings(OpenIdConnectOptions options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public OpenIdConnectOptions Options => _options;
|
||||
|
||||
public UrlEncoder Encoder => UrlEncoder.Default;
|
||||
|
||||
public string ExpectedState { get; set; }
|
||||
|
||||
public TestServer CreateTestServer() => TestServerBuilder.CreateServer(Options);
|
||||
|
||||
public IDictionary<string, string> ValidateChallengeFormPost(string responseBody, params string[] parametersToValidate)
|
||||
{
|
||||
IDictionary<string, string> formInputs = null;
|
||||
var errors = new List<string>();
|
||||
var xdoc = XDocument.Parse(responseBody.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 challenge 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);
|
||||
|
||||
public IDictionary<string, string> ValidateSignoutRedirect(Uri redirectUri, params string[] parametersToValidate) =>
|
||||
ValidateRedirectCore(redirectUri, OpenIdConnectRequestType.Logout, parametersToValidate);
|
||||
|
||||
private IDictionary<string, string> ValidateRedirectCore(Uri redirectUri, OpenIdConnectRequestType requestType, string[] parametersToValidate)
|
||||
{
|
||||
var errors = new List<string>();
|
||||
|
||||
// Validate the authority
|
||||
ValidateExpectedAuthority(redirectUri.AbsoluteUri, errors, requestType);
|
||||
|
||||
// Convert query to dictionary
|
||||
var queryDict = string.IsNullOrEmpty(redirectUri.Query) ?
|
||||
new Dictionary<string, string>() :
|
||||
redirectUri.Query.TrimStart('?').Split('&').Select(part => part.Split('=')).ToDictionary(parts => parts[0], parts => parts[1]);
|
||||
|
||||
// Validate the query string parameters
|
||||
ValidateParameters(queryDict, parametersToValidate, errors, htmlEncoded: true);
|
||||
|
||||
if (errors.Any())
|
||||
{
|
||||
var buf = new StringBuilder();
|
||||
buf.AppendLine($"The redirect uri is not valid.");
|
||||
buf.AppendLine(redirectUri.AbsoluteUri);
|
||||
|
||||
foreach (var error in errors)
|
||||
{
|
||||
buf.AppendLine(error);
|
||||
}
|
||||
|
||||
Debug.WriteLine(buf.ToString());
|
||||
Assert.True(false, buf.ToString());
|
||||
}
|
||||
|
||||
return queryDict;
|
||||
}
|
||||
|
||||
private void ValidateParameters(
|
||||
IDictionary<string, string> actualValues,
|
||||
IEnumerable<string> parametersToValidate,
|
||||
ICollection<string> errors,
|
||||
bool htmlEncoded)
|
||||
{
|
||||
foreach (var paramToValidate in parametersToValidate)
|
||||
{
|
||||
switch (paramToValidate)
|
||||
{
|
||||
case OpenIdConnectParameterNames.ClientId:
|
||||
ValidateClientId(actualValues, errors, htmlEncoded);
|
||||
break;
|
||||
case OpenIdConnectParameterNames.ResponseType:
|
||||
ValidateResponseType(actualValues, errors, htmlEncoded);
|
||||
break;
|
||||
case OpenIdConnectParameterNames.ResponseMode:
|
||||
ValidateResponseMode(actualValues, errors, htmlEncoded);
|
||||
break;
|
||||
case OpenIdConnectParameterNames.Scope:
|
||||
ValidateScope(actualValues, errors, htmlEncoded);
|
||||
break;
|
||||
case OpenIdConnectParameterNames.RedirectUri:
|
||||
ValidateRedirectUri(actualValues, errors, htmlEncoded);
|
||||
break;
|
||||
case OpenIdConnectParameterNames.Resource:
|
||||
ValidateResource(actualValues, errors, htmlEncoded);
|
||||
break;
|
||||
case OpenIdConnectParameterNames.State:
|
||||
ValidateState(actualValues, errors, htmlEncoded);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($"Unknown parameter \"{paramToValidate}\".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateExpectedAuthority(string absoluteUri, ICollection<string> errors, OpenIdConnectRequestType requestType)
|
||||
{
|
||||
string expectedAuthority;
|
||||
switch (requestType)
|
||||
{
|
||||
case OpenIdConnectRequestType.Token:
|
||||
expectedAuthority = _options.Configuration?.TokenEndpoint ?? _options.Authority + @"/oauth2/token";
|
||||
break;
|
||||
case OpenIdConnectRequestType.Logout:
|
||||
expectedAuthority = _options.Configuration?.EndSessionEndpoint ?? _options.Authority + @"/oauth2/logout";
|
||||
break;
|
||||
default:
|
||||
expectedAuthority = _options.Configuration?.AuthorizationEndpoint ?? _options.Authority + @"/oauth2/authorize";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!absoluteUri.StartsWith(expectedAuthority))
|
||||
{
|
||||
errors.Add($"ExpectedAuthority: {expectedAuthority}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateClientId(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
|
||||
ValidateQueryParameter(OpenIdConnectParameterNames.ClientId, _options.ClientId, actualQuery, errors, htmlEncoded);
|
||||
|
||||
private void ValidateResponseType(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
|
||||
ValidateQueryParameter(OpenIdConnectParameterNames.ResponseType, _options.ResponseType, actualQuery, errors, htmlEncoded);
|
||||
|
||||
private void ValidateResponseMode(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
|
||||
ValidateQueryParameter(OpenIdConnectParameterNames.ResponseMode, _options.ResponseMode, actualQuery, 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 ValidateRedirectUri(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
|
||||
ValidateQueryParameter(OpenIdConnectParameterNames.RedirectUri, TestDefaultValues.TestHost + _options.CallbackPath, actualQuery, errors, htmlEncoded);
|
||||
|
||||
private void ValidateResource(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
|
||||
ValidateQueryParameter(OpenIdConnectParameterNames.RedirectUri, _options.Resource, actualQuery, errors, htmlEncoded);
|
||||
|
||||
private void ValidateState(IDictionary<string, string> actualQuery, ICollection<string> errors, bool htmlEncoded) =>
|
||||
ValidateQueryParameter(OpenIdConnectParameterNames.State, ExpectedState, actualQuery, errors, htmlEncoded);
|
||||
|
||||
private void ValidateQueryParameter(
|
||||
string parameterName,
|
||||
string expectedValue,
|
||||
IDictionary<string, string> actualQuery,
|
||||
ICollection<string> errors,
|
||||
bool htmlEncoded)
|
||||
{
|
||||
string actualValue;
|
||||
if (actualQuery.TryGetValue(parameterName, out actualValue))
|
||||
{
|
||||
if (htmlEncoded)
|
||||
{
|
||||
expectedValue = Encoder.Encode(expectedValue);
|
||||
}
|
||||
|
||||
if (actualValue != expectedValue)
|
||||
{
|
||||
errors.Add($"Query parameter {parameterName}'s expected value is {expectedValue} but its actual value is {actualValue}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errors.Add($"Query parameter {parameterName} is missing");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
||||
{
|
||||
internal class TestTransaction
|
||||
{
|
||||
public static Task<TestTransaction> SendAsync(TestServer server, string url)
|
||||
{
|
||||
return SendAsync(server, url, cookieHeader: null);
|
||||
}
|
||||
|
||||
public static async Task<TestTransaction> SendAsync(TestServer server, string uri, string cookieHeader)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, uri);
|
||||
if (!string.IsNullOrEmpty(cookieHeader))
|
||||
{
|
||||
request.Headers.Add("Cookie", cookieHeader);
|
||||
}
|
||||
|
||||
var transaction = new TestTransaction
|
||||
{
|
||||
Request = request,
|
||||
Response = await server.CreateClient().SendAsync(request),
|
||||
};
|
||||
|
||||
if (transaction.Response.Headers.Contains("Set-Cookie"))
|
||||
{
|
||||
transaction.SetCookie = transaction.Response.Headers.GetValues("Set-Cookie").ToList();
|
||||
}
|
||||
|
||||
transaction.ResponseText = await transaction.Response.Content.ReadAsStringAsync();
|
||||
if (transaction.Response.Content != null &&
|
||||
transaction.Response.Content.Headers.ContentType != null &&
|
||||
transaction.Response.Content.Headers.ContentType.MediaType == "text/xml")
|
||||
{
|
||||
transaction.ResponseElement = XElement.Parse(transaction.ResponseText);
|
||||
}
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public HttpRequestMessage Request { get; set; }
|
||||
|
||||
public HttpResponseMessage Response { get; set; }
|
||||
|
||||
public IList<string> SetCookie { get; set; }
|
||||
|
||||
public string ResponseText { get; set; }
|
||||
|
||||
public XElement ResponseElement { get; set; }
|
||||
|
||||
public string AuthenticationCookieValue
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SetCookie != null && SetCookie.Count > 0)
|
||||
{
|
||||
var authCookie = SetCookie.SingleOrDefault(c => c.Contains(".AspNetCore.Cookie="));
|
||||
if (authCookie != null)
|
||||
{
|
||||
return authCookie.Substring(0, authCookie.IndexOf(';'));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.IdentityModel.Protocols;
|
||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Tests.OpenIdConnect
|
||||
{
|
||||
/// <summary>
|
||||
/// These utilities are designed to test openidconnect related flows
|
||||
/// </summary>
|
||||
public class TestUtilities
|
||||
{
|
||||
public const string DefaultHost = @"http://localhost";
|
||||
|
||||
public static IConfigurationManager<OpenIdConnectConfiguration> DefaultOpenIdConnectConfigurationManager
|
||||
{
|
||||
get
|
||||
{
|
||||
return new StaticConfigurationManager<OpenIdConnectConfiguration>(DefaultOpenIdConnectConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
public static OpenIdConnectConfiguration DefaultOpenIdConnectConfiguration
|
||||
{
|
||||
get
|
||||
{
|
||||
return new OpenIdConnectConfiguration()
|
||||
{
|
||||
AuthorizationEndpoint = @"https://login.microsoftonline.com/common/oauth2/authorize",
|
||||
EndSessionEndpoint = @"https://login.microsoftonline.com/common/oauth2/endsessionendpoint",
|
||||
TokenEndpoint = @"https://login.microsoftonline.com/common/oauth2/token",
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue