// 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.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.AspNet.Authentication.Cookies;
using Microsoft.AspNet.Authentication.OpenIdConnect;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Authentication;
using Microsoft.AspNet.TestHost;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.WebEncoders;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Moq;
using Shouldly;
using Xunit;
namespace Microsoft.AspNet.Authentication.Tests.OpenIdConnect
{
public class OpenIdConnectMiddlewareTests
{
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 DefaultAuthority = @"https://example.com/common";
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(options =>
{
options.Authority = DefaultAuthority;
options.ClientId = "Test Id";
options.Configuration = TestUtilities.DefaultOpenIdConnectConfiguration;
options.AuthenticationMethod = OpenIdConnectAuthenticationMethod.FormPost;
});
var transaction = await SendAsync(server, DefaultHost + Challenge);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.OK);
transaction.Response.Content.Headers.ContentType.MediaType.ShouldBe("text/html");
transaction.ResponseText.ShouldContain("form");
}
[Fact]
public async Task ChallengeWillSetDefaults()
{
var stateDataFormat = new AuthenticationPropertiesFormaterKeyValue();
var queryValues = ExpectedQueryValues.Defaults(DefaultAuthority);
queryValues.State = OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey + "=" + stateDataFormat.Protect(new AuthenticationProperties());
var server = CreateServer(options =>
{
SetOptions(options, DefaultParameters(), queryValues);
});
var transaction = await SendAsync(server, DefaultHost + Challenge);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
queryValues.CheckValues(transaction.Response.Headers.Location.AbsoluteUri, DefaultParameters());
}
[Fact]
public async Task ChallengeWillSetNonceCookie()
{
var server = CreateServer(options =>
{
options.Authority = DefaultAuthority;
options.ClientId = "Test Id";
options.Configuration = TestUtilities.DefaultOpenIdConnectConfiguration;
});
var transaction = await SendAsync(server, DefaultHost + Challenge);
transaction.SetCookie.Single().ShouldContain(OpenIdConnectAuthenticationDefaults.CookieNoncePrefix);
}
[Fact]
public async Task ChallengeWillUseOptionsProperties()
{
var queryValues = new ExpectedQueryValues(DefaultAuthority);
var server = CreateServer(options =>
{
SetOptions(options, DefaultParameters(), queryValues);
});
var transaction = await SendAsync(server, DefaultHost + Challenge);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
queryValues.CheckValues(transaction.Response.Headers.Location.AbsoluteUri, DefaultParameters());
}
///
/// Tests RedirectToIdentityProviderContext replaces the OpenIdConnectMesssage correctly.
///
/// Task
[Theory]
[InlineData(Challenge, OpenIdConnectRequestType.AuthenticationRequest)]
[InlineData(Signout, OpenIdConnectRequestType.LogoutRequest)]
public async Task ChallengeSettingMessage(string challenge, OpenIdConnectRequestType requestType)
{
var configuration = new OpenIdConnectConfiguration
{
AuthorizationEndpoint = ExpectedAuthorizeRequest,
EndSessionEndpoint = ExpectedLogoutRequest
};
var queryValues = new ExpectedQueryValues(DefaultAuthority, configuration)
{
RequestType = requestType
};
var server = CreateServer(SetProtocolMessageOptions);
var transaction = await SendAsync(server, DefaultHost + challenge);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
queryValues.CheckValues(transaction.Response.Headers.Location.AbsoluteUri, new string[] {});
}
private static void SetProtocolMessageOptions(OpenIdConnectAuthenticationOptions options)
{
var mockOpenIdConnectMessage = new Mock();
mockOpenIdConnectMessage.Setup(m => m.CreateAuthenticationRequestUrl()).Returns(ExpectedAuthorizeRequest);
mockOpenIdConnectMessage.Setup(m => m.CreateLogoutRequestUrl()).Returns(ExpectedLogoutRequest);
options.AutomaticAuthentication = true;
options.Events = new OpenIdConnectAuthenticationEvents()
{
OnRedirectToIdentityProvider = (context) =>
{
context.ProtocolMessage = mockOpenIdConnectMessage.Object;
return Task.FromResult