Purge old tests.
This commit is contained in:
parent
b43c27763d
commit
93a88af467
|
|
@ -1,64 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
// All Rights Reserved
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
|
|
||||||
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
|
||||||
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
|
||||||
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
|
||||||
// NON-INFRINGEMENT.
|
|
||||||
// See the Apache 2 License for the specific language governing
|
|
||||||
// permissions and limitations under the License.
|
|
||||||
|
|
||||||
// <copyright file="DenyAnonymous.cs" company="Katana contributors">
|
|
||||||
// Copyright 2011-2012 Katana contributors
|
|
||||||
// </copyright>
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Security.Principal;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Security.Windows.Tests
|
|
||||||
{
|
|
||||||
using AppFunc = Func<IDictionary<string, object>, Task>;
|
|
||||||
|
|
||||||
// This middleware can be placed at the end of a chain of pass-through auth schemes if at least one type of auth is required.
|
|
||||||
public class DenyAnonymous
|
|
||||||
{
|
|
||||||
private readonly AppFunc _nextApp;
|
|
||||||
|
|
||||||
public DenyAnonymous(AppFunc nextApp)
|
|
||||||
{
|
|
||||||
_nextApp = nextApp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Invoke(IDictionary<string, object> env)
|
|
||||||
{
|
|
||||||
if (env.Get<IPrincipal>("server.User") == null)
|
|
||||||
{
|
|
||||||
env["owin.ResponseStatusCode"] = 401;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await _nextApp(env);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
// All Rights Reserved
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
|
|
||||||
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
|
||||||
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
|
||||||
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
|
||||||
// NON-INFRINGEMENT.
|
|
||||||
// See the Apache 2 License for the specific language governing
|
|
||||||
// permissions and limitations under the License.
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// <copyright file="DictionaryExtensions.cs" company="Microsoft">
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace System.Collections.Generic
|
|
||||||
{
|
|
||||||
internal static class DictionaryExtensions
|
|
||||||
{
|
|
||||||
internal static void Append(this IDictionary<string, string[]> dictionary, string key, string value)
|
|
||||||
{
|
|
||||||
string[] orriginalValues;
|
|
||||||
if (dictionary.TryGetValue(key, out orriginalValues))
|
|
||||||
{
|
|
||||||
string[] newValues = new string[orriginalValues.Length + 1];
|
|
||||||
orriginalValues.CopyTo(newValues, 0);
|
|
||||||
newValues[newValues.Length - 1] = value;
|
|
||||||
dictionary[key] = newValues;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dictionary[key] = new string[] { value };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string Get(this IDictionary<string, string[]> dictionary, string key)
|
|
||||||
{
|
|
||||||
string[] values;
|
|
||||||
if (dictionary.TryGetValue(key, out values))
|
|
||||||
{
|
|
||||||
return string.Join(", ", values);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static T Get<T>(this IDictionary<string, object> dictionary, string key, T fallback = default(T))
|
|
||||||
{
|
|
||||||
object values;
|
|
||||||
if (dictionary.TryGetValue(key, out values))
|
|
||||||
{
|
|
||||||
return (T)values;
|
|
||||||
}
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,261 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
// All Rights Reserved
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
|
|
||||||
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
|
||||||
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
|
||||||
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
|
||||||
// NON-INFRINGEMENT.
|
|
||||||
// See the Apache 2 License for the specific language governing
|
|
||||||
// permissions and limitations under the License.
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// <copyright file="DigestTests.cs" company="Microsoft">
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Security.Authentication.ExtendedProtection;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNet.Server.WebListener;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Security.Windows.Tests
|
|
||||||
{
|
|
||||||
using AppFunc = Func<IDictionary<string, object>, Task>;
|
|
||||||
|
|
||||||
public class DigestTests
|
|
||||||
{
|
|
||||||
private const string Address = "http://localhost:8080/";
|
|
||||||
private const string SecureAddress = "https://localhost:9090/";
|
|
||||||
private const int DefaultStatusCode = 201;
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Digest_PartialMatch_PassedThrough()
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(SimpleApp);
|
|
||||||
IDictionary<string, object> emptyEnv = CreateEmptyRequest("Authorization", "Digestion blablabla");
|
|
||||||
await windowsAuth.Invoke(emptyEnv);
|
|
||||||
|
|
||||||
Assert.Equal(DefaultStatusCode, emptyEnv.Get<int>("owin.ResponseStatusCode"));
|
|
||||||
var responseHeaders = emptyEnv.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
|
||||||
Assert.Equal(0, responseHeaders.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Digest_BadData_400()
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(SimpleApp);
|
|
||||||
IDictionary<string, object> emptyEnv = CreateEmptyRequest("Authorization", "Digest blablabla");
|
|
||||||
await windowsAuth.Invoke(emptyEnv);
|
|
||||||
|
|
||||||
Assert.Equal(400, emptyEnv.Get<int>("owin.ResponseStatusCode"));
|
|
||||||
var responseHeaders = emptyEnv.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
|
||||||
Assert.Equal(0, responseHeaders.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Digest_AppSets401_401WithChallenge()
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(new DenyAnonymous(SimpleApp).Invoke);
|
|
||||||
windowsAuth.AuthenticationSchemes = AuthTypes.Digest;
|
|
||||||
IDictionary<string, object> emptyEnv = CreateEmptyRequest();
|
|
||||||
await windowsAuth.Invoke(emptyEnv);
|
|
||||||
FireOnSendingHeadersActions(emptyEnv);
|
|
||||||
|
|
||||||
Assert.Equal(401, emptyEnv.Get<int>("owin.ResponseStatusCode"));
|
|
||||||
var responseHeaders = emptyEnv.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
|
||||||
Assert.Equal(1, responseHeaders.Count);
|
|
||||||
Assert.NotNull(responseHeaders.Get("www-authenticate"));
|
|
||||||
Assert.True(responseHeaders.Get("www-authenticate").StartsWith("Digest "));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Digest_CbtOptionalButNotPresent_401WithChallenge()
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(new DenyAnonymous(SimpleApp).Invoke);
|
|
||||||
windowsAuth.AuthenticationSchemes = AuthTypes.Digest;
|
|
||||||
windowsAuth.ExtendedProtectionPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.WhenSupported);
|
|
||||||
IDictionary<string, object> emptyEnv = CreateEmptyRequest();
|
|
||||||
emptyEnv["owin.RequestScheme"] = "https";
|
|
||||||
await windowsAuth.Invoke(emptyEnv);
|
|
||||||
FireOnSendingHeadersActions(emptyEnv);
|
|
||||||
|
|
||||||
Assert.Equal(401, emptyEnv.Get<int>("owin.ResponseStatusCode"));
|
|
||||||
var responseHeaders = emptyEnv.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
|
||||||
Assert.Equal(0, responseHeaders.Count);
|
|
||||||
Assert.Null(responseHeaders.Get("www-authenticate"));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Digest_CbtRequiredButNotPresent_400()
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(new DenyAnonymous(SimpleApp).Invoke);
|
|
||||||
windowsAuth.AuthenticationSchemes = AuthTypes.Digest;
|
|
||||||
windowsAuth.ExtendedProtectionPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Always);
|
|
||||||
IDictionary<string, object> emptyEnv = CreateEmptyRequest();
|
|
||||||
emptyEnv["owin.RequestScheme"] = "https";
|
|
||||||
await windowsAuth.Invoke(emptyEnv);
|
|
||||||
FireOnSendingHeadersActions(emptyEnv);
|
|
||||||
|
|
||||||
Assert.Equal(401, emptyEnv.Get<int>("owin.ResponseStatusCode"));
|
|
||||||
var responseHeaders = emptyEnv.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
|
||||||
Assert.Equal(0, responseHeaders.Count);
|
|
||||||
Assert.Null(responseHeaders.Get("www-authenticate"));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact(Skip = "Broken")]
|
|
||||||
public async Task Digest_ClientAuthenticates_Success()
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(new DenyAnonymous(SimpleApp).Invoke);
|
|
||||||
windowsAuth.AuthenticationSchemes = AuthTypes.Digest;
|
|
||||||
|
|
||||||
using (CreateServer(windowsAuth.Invoke))
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await SendAuthRequestAsync(Address);
|
|
||||||
Assert.Equal(DefaultStatusCode, (int)response.StatusCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact(Skip = "Broken")]
|
|
||||||
public async Task Digest_ClientAuthenticatesMultipleTimes_Success()
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(new DenyAnonymous(SimpleApp).Invoke);
|
|
||||||
windowsAuth.AuthenticationSchemes = AuthTypes.Digest;
|
|
||||||
|
|
||||||
using (CreateServer(windowsAuth.Invoke))
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 10; i++)
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await SendAuthRequestAsync(Address);
|
|
||||||
Assert.Equal(DefaultStatusCode, (int)response.StatusCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task Digest_AnonmousClient_401()
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(new DenyAnonymous(SimpleApp).Invoke);
|
|
||||||
windowsAuth.AuthenticationSchemes = AuthTypes.Digest;
|
|
||||||
|
|
||||||
using (CreateServer(windowsAuth.Invoke))
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await SendRequestAsync(Address);
|
|
||||||
Assert.Equal(401, (int)response.StatusCode);
|
|
||||||
Assert.True(response.Headers.WwwAuthenticate.ToString().StartsWith("Digest "));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact(Skip = "Broken")]
|
|
||||||
public async Task Digest_ClientAuthenticatesWithCbt_Success()
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(new DenyAnonymous(SimpleApp).Invoke);
|
|
||||||
windowsAuth.AuthenticationSchemes = AuthTypes.Digest;
|
|
||||||
windowsAuth.ExtendedProtectionPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Always);
|
|
||||||
|
|
||||||
using (CreateSecureServer(windowsAuth.Invoke))
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await SendAuthRequestAsync(SecureAddress);
|
|
||||||
Assert.Equal(DefaultStatusCode, (int)response.StatusCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IDictionary<string, object> CreateEmptyRequest(string header = null, string value = null)
|
|
||||||
{
|
|
||||||
IDictionary<string, object> env = new Dictionary<string, object>();
|
|
||||||
var requestHeaders = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
env["owin.RequestHeaders"] = requestHeaders;
|
|
||||||
if (header != null)
|
|
||||||
{
|
|
||||||
requestHeaders[header] = new string[] { value };
|
|
||||||
}
|
|
||||||
env["owin.ResponseHeaders"] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
var onSendingHeadersActions = new List<Tuple<Action<object>, object>>();
|
|
||||||
env["server.OnSendingHeaders"] = new Action<Action<object>, object>(
|
|
||||||
(a, b) => onSendingHeadersActions.Add(new Tuple<Action<object>, object>(a, b)));
|
|
||||||
|
|
||||||
env["test.OnSendingHeadersActions"] = onSendingHeadersActions;
|
|
||||||
return env;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FireOnSendingHeadersActions(IDictionary<string, object> env)
|
|
||||||
{
|
|
||||||
var onSendingHeadersActions = env.Get<IList<Tuple<Action<object>, object>>>("test.OnSendingHeadersActions");
|
|
||||||
foreach (var actionPair in onSendingHeadersActions.Reverse())
|
|
||||||
{
|
|
||||||
actionPair.Item1(actionPair.Item2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IDisposable CreateServer(AppFunc app)
|
|
||||||
{
|
|
||||||
IDictionary<string, object> properties = new Dictionary<string, object>();
|
|
||||||
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
|
|
||||||
properties["host.Addresses"] = addresses;
|
|
||||||
|
|
||||||
IDictionary<string, object> address = new Dictionary<string, object>();
|
|
||||||
addresses.Add(address);
|
|
||||||
|
|
||||||
address["scheme"] = "http";
|
|
||||||
address["host"] = "localhost";
|
|
||||||
address["port"] = "8080";
|
|
||||||
address["path"] = string.Empty;
|
|
||||||
|
|
||||||
return OwinServerFactory.Create(app, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IDisposable CreateSecureServer(AppFunc app)
|
|
||||||
{
|
|
||||||
IDictionary<string, object> properties = new Dictionary<string, object>();
|
|
||||||
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
|
|
||||||
properties["host.Addresses"] = addresses;
|
|
||||||
|
|
||||||
IDictionary<string, object> address = new Dictionary<string, object>();
|
|
||||||
addresses.Add(address);
|
|
||||||
|
|
||||||
address["scheme"] = "https";
|
|
||||||
address["host"] = "localhost";
|
|
||||||
address["port"] = "9090";
|
|
||||||
address["path"] = string.Empty;
|
|
||||||
|
|
||||||
return OwinServerFactory.Create(app, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<HttpResponseMessage> SendRequestAsync(string uri)
|
|
||||||
{
|
|
||||||
using (HttpClient client = new HttpClient())
|
|
||||||
{
|
|
||||||
return await client.GetAsync(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<HttpResponseMessage> SendAuthRequestAsync(string uri)
|
|
||||||
{
|
|
||||||
WebRequestHandler handler = new WebRequestHandler();
|
|
||||||
handler.UseDefaultCredentials = true;
|
|
||||||
handler.ServerCertificateValidationCallback = (a, b, c, d) => true;
|
|
||||||
using (HttpClient client = new HttpClient(handler))
|
|
||||||
{
|
|
||||||
return await client.GetAsync(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SimpleApp(IDictionary<string, object> env)
|
|
||||||
{
|
|
||||||
env["owin.ResponseStatusCode"] = DefaultStatusCode;
|
|
||||||
return Task.FromResult<object>(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,278 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
// All Rights Reserved
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
|
|
||||||
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
|
||||||
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
|
||||||
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
|
||||||
// NON-INFRINGEMENT.
|
|
||||||
// See the Apache 2 License for the specific language governing
|
|
||||||
// permissions and limitations under the License.
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// <copyright file="NegotiateTests.cs" company="Microsoft">
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Security.Authentication.ExtendedProtection;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNet.Server.WebListener;
|
|
||||||
using Xunit;
|
|
||||||
using Xunit.Extensions;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Security.Windows.Tests
|
|
||||||
{
|
|
||||||
using AppFunc = Func<IDictionary<string, object>, Task>;
|
|
||||||
|
|
||||||
public class NegotiateTests
|
|
||||||
{
|
|
||||||
private const string Address = "http://localhost:8080/";
|
|
||||||
private const string SecureAddress = "https://localhost:9090/";
|
|
||||||
private const int DefaultStatusCode = 201;
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("Negotiate")]
|
|
||||||
[InlineData("NTLM")]
|
|
||||||
public async Task Negotiate_PartialMatch_PassedThrough(string package)
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(SimpleApp);
|
|
||||||
IDictionary<string, object> emptyEnv = CreateEmptyRequest("Authorization", package + "ion blablabla");
|
|
||||||
await windowsAuth.Invoke(emptyEnv);
|
|
||||||
|
|
||||||
Assert.Equal(DefaultStatusCode, emptyEnv.Get<int>("owin.ResponseStatusCode"));
|
|
||||||
var responseHeaders = emptyEnv.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
|
||||||
Assert.Equal(0, responseHeaders.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("Negotiate")]
|
|
||||||
[InlineData("NTLM")]
|
|
||||||
public async Task Negotiate_BadData_400(string package)
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(SimpleApp);
|
|
||||||
IDictionary<string, object> emptyEnv = CreateEmptyRequest("Authorization", package + " blablabla");
|
|
||||||
await windowsAuth.Invoke(emptyEnv);
|
|
||||||
|
|
||||||
Assert.Equal(400, emptyEnv.Get<int>("owin.ResponseStatusCode"));
|
|
||||||
var responseHeaders = emptyEnv.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
|
||||||
Assert.Equal(0, responseHeaders.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("Negotiate")]
|
|
||||||
[InlineData("NTLM")]
|
|
||||||
public async Task Negotiate_AppSets401_401WithChallenge(string package)
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(SimpleApp401);
|
|
||||||
windowsAuth.AuthenticationSchemes = (AuthTypes)Enum.Parse(typeof(AuthTypes), package, true);
|
|
||||||
IDictionary<string, object> emptyEnv = CreateEmptyRequest();
|
|
||||||
await windowsAuth.Invoke(emptyEnv);
|
|
||||||
FireOnSendingHeadersActions(emptyEnv);
|
|
||||||
|
|
||||||
Assert.Equal(401, emptyEnv.Get<int>("owin.ResponseStatusCode"));
|
|
||||||
var responseHeaders = emptyEnv.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
|
||||||
Assert.Equal(1, responseHeaders.Count);
|
|
||||||
Assert.NotNull(responseHeaders.Get("www-authenticate"));
|
|
||||||
Assert.Equal(package, responseHeaders.Get("www-authenticate"));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory(Skip = "Broken")]
|
|
||||||
[InlineData("Negotiate")]
|
|
||||||
[InlineData("NTLM")]
|
|
||||||
public async Task Negotiate_ClientAuthenticates_Success(string package)
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(new DenyAnonymous(SimpleApp).Invoke);
|
|
||||||
windowsAuth.AuthenticationSchemes = (AuthTypes)Enum.Parse(typeof(AuthTypes), package, true);
|
|
||||||
|
|
||||||
using (CreateServer(windowsAuth.Invoke))
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await SendAuthRequestAsync(Address);
|
|
||||||
Assert.Equal(DefaultStatusCode, (int)response.StatusCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory(Skip = "Broken")]
|
|
||||||
[InlineData("Negotiate")]
|
|
||||||
[InlineData("NTLM")]
|
|
||||||
public async Task Negotiate_ClientAuthenticatesMultipleTimes_Success(string package)
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(new DenyAnonymous(SimpleApp).Invoke);
|
|
||||||
windowsAuth.AuthenticationSchemes = (AuthTypes)Enum.Parse(typeof(AuthTypes), package, true);
|
|
||||||
|
|
||||||
using (CreateServer(windowsAuth.Invoke))
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 10; i++)
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await SendAuthRequestAsync(Address);
|
|
||||||
Assert.Equal(DefaultStatusCode, (int)response.StatusCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("Negotiate")]
|
|
||||||
[InlineData("NTLM")]
|
|
||||||
public async Task Negotiate_AnonmousClient_401(string package)
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(new DenyAnonymous(SimpleApp).Invoke);
|
|
||||||
windowsAuth.AuthenticationSchemes = (AuthTypes)Enum.Parse(typeof(AuthTypes), package, true);
|
|
||||||
|
|
||||||
using (CreateServer(windowsAuth.Invoke))
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await SendRequestAsync(Address);
|
|
||||||
Assert.Equal(401, (int)response.StatusCode);
|
|
||||||
Assert.Equal(package, response.Headers.WwwAuthenticate.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact(Skip = "Broken")]
|
|
||||||
public async Task UnsafeSharedNTLM_AuthenticatedClient_Success()
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(new DenyAnonymous(SimpleApp).Invoke);
|
|
||||||
windowsAuth.AuthenticationSchemes = AuthTypes.Ntlm;
|
|
||||||
windowsAuth.UnsafeConnectionNtlmAuthentication = true;
|
|
||||||
|
|
||||||
using (CreateServer(windowsAuth.Invoke))
|
|
||||||
{
|
|
||||||
WebRequestHandler handler = new WebRequestHandler();
|
|
||||||
CredentialCache cache = new CredentialCache();
|
|
||||||
cache.Add(new Uri(Address), "NTLM", CredentialCache.DefaultNetworkCredentials);
|
|
||||||
handler.Credentials = cache;
|
|
||||||
handler.UnsafeAuthenticatedConnectionSharing = true;
|
|
||||||
using (HttpClient client = new HttpClient(handler))
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await client.GetAsync(Address);
|
|
||||||
Assert.Equal(DefaultStatusCode, (int)response.StatusCode);
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
// Remove the credentials before try two just to prove they aren't used.
|
|
||||||
cache.Remove(new Uri(Address), "NTLM");
|
|
||||||
response = await client.GetAsync(Address);
|
|
||||||
Assert.Equal(DefaultStatusCode, (int)response.StatusCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory(Skip = "Broken")]
|
|
||||||
[InlineData("Negotiate")]
|
|
||||||
[InlineData("NTLM")]
|
|
||||||
public async Task Negotiate_ClientAuthenticatesWithCbt_Success(string package)
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(new DenyAnonymous(SimpleApp).Invoke);
|
|
||||||
windowsAuth.AuthenticationSchemes = (AuthTypes)Enum.Parse(typeof(AuthTypes), package, true);
|
|
||||||
windowsAuth.ExtendedProtectionPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Always);
|
|
||||||
|
|
||||||
using (CreateSecureServer(windowsAuth.Invoke))
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await SendAuthRequestAsync(SecureAddress);
|
|
||||||
Assert.Equal(DefaultStatusCode, (int)response.StatusCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IDictionary<string, object> CreateEmptyRequest(string header = null, string value = null, string connectionId = "Random")
|
|
||||||
{
|
|
||||||
IDictionary<string, object> env = new Dictionary<string, object>();
|
|
||||||
var requestHeaders = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
env["owin.RequestHeaders"] = requestHeaders;
|
|
||||||
if (header != null)
|
|
||||||
{
|
|
||||||
requestHeaders[header] = new string[] { value };
|
|
||||||
}
|
|
||||||
env["owin.ResponseHeaders"] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
var onSendingHeadersActions = new List<Tuple<Action<object>, object>>();
|
|
||||||
env["server.OnSendingHeaders"] = new Action<Action<object>, object>(
|
|
||||||
(a, b) => onSendingHeadersActions.Add(new Tuple<Action<object>, object>(a, b)));
|
|
||||||
|
|
||||||
env["test.OnSendingHeadersActions"] = onSendingHeadersActions;
|
|
||||||
env["server.ConnectionId"] = connectionId;
|
|
||||||
return env;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FireOnSendingHeadersActions(IDictionary<string, object> env)
|
|
||||||
{
|
|
||||||
var onSendingHeadersActions = env.Get<IList<Tuple<Action<object>, object>>>("test.OnSendingHeadersActions");
|
|
||||||
foreach (var actionPair in onSendingHeadersActions.Reverse())
|
|
||||||
{
|
|
||||||
actionPair.Item1(actionPair.Item2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IDisposable CreateServer(AppFunc app)
|
|
||||||
{
|
|
||||||
IDictionary<string, object> properties = new Dictionary<string, object>();
|
|
||||||
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
|
|
||||||
properties["host.Addresses"] = addresses;
|
|
||||||
|
|
||||||
IDictionary<string, object> address = new Dictionary<string, object>();
|
|
||||||
addresses.Add(address);
|
|
||||||
|
|
||||||
address["scheme"] = "http";
|
|
||||||
address["host"] = "localhost";
|
|
||||||
address["port"] = "8080";
|
|
||||||
address["path"] = string.Empty;
|
|
||||||
|
|
||||||
return OwinServerFactory.Create(app, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IDisposable CreateSecureServer(AppFunc app)
|
|
||||||
{
|
|
||||||
IDictionary<string, object> properties = new Dictionary<string, object>();
|
|
||||||
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
|
|
||||||
properties["host.Addresses"] = addresses;
|
|
||||||
|
|
||||||
IDictionary<string, object> address = new Dictionary<string, object>();
|
|
||||||
addresses.Add(address);
|
|
||||||
|
|
||||||
address["scheme"] = "https";
|
|
||||||
address["host"] = "localhost";
|
|
||||||
address["port"] = "9090";
|
|
||||||
address["path"] = string.Empty;
|
|
||||||
|
|
||||||
return OwinServerFactory.Create(app, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<HttpResponseMessage> SendRequestAsync(string uri)
|
|
||||||
{
|
|
||||||
using (HttpClient client = new HttpClient())
|
|
||||||
{
|
|
||||||
return await client.GetAsync(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<HttpResponseMessage> SendAuthRequestAsync(string uri)
|
|
||||||
{
|
|
||||||
WebRequestHandler handler = new WebRequestHandler();
|
|
||||||
handler.UseDefaultCredentials = true;
|
|
||||||
handler.ServerCertificateValidationCallback = (a, b, c, d) => true;
|
|
||||||
using (HttpClient client = new HttpClient(handler))
|
|
||||||
{
|
|
||||||
return await client.GetAsync(uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SimpleApp(IDictionary<string, object> env)
|
|
||||||
{
|
|
||||||
env["owin.ResponseStatusCode"] = DefaultStatusCode;
|
|
||||||
return Task.FromResult<object>(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SimpleApp401(IDictionary<string, object> env)
|
|
||||||
{
|
|
||||||
env["owin.ResponseStatusCode"] = 401;
|
|
||||||
return Task.FromResult<object>(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
// All Rights Reserved
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
|
|
||||||
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
|
||||||
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
|
||||||
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
|
||||||
// NON-INFRINGEMENT.
|
|
||||||
// See the Apache 2 License for the specific language governing
|
|
||||||
// permissions and limitations under the License.
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// <copyright file="PassThroughTests.cs" company="Microsoft">
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Security.Windows.Tests
|
|
||||||
{
|
|
||||||
public class PassThroughTests
|
|
||||||
{
|
|
||||||
private const int DefaultStatusCode = 201;
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task PassThrough_EmptyRequest_Success()
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(SimpleApp);
|
|
||||||
IDictionary<string, object> emptyEnv = CreateEmptyRequest();
|
|
||||||
await windowsAuth.Invoke(emptyEnv);
|
|
||||||
|
|
||||||
Assert.Equal(DefaultStatusCode, emptyEnv.Get<int>("owin.ResponseStatusCode"));
|
|
||||||
var responseHeaders = emptyEnv.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
|
||||||
Assert.Equal(0, responseHeaders.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public async Task PassThrough_BasicAuth_Success()
|
|
||||||
{
|
|
||||||
WindowsAuthMiddleware windowsAuth = new WindowsAuthMiddleware(SimpleApp);
|
|
||||||
IDictionary<string, object> emptyEnv = CreateEmptyRequest("Authorization", "Basic blablabla");
|
|
||||||
await windowsAuth.Invoke(emptyEnv);
|
|
||||||
|
|
||||||
Assert.Equal(DefaultStatusCode, emptyEnv.Get<int>("owin.ResponseStatusCode"));
|
|
||||||
var responseHeaders = emptyEnv.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");
|
|
||||||
Assert.Equal(0, responseHeaders.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IDictionary<string, object> CreateEmptyRequest(string header = null, string value = null)
|
|
||||||
{
|
|
||||||
IDictionary<string, object> env = new Dictionary<string, object>();
|
|
||||||
var requestHeaders = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
env["owin.RequestHeaders"] = requestHeaders;
|
|
||||||
if (header != null)
|
|
||||||
{
|
|
||||||
requestHeaders[header] = new string[] { value };
|
|
||||||
}
|
|
||||||
env["owin.ResponseHeaders"] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
env["server.OnSendingHeaders"] = new Action<Action<object>, object>((a, b) => { });
|
|
||||||
return env;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task SimpleApp(IDictionary<string, object> env)
|
|
||||||
{
|
|
||||||
env["owin.ResponseStatusCode"] = DefaultStatusCode;
|
|
||||||
return Task.FromResult<object>(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
|
||||||
// All Rights Reserved
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
|
|
||||||
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
|
||||||
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
|
||||||
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
|
||||||
// NON-INFRINGEMENT.
|
|
||||||
// See the Apache 2 License for the specific language governing
|
|
||||||
// permissions and limitations under the License.
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// <copyright file="AssemblyInfo.cs" company="Microsoft">
|
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
[assembly: AssemblyTitle("Microsoft.AspNet.Security.Windows.Tests")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("Microsoft.AspNet.Security.Windows.Tests")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © 2012")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
|
||||||
// to COM components. If you need to access a type in this assembly from
|
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|
||||||
[assembly: Guid("334c99b0-a718-4cda-9ca0-d5a45c3a32b0")]
|
|
||||||
|
|
||||||
// Version information for an assembly consists of the following four values:
|
|
||||||
//
|
|
||||||
// Major Version
|
|
||||||
// Minor Version
|
|
||||||
// Build Number
|
|
||||||
// Revision
|
|
||||||
//
|
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
|
||||||
// by using the '*' as shown below:
|
|
||||||
// [assembly: AssemblyVersion("0.5")]
|
|
||||||
[assembly: AssemblyVersion("0.5")]
|
|
||||||
[assembly: AssemblyFileVersion("0.5.40117.0")]
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.AspNet.Security.Windows" : "",
|
|
||||||
"Microsoft.AspNet.Server.WebListener" : "",
|
|
||||||
"xunit.abstractions": "2.0.0-aspnet-*",
|
|
||||||
"xunit.assert": "2.0.0-aspnet-*",
|
|
||||||
"xunit.core": "2.0.0-aspnet-*",
|
|
||||||
"xunit.execution": "2.0.0-aspnet-*"
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"aspnet50": {
|
|
||||||
"dependencies": {
|
|
||||||
"System.Net.Http": "",
|
|
||||||
"System.Net.Http.WebRequest": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue