Adding verification for openIdconnect logout flow

As well removed the logic to wait for the creation of the db file in userprofile folder
as we now have retry logic.
This commit is contained in:
Praburaj 2015-02-06 12:09:11 -08:00
parent 0d673eafc9
commit 2c881cf6a6
10 changed files with 53 additions and 58 deletions

View File

@ -437,7 +437,7 @@ namespace MusicStore.Controllers
// TODO: Currently SignInManager.SignOut does not sign out OpenIdc and does not have a way to pass in a specific
// AuthType to sign out.
var appEnv = Context.RequestServices.GetService<IHostingEnvironment>();
if (appEnv.EnvironmentName == "OpenIdConnect")
if (appEnv.EnvironmentName.StartsWith("OpenIdConnect"))
{
Response.SignOut("OpenIdConnect");
}

View File

@ -63,7 +63,7 @@ namespace E2ETests
private static string APP_RELATIVE_PATH = Path.Combine("..", "..", "src", "MusicStore");
public static Process StartApplication(StartParameters startParameters, string identityDbName, ILogger logger)
public static Process StartApplication(StartParameters startParameters, ILogger logger)
{
startParameters.ApplicationPath = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, APP_RELATIVE_PATH));
@ -158,7 +158,7 @@ namespace E2ETests
}
else
{
hostProcess = StartSelfHost(startParameters, identityDbName, logger);
hostProcess = StartSelfHost(startParameters, logger);
}
}
@ -205,6 +205,13 @@ namespace E2ETests
var hostProcess = Process.Start(startInfo);
logger.WriteInformation("Started {0}. Process Id : {1}", hostProcess.MainModule.FileName, hostProcess.Id);
if (hostProcess.HasExited)
{
logger.WriteError("Host process {processName} exited with code {exitCode} or failed to start.", startInfo.FileName, hostProcess.ExitCode);
throw new Exception("Failed to start host");
}
return hostProcess;
}
@ -256,7 +263,7 @@ namespace E2ETests
return hostProcess;
}
private static Process StartSelfHost(StartParameters startParameters, string identityDbName, ILogger logger)
private static Process StartSelfHost(StartParameters startParameters, ILogger logger)
{
var commandName = startParameters.ServerType == ServerType.WebListener ? "web" : "kestrel";
logger.WriteInformation("Executing klr.exe --appbase {appPath} \"Microsoft.Framework.ApplicationHost\" {command}", startParameters.ApplicationPath, commandName);
@ -273,6 +280,12 @@ namespace E2ETests
//Sometimes reading MainModule returns null if called immediately after starting process.
Thread.Sleep(1 * 1000);
if (hostProcess.HasExited)
{
logger.WriteError("Host process {processName} exited with code {exitCode} or failed to start.", startInfo.FileName, hostProcess.ExitCode);
throw new Exception("Failed to start host");
}
try
{
logger.WriteInformation("Started {fileName}. Process Id : {processId}", hostProcess.MainModule.FileName, hostProcess.Id);
@ -282,8 +295,6 @@ namespace E2ETests
logger.WriteWarning("Cannot access 64 bit modules from a 32 bit process. Failed with following message.", win32Exception);
}
WaitTillDbCreated(identityDbName, logger);
return hostProcess;
}
@ -342,50 +353,6 @@ namespace E2ETests
logger.WriteInformation("kpm bundle finished with exit code : {exitCode}", hostProcess.ExitCode);
}
//In case of self-host application activation happens immediately unlike iis where activation happens on first request.
//So in self-host case, we need a way to block the first request until the application is initialized. In MusicStore application's case,
//identity DB creation is pretty much the last step of application setup. So waiting on this event will help us wait efficiently.
private static void WaitTillDbCreated(string identityDbName, ILogger logger)
{
var identityDBFullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), identityDbName + ".mdf");
if (File.Exists(identityDBFullPath))
{
logger.WriteWarning("Database file '{mdf}' exists. Proceeding with the tests.", identityDBFullPath);
return;
}
logger.WriteInformation("Watching for the DB file '{mdf}'", identityDBFullPath);
var dbWatch = new FileSystemWatcher(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), identityDbName + ".mdf");
dbWatch.EnableRaisingEvents = true;
try
{
if (!File.Exists(identityDBFullPath))
{
//Wait for a maximum of 1 minute assuming the slowest cold start.
var watchResult = dbWatch.WaitForChanged(WatcherChangeTypes.Created, 60 * 1000);
if (watchResult.ChangeType == WatcherChangeTypes.Created)
{
//This event is fired immediately after the localdb file is created. Give it a while to finish populating data and start the application.
Thread.Sleep(5 * 1000);
logger.WriteInformation("Database file created '{mdf}'. Proceeding with the tests.", identityDBFullPath);
}
else
{
logger.WriteWarning("Database file '{mdf}' not created", identityDBFullPath);
}
}
}
catch (Exception exception)
{
logger.WriteWarning("Received this exception while watching for Database file", exception);
}
finally
{
dbWatch.Dispose();
}
}
public static void CleanUpApplication(StartParameters startParameters, Process hostProcess, string musicStoreDbName, ILogger logger)
{
if (startParameters.ServerType == ServerType.IISNativeModule ||

View File

@ -31,8 +31,7 @@ namespace E2ETests
if (exception.InnerException is HttpRequestException || exception.InnerException is WebException)
{
logger.WriteWarning("Failed to complete the request.", exception);
var waitTimeInMilliSeconds = (RunningOnMono ? 7 : 1) * 1000;
Thread.Sleep(waitTimeInMilliSeconds); //Wait for a second before retry
Thread.Sleep(7 * 1000); //Wait for a while before retry.
}
}
}

View File

@ -82,6 +82,25 @@ namespace E2ETests
//This action requires admin permissions. If notifications are fired this permission is granted
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
_logger.WriteInformation("Middleware notifications were fired successfully");
_logger.WriteInformation("Verifying the OpenIdConnect logout flow..");
response = _httpClient.GetAsync(string.Empty).Result;
ThrowIfResponseStatusNotOk(response);
responseContent = response.Content.ReadAsStringAsync().Result;
ValidateLayoutPage(responseContent);
formParameters = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("__RequestVerificationToken", HtmlDOMHelper.RetrieveAntiForgeryToken(responseContent, "/Account/LogOff")),
};
content = new FormUrlEncodedContent(formParameters.ToArray());
response = _httpClient.PostAsync("Account/LogOff", content).Result;
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
Assert.Equal<string>(
"https://login.windows.net/4afbc689-805b-48cf-a24c-d4aa3248a248/oauth2/logout",
response.RequestMessage.RequestUri.AbsoluteUri.Replace(response.RequestMessage.RequestUri.Query, string.Empty));
queryItems = new ReadableStringCollection(QueryHelpers.ParseQuery(response.RequestMessage.RequestUri.Query));
Assert.Equal<string>(_applicationBaseUrl + "Account/Login", queryItems["post_logout_redirect_uri"]);
}
}
}

View File

@ -56,7 +56,9 @@ namespace E2ETests
_logger.WriteInformation("Application initialization successful.");
_logger.WriteInformation("Application runtime information");
var runtimeInfo = _httpClient.GetAsync("runtimeinfo").Result.Content.ReadAsStringAsync().Result;
var runtimeResponse = _httpClient.GetAsync("runtimeinfo").Result;
ThrowIfResponseStatusNotOk(runtimeResponse);
var runtimeInfo = runtimeResponse.Content.ReadAsStringAsync().Result;
_logger.WriteInformation(runtimeInfo);
}

View File

@ -46,7 +46,7 @@ namespace E2ETests
try
{
hostProcess = DeploymentUtility.StartApplication(_startParameters, musicStoreDbName, _logger);
hostProcess = DeploymentUtility.StartApplication(_startParameters, _logger);
_httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(applicationBaseUrl) };

View File

@ -11,7 +11,7 @@ namespace E2ETests
{
[ConditionalTheory]
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5001/")]
[InlineData(ServerType.IISExpress, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5001/")]
public void OpenIdConnect_OnX86(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
{
OpenIdConnectTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
@ -55,7 +55,7 @@ namespace E2ETests
try
{
hostProcess = DeploymentUtility.StartApplication(_startParameters, musicStoreDbName, _logger);
hostProcess = DeploymentUtility.StartApplication(_startParameters, _logger);
if (serverType == ServerType.IISNativeModule || serverType == ServerType.IIS)
{
// Accomodate the vdir name.

View File

@ -65,7 +65,7 @@ namespace E2ETests
try
{
hostProcess = DeploymentUtility.StartApplication(_startParameters, musicStoreDbName, _logger);
hostProcess = DeploymentUtility.StartApplication(_startParameters, _logger);
_httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(applicationBaseUrl) };

View File

@ -116,7 +116,7 @@ namespace E2ETests
try
{
hostProcess = DeploymentUtility.StartApplication(_startParameters, musicStoreDbName, _logger);
hostProcess = DeploymentUtility.StartApplication(_startParameters, _logger);
if (serverType == ServerType.IISNativeModule || serverType == ServerType.IIS)
{
// Accomodate the vdir name.

View File

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Security.Notifications;
using Microsoft.AspNet.Security.OpenIdConnect;
using Microsoft.IdentityModel.Protocols;
@ -58,6 +59,13 @@ namespace MusicStore.Mocks.OpenIdConnect
(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
{
notificationsFired.Add(nameof(RedirectToIdentityProvider));
if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
context.ProtocolMessage.PostLogoutRedirectUri =
context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + new PathString("/Account/Login");
}
await Task.FromResult(0);
}
}