Initial port of Secuirty base package from Katana.

This commit is contained in:
Chris Ross 2014-03-14 12:43:45 -07:00
commit 085188996c
54 changed files with 2489 additions and 0 deletions

50
.gitattributes vendored Normal file
View File

@ -0,0 +1,50 @@
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.jpg binary
*.png binary
*.gif binary
*.cs text=auto diff=csharp
*.vb text=auto
*.resx text=auto
*.c text=auto
*.cpp text=auto
*.cxx text=auto
*.h text=auto
*.hxx text=auto
*.py text=auto
*.rb text=auto
*.java text=auto
*.html text=auto
*.htm text=auto
*.css text=auto
*.scss text=auto
*.sass text=auto
*.less text=auto
*.js text=auto
*.lisp text=auto
*.clj text=auto
*.sql text=auto
*.php text=auto
*.lua text=auto
*.m text=auto
*.asm text=auto
*.erl text=auto
*.fs text=auto
*.fsx text=auto
*.hs text=auto
*.csproj text=auto
*.vbproj text=auto
*.fsproj text=auto
*.dbproj text=auto
*.sln text=auto eol=crlf

24
.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
[Oo]bj/
[Bb]in/
TestResults/
.nuget/
_ReSharper.*/
packages/
artifacts/
PublishProfiles/
*.user
*.suo
*.cache
*.docstates
_ReSharper.*
nuget.exe
*net45.csproj
*k10.csproj
*.psess
*.vsp
*.pidb
*.userprefs
*DS_Store
*.ncrunchsolution
*.*sdf
*.ipch

13
NuGet.Config Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="AspNetVNext" value="https://www.myget.org/F/aspnetvnext/api/v2" />
<add key="NuGet.org" value="https://nuget.org/api/v2/" />
</packageSources>
<packageSourceCredentials>
<AspNetVNext>
<add key="Username" value="aspnetreadonly" />
<add key="ClearTextPassword" value="4d8a2d9c-7b80-4162-9978-47e918c9658c" />
</AspNetVNext>
</packageSourceCredentials>
</configuration>

34
Security.sln Normal file
View File

@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30203.2
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Security.net45", "src\Microsoft.AspNet.Security\Microsoft.AspNet.Security.net45.csproj", "{70640501-CCBB-4FD7-8231-329B6A436DE4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4D2B6A51-2F9F-44F5-8131-EA5CAC053652}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Security.k10", "src\Microsoft.AspNet.Security\Microsoft.AspNet.Security.k10.csproj", "{F2391907-4463-4650-AEA4-E1B5733105C4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{70640501-CCBB-4FD7-8231-329B6A436DE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{70640501-CCBB-4FD7-8231-329B6A436DE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70640501-CCBB-4FD7-8231-329B6A436DE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70640501-CCBB-4FD7-8231-329B6A436DE4}.Release|Any CPU.Build.0 = Release|Any CPU
{F2391907-4463-4650-AEA4-E1B5733105C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2391907-4463-4650-AEA4-E1B5733105C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2391907-4463-4650-AEA4-E1B5733105C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2391907-4463-4650-AEA4-E1B5733105C4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{70640501-CCBB-4FD7-8231-329B6A436DE4} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
{F2391907-4463-4650-AEA4-E1B5733105C4} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
EndGlobalSection
EndGlobal

23
build.cmd Normal file
View File

@ -0,0 +1,23 @@
@echo off
cd %~dp0
SETLOCAL
SET CACHED_NUGET=%LocalAppData%\NuGet\NuGet.exe
IF EXIST %CACHED_NUGET% goto copynuget
echo Downloading latest version of NuGet.exe...
IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://www.nuget.org/nuget.exe' -OutFile '%CACHED_NUGET%'"
:copynuget
IF EXIST .nuget\nuget.exe goto restore
md .nuget
copy %CACHED_NUGET% .nuget\nuget.exe > nul
:restore
IF EXIST packages\KoreBuild goto run
.nuget\NuGet.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
.nuget\NuGet.exe install Sake -version 0.2 -o packages -ExcludeVersion
:run
packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %*

3
global.json Normal file
View File

@ -0,0 +1,3 @@
{
"sources": ["src"]
}

7
makefile.shade Normal file
View File

@ -0,0 +1,7 @@
var VERSION='0.1'
var FULL_VERSION='0.1'
var AUTHORS='Microsoft'
use-standard-lifecycle
k-standard-goals

View File

@ -0,0 +1,57 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
/* TODO:
using System;
using Owin;
namespace Microsoft.AspNet.Security
{
/// <summary>
/// Provides extensions methods for app.Property values that are only needed by implementations of authentication middleware.
/// </summary>
public static class AppBuilderSecurityExtensions
{
/// <summary>
/// Returns the previously set AuthenticationType that external sign in middleware should use when the
/// browser navigates back to their return url.
/// </summary>
/// <param name="app">App builder passed to the application startup code</param>
/// <returns></returns>
public static string GetDefaultSignInAsAuthenticationType(this IAppBuilder app)
{
if (app == null)
{
throw new ArgumentNullException("app");
}
object value;
if (app.Properties.TryGetValue(Constants.DefaultSignInAsAuthenticationType, out value))
{
var authenticationType = value as string;
if (!string.IsNullOrEmpty(authenticationType))
{
return authenticationType;
}
}
throw new InvalidOperationException(Resources.Exception_MissingDefaultSignInAsAuthenticationType);
}
/// <summary>
/// Called by middleware to change the name of the AuthenticationType that external middleware should use
/// when the browser navigates back to their return url.
/// </summary>
/// <param name="app">App builder passed to the application startup code</param>
/// <param name="authenticationType">AuthenticationType that external middleware should sign in as.</param>
public static void SetDefaultSignInAsAuthenticationType(this IAppBuilder app, string authenticationType)
{
if (app == null)
{
throw new ArgumentNullException("app");
}
if (authenticationType == null)
{
throw new ArgumentNullException("authenticationType");
}
app.Properties[Constants.DefaultSignInAsAuthenticationType] = authenticationType;
}
}
}
*/

View File

@ -0,0 +1,22 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security
{
/// <summary>
/// Controls the behavior of authentication middleware
/// </summary>
public enum AuthenticationMode
{
/// <summary>
/// In Active mode the authentication middleware will alter the user identity as the request arrives, and
/// will also alter a plain 401 as the response leaves.
/// </summary>
Active,
/// <summary>
/// In Passive mode the authentication middleware will only provide user identity when asked, and will only
/// alter 401 responses where the authentication type named in the extra challenge data.
/// </summary>
Passive
}
}

View File

@ -0,0 +1,49 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security
{
/// <summary>
/// Base Options for all authentication middleware
/// </summary>
public abstract class AuthenticationOptions
{
private string _authenticationType;
/// <summary>
/// Initialize properties of AuthenticationOptions base class
/// </summary>
/// <param name="authenticationType">Assigned to the AuthenticationType property</param>
protected AuthenticationOptions(string authenticationType)
{
Description = new AuthenticationDescription();
AuthenticationType = authenticationType;
AuthenticationMode = AuthenticationMode.Active;
}
/// <summary>
/// The AuthenticationType in the options corresponds to the IIdentity AuthenticationType property. A different
/// value may be assigned in order to use the same authentication middleware type more than once in a pipeline.
/// </summary>
public string AuthenticationType
{
get { return _authenticationType; }
set
{
_authenticationType = value;
Description.AuthenticationType = value;
}
}
/// <summary>
/// If Active the authentication middleware alter the request user coming in and
/// alter 401 Unauthorized responses going out. If Passive the authentication middleware will only provide
/// identity and alter responses when explicitly indicated by the AuthenticationType.
/// </summary>
public AuthenticationMode AuthenticationMode { get; set; }
/// <summary>
/// Additional information about the authentication type which is made available to the application.
/// </summary>
public AuthenticationDescription Description { get; set; }
}
}

View File

@ -0,0 +1,33 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Security.Claims;
namespace Microsoft.AspNet.Security
{
/// <summary>
/// Contains user identity information as well as additional authentication state.
/// </summary>
public class AuthenticationTicket
{
/// <summary>
/// Initializes a new instance of the <see cref="AuthenticationTicket"/> class
/// </summary>
/// <param name="identity"></param>
/// <param name="properties"></param>
public AuthenticationTicket(ClaimsIdentity identity, AuthenticationProperties properties)
{
Identity = identity;
Properties = properties ?? new AuthenticationProperties();
}
/// <summary>
/// Gets the authenticated user identity.
/// </summary>
public ClaimsIdentity Identity { get; private set; }
/// <summary>
/// Additional state values for the authentication session.
/// </summary>
public AuthenticationProperties Properties { get; private set; }
}
}

View File

@ -0,0 +1,88 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
/* TODO:
using System;
using System.Collections.Generic;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace Microsoft.AspNet.Security
{
/// <summary>
/// Provides pinned certificate validation based on the subject key identifier of the certificate.
/// </summary>
public class CertificateSubjectKeyIdentifierValidator : ICertificateValidator
{
private readonly HashSet<string> _validSubjectKeyIdentifiers;
/// <summary>
/// Initializes a new instance of the <see cref="CertificateSubjectKeyIdentifierValidator"/> class.
/// </summary>
/// <param name="validSubjectKeyIdentifiers">A set of subject key identifiers which are valid for an HTTPS request.</param>
public CertificateSubjectKeyIdentifierValidator(IEnumerable<string> validSubjectKeyIdentifiers)
{
if (validSubjectKeyIdentifiers == null)
{
throw new ArgumentNullException("validSubjectKeyIdentifiers");
}
_validSubjectKeyIdentifiers = new HashSet<string>(validSubjectKeyIdentifiers, StringComparer.OrdinalIgnoreCase);
if (_validSubjectKeyIdentifiers.Count == 0)
{
throw new ArgumentOutOfRangeException("validSubjectKeyIdentifiers");
}
}
/// <summary>
/// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication.
/// </summary>
/// <param name="sender">An object that contains state information for this validation.</param>
/// <param name="certificate">The certificate used to authenticate the remote party.</param>
/// <param name="chain">The chain of certificate authorities associated with the remote certificate.</param>
/// <param name="sslPolicyErrors">One or more errors associated with the remote certificate.</param>
/// <returns>A Boolean value that determines whether the specified certificate is accepted for authentication.</returns>
public bool Validate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors != SslPolicyErrors.None)
{
return false;
}
if (chain == null)
{
throw new ArgumentNullException("chain");
}
if (chain.ChainElements.Count < 2)
{
// Self signed.
return false;
}
foreach (var chainElement in chain.ChainElements)
{
string subjectKeyIdentifier = GetSubjectKeyIdentifier(chainElement.Certificate);
if (string.IsNullOrWhiteSpace(subjectKeyIdentifier))
{
continue;
}
if (_validSubjectKeyIdentifiers.Contains(subjectKeyIdentifier))
{
return true;
}
}
return false;
}
private static string GetSubjectKeyIdentifier(X509Certificate2 certificate)
{
const string SubjectKeyIdentifierOid = "2.5.29.14";
var extension = certificate.Extensions[SubjectKeyIdentifierOid] as X509SubjectKeyIdentifierExtension;
return extension == null ? null : extension.SubjectKeyIdentifier;
}
}
}
*/

View File

@ -0,0 +1,135 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
/* TODO:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Win32;
namespace Microsoft.AspNet.Security
{
/// <summary>
/// Implements a cert pinning validator passed on
/// http://datatracker.ietf.org/doc/draft-ietf-websec-key-pinning/?include_text=1
/// </summary>
public class CertificateSubjectPublicKeyInfoValidator : ICertificateValidator
{
private readonly HashSet<string> _validBase64EncodedSubjectPublicKeyInfoHashes;
private readonly SubjectPublicKeyInfoAlgorithm _algorithm;
/// <summary>
/// Initializes a new instance of the <see cref="CertificateSubjectPublicKeyInfoValidator"/> class.
/// </summary>
/// <param name="validBase64EncodedSubjectPublicKeyInfoHashes">A collection of valid base64 encoded hashes of the certificate public key information blob.</param>
/// <param name="algorithm">The algorithm used to generate the hashes.</param>
public CertificateSubjectPublicKeyInfoValidator(IEnumerable<string> validBase64EncodedSubjectPublicKeyInfoHashes, SubjectPublicKeyInfoAlgorithm algorithm)
{
if (validBase64EncodedSubjectPublicKeyInfoHashes == null)
{
throw new ArgumentNullException("validBase64EncodedSubjectPublicKeyInfoHashes");
}
_validBase64EncodedSubjectPublicKeyInfoHashes = new HashSet<string>(validBase64EncodedSubjectPublicKeyInfoHashes);
if (_validBase64EncodedSubjectPublicKeyInfoHashes.Count == 0)
{
throw new ArgumentOutOfRangeException("validBase64EncodedSubjectPublicKeyInfoHashes");
}
if (_algorithm != SubjectPublicKeyInfoAlgorithm.Sha1 && _algorithm != SubjectPublicKeyInfoAlgorithm.Sha256)
{
throw new ArgumentOutOfRangeException("algorithm");
}
_algorithm = algorithm;
}
/// <summary>
/// Validates at least one SPKI hash is known.
/// </summary>
/// <param name="sender">An object that contains state information for this validation.</param>
/// <param name="certificate">The certificate used to authenticate the remote party.</param>
/// <param name="chain">The chain of certificate authorities associated with the remote certificate.</param>
/// <param name="sslPolicyErrors">One or more errors associated with the remote certificate.</param>
/// <returns>A Boolean value that determines whether the specified certificate is accepted for authentication.</returns>
public bool Validate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors != SslPolicyErrors.None)
{
return false;
}
if (chain == null)
{
throw new ArgumentNullException("chain");
}
if (chain.ChainElements.Count < 2)
{
return false;
}
using (HashAlgorithm algorithm = CreateHashAlgorithm())
{
foreach (var chainElement in chain.ChainElements)
{
X509Certificate2 chainedCertificate = chainElement.Certificate;
string base64Spki = Convert.ToBase64String(algorithm.ComputeHash(ExtractSpkiBlob(chainedCertificate)));
if (_validBase64EncodedSubjectPublicKeyInfoHashes.Contains(base64Spki))
{
return true;
}
}
}
return false;
}
private static byte[] ExtractSpkiBlob(X509Certificate2 certificate)
{
// Get a native cert_context from the managed X590Certificate2 instance.
var certContext = (NativeMethods.CERT_CONTEXT)Marshal.PtrToStructure(certificate.Handle, typeof(NativeMethods.CERT_CONTEXT));
// Pull the CERT_INFO structure from the context.
var certInfo = (NativeMethods.CERT_INFO)Marshal.PtrToStructure(certContext.pCertInfo, typeof(NativeMethods.CERT_INFO));
// And finally grab the key information, public key, algorithm and parameters from it.
NativeMethods.CERT_PUBLIC_KEY_INFO publicKeyInfo = certInfo.SubjectPublicKeyInfo;
// Now start encoding to ASN1.
// First see how large the ASN1 representation is going to be.
UInt32 blobSize = 0;
var structType = new IntPtr(NativeMethods.X509_PUBLIC_KEY_INFO);
if (!NativeMethods.CryptEncodeObject(NativeMethods.X509_ASN_ENCODING, structType, ref publicKeyInfo, null, ref blobSize))
{
int error = Marshal.GetLastWin32Error();
throw new Win32Exception(error);
}
// Allocate enough space.
var blob = new byte[blobSize];
// Finally get the ASN1 representation.
if (!NativeMethods.CryptEncodeObject(NativeMethods.X509_ASN_ENCODING, structType, ref publicKeyInfo, blob, ref blobSize))
{
int error = Marshal.GetLastWin32Error();
throw new Win32Exception(error);
}
return blob;
}
[SuppressMessage("Microsoft.Security.Cryptography", "CA5354:SHA1CannotBeUsed", Justification = "Only used to verify cert hashes.")]
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Caller is responsible for disposal.")]
private HashAlgorithm CreateHashAlgorithm()
{
return _algorithm == SubjectPublicKeyInfoAlgorithm.Sha1 ? (HashAlgorithm)new SHA1CryptoServiceProvider() : new SHA256CryptoServiceProvider();
}
}
}
*/

View File

@ -0,0 +1,81 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
/* TODO:
using System;
using System.Collections.Generic;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace Microsoft.AspNet.Security
{
/// <summary>
/// Provides pinned certificate validation based on the certificate thumbprint.
/// </summary>
public class CertificateThumbprintValidator : ICertificateValidator
{
private readonly HashSet<string> _validCertificateThumbprints;
/// <summary>
/// Initializes a new instance of the <see cref="CertificateThumbprintValidator"/> class.
/// </summary>
/// <param name="validThumbprints">A set of thumbprints which are valid for an HTTPS request.</param>
public CertificateThumbprintValidator(IEnumerable<string> validThumbprints)
{
if (validThumbprints == null)
{
throw new ArgumentNullException("validThumbprints");
}
_validCertificateThumbprints = new HashSet<string>(validThumbprints, StringComparer.OrdinalIgnoreCase);
if (_validCertificateThumbprints.Count == 0)
{
throw new ArgumentOutOfRangeException("validThumbprints");
}
}
/// <summary>
/// Validates that the certificate thumbprints in the signing chain match at least one whitelisted thumbprint.
/// </summary>
/// <param name="sender">An object that contains state information for this validation.</param>
/// <param name="certificate">The certificate used to authenticate the remote party.</param>
/// <param name="chain">The chain of certificate authorities associated with the remote certificate.</param>
/// <param name="sslPolicyErrors">One or more errors associated with the remote certificate.</param>
/// <returns>A Boolean value that determines whether the specified certificate is accepted for authentication.</returns>
public bool Validate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors != SslPolicyErrors.None)
{
return false;
}
if (chain == null)
{
throw new ArgumentNullException("chain");
}
if (chain.ChainElements.Count < 2)
{
// Self signed.
return false;
}
foreach (var chainElement in chain.ChainElements)
{
string thumbprintToCheck = chainElement.Certificate.Thumbprint;
if (thumbprintToCheck == null)
{
continue;
}
if (_validCertificateThumbprints.Contains(thumbprintToCheck))
{
return true;
}
}
return false;
}
}
}
*/

View File

@ -0,0 +1,15 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security
{
/// <summary>
/// String constants used only by the Security assembly
/// </summary>
internal static class Constants
{
/// <summary>
/// Used by middleware extension methods to coordinate the default value Options property SignInAsAuthenticationType
/// </summary>
public const string DefaultSignInAsAuthenticationType = "Microsoft.AspNet.Security.Constants.DefaultSignInAsAuthenticationType";
}
}

View File

@ -0,0 +1,19 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
namespace Microsoft.AspNet.Security.DataHandler.Encoder
{
public class Base64TextEncoder : ITextEncoder
{
public string Encode(byte[] data)
{
return Convert.ToBase64String(data);
}
public byte[] Decode(string text)
{
return Convert.FromBase64String(text);
}
}
}

View File

@ -0,0 +1,39 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
namespace Microsoft.AspNet.Security.DataHandler.Encoder
{
public class Base64UrlTextEncoder : ITextEncoder
{
public string Encode(byte[] data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
return Convert.ToBase64String(data).TrimEnd('=').Replace('+', '-').Replace('/', '_');
}
public byte[] Decode(string text)
{
if (text == null)
{
throw new ArgumentNullException("text");
}
return Convert.FromBase64String(Pad(text.Replace('-', '+').Replace('_', '/')));
}
private static string Pad(string text)
{
var padding = 3 - ((text.Length + 3) % 4);
if (padding == 0)
{
return text;
}
return text + new string('=', padding);
}
}
}

View File

@ -0,0 +1,10 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security.DataHandler.Encoder
{
public interface ITextEncoder
{
string Encode(byte[] data);
byte[] Decode(string text);
}
}

View File

@ -0,0 +1,20 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security.DataHandler.Encoder
{
public static class TextEncodings
{
private static readonly ITextEncoder Base64Instance = new Base64TextEncoder();
private static readonly ITextEncoder Base64UrlInstance = new Base64UrlTextEncoder();
public static ITextEncoder Base64
{
get { return Base64Instance; }
}
public static ITextEncoder Base64Url
{
get { return Base64UrlInstance; }
}
}
}

View File

@ -0,0 +1,10 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security
{
public interface ISecureDataFormat<TData>
{
string Protect(TData data);
TData Unprotect(string protectedText);
}
}

View File

@ -0,0 +1,16 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using Microsoft.AspNet.Security.DataHandler.Encoder;
using Microsoft.AspNet.Security.DataHandler.Serializer;
using Microsoft.AspNet.Security.DataProtection;
namespace Microsoft.AspNet.Security.DataHandler
{
public class PropertiesDataFormat : SecureDataFormat<AuthenticationProperties>
{
public PropertiesDataFormat(IDataProtector protector)
: base(DataSerializers.Properties, protector, TextEncodings.Base64Url)
{
}
}
}

View File

@ -0,0 +1,63 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNet.Security.DataHandler.Encoder;
using Microsoft.AspNet.Security.DataHandler.Serializer;
using Microsoft.AspNet.Security.DataProtection;
namespace Microsoft.AspNet.Security.DataHandler
{
public class SecureDataFormat<TData> : ISecureDataFormat<TData>
{
private readonly IDataSerializer<TData> _serializer;
private readonly IDataProtector _protector;
private readonly ITextEncoder _encoder;
public SecureDataFormat(IDataSerializer<TData> serializer, IDataProtector protector, ITextEncoder encoder)
{
_serializer = serializer;
_protector = protector;
_encoder = encoder;
}
public string Protect(TData data)
{
byte[] userData = _serializer.Serialize(data);
byte[] protectedData = _protector.Protect(userData);
string protectedText = _encoder.Encode(protectedData);
return protectedText;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exception will be traced")]
public TData Unprotect(string protectedText)
{
try
{
if (protectedText == null)
{
return default(TData);
}
byte[] protectedData = _encoder.Decode(protectedText);
if (protectedData == null)
{
return default(TData);
}
byte[] userData = _protector.Unprotect(protectedData);
if (userData == null)
{
return default(TData);
}
TData model = _serializer.Deserialize(userData);
return model;
}
catch
{
// TODO trace exception, but do not leak other information
return default(TData);
}
}
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security.DataHandler.Serializer
{
public static class DataSerializers
{
static DataSerializers()
{
Properties = new PropertiesSerializer();
Ticket = new TicketSerializer();
}
public static IDataSerializer<AuthenticationProperties> Properties { get; set; }
public static IDataSerializer<AuthenticationTicket> Ticket { get; set; }
}
}

View File

@ -0,0 +1,10 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security.DataHandler.Serializer
{
public interface IDataSerializer<TModel>
{
byte[] Serialize(TModel model);
TModel Deserialize(byte[] data);
}
}

View File

@ -0,0 +1,82 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
namespace Microsoft.AspNet.Security.DataHandler.Serializer
{
public class PropertiesSerializer : IDataSerializer<AuthenticationProperties>
{
private const int FormatVersion = 1;
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Dispose is idempotent")]
public byte[] Serialize(AuthenticationProperties model)
{
using (var memory = new MemoryStream())
{
using (var writer = new BinaryWriter(memory))
{
Write(writer, model);
writer.Flush();
return memory.ToArray();
}
}
}
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Dispose is idempotent")]
public AuthenticationProperties Deserialize(byte[] data)
{
using (var memory = new MemoryStream(data))
{
using (var reader = new BinaryReader(memory))
{
return Read(reader);
}
}
}
public static void Write(BinaryWriter writer, AuthenticationProperties properties)
{
if (writer == null)
{
throw new ArgumentNullException("writer");
}
if (properties == null)
{
throw new ArgumentNullException("properties");
}
writer.Write(FormatVersion);
writer.Write(properties.Dictionary.Count);
foreach (var kv in properties.Dictionary)
{
writer.Write(kv.Key);
writer.Write(kv.Value);
}
}
public static AuthenticationProperties Read(BinaryReader reader)
{
if (reader == null)
{
throw new ArgumentNullException("reader");
}
if (reader.ReadInt32() != FormatVersion)
{
return null;
}
int count = reader.ReadInt32();
var extra = new Dictionary<string, string>(count);
for (int index = 0; index != count; ++index)
{
string key = reader.ReadString();
string value = reader.ReadString();
extra.Add(key, value);
}
return new AuthenticationProperties(extra);
}
}
}

View File

@ -0,0 +1,136 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Security.Claims;
namespace Microsoft.AspNet.Security.DataHandler.Serializer
{
public class TicketSerializer : IDataSerializer<AuthenticationTicket>
{
private const int FormatVersion = 2;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Dispose is idempotent")]
public virtual byte[] Serialize(AuthenticationTicket model)
{
using (var memory = new MemoryStream())
{
using (var compression = new GZipStream(memory, CompressionLevel.Optimal))
{
using (var writer = new BinaryWriter(compression))
{
Write(writer, model);
}
}
return memory.ToArray();
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Dispose is idempotent")]
public virtual AuthenticationTicket Deserialize(byte[] data)
{
using (var memory = new MemoryStream(data))
{
using (var compression = new GZipStream(memory, CompressionMode.Decompress))
{
using (var reader = new BinaryReader(compression))
{
return Read(reader);
}
}
}
}
public static void Write(BinaryWriter writer, AuthenticationTicket model)
{
if (writer == null)
{
throw new ArgumentNullException("writer");
}
if (model == null)
{
throw new ArgumentNullException("model");
}
writer.Write(FormatVersion);
ClaimsIdentity identity = model.Identity;
writer.Write(identity.AuthenticationType);
WriteWithDefault(writer, identity.NameClaimType, DefaultValues.NameClaimType);
WriteWithDefault(writer, identity.RoleClaimType, DefaultValues.RoleClaimType);
writer.Write(identity.Claims.Count());
foreach (var claim in identity.Claims)
{
WriteWithDefault(writer, claim.Type, identity.NameClaimType);
writer.Write(claim.Value);
WriteWithDefault(writer, claim.ValueType, DefaultValues.StringValueType);
WriteWithDefault(writer, claim.Issuer, DefaultValues.LocalAuthority);
WriteWithDefault(writer, claim.OriginalIssuer, claim.Issuer);
}
PropertiesSerializer.Write(writer, model.Properties);
}
public static AuthenticationTicket Read(BinaryReader reader)
{
if (reader == null)
{
throw new ArgumentNullException("reader");
}
if (reader.ReadInt32() != FormatVersion)
{
return null;
}
string authenticationType = reader.ReadString();
string nameClaimType = ReadWithDefault(reader, DefaultValues.NameClaimType);
string roleClaimType = ReadWithDefault(reader, DefaultValues.RoleClaimType);
int count = reader.ReadInt32();
var claims = new Claim[count];
for (int index = 0; index != count; ++index)
{
string type = ReadWithDefault(reader, nameClaimType);
string value = reader.ReadString();
string valueType = ReadWithDefault(reader, DefaultValues.StringValueType);
string issuer = ReadWithDefault(reader, DefaultValues.LocalAuthority);
string originalIssuer = ReadWithDefault(reader, issuer);
claims[index] = new Claim(type, value, valueType, issuer, originalIssuer);
}
var identity = new ClaimsIdentity(claims, authenticationType, nameClaimType, roleClaimType);
AuthenticationProperties properties = PropertiesSerializer.Read(reader);
return new AuthenticationTicket(identity, properties);
}
private static void WriteWithDefault(BinaryWriter writer, string value, string defaultValue)
{
if (string.Equals(value, defaultValue, StringComparison.Ordinal))
{
writer.Write(DefaultValues.DefaultStringPlaceholder);
}
else
{
writer.Write(value);
}
}
private static string ReadWithDefault(BinaryReader reader, string defaultValue)
{
string value = reader.ReadString();
if (string.Equals(value, DefaultValues.DefaultStringPlaceholder, StringComparison.Ordinal))
{
return defaultValue;
}
return value;
}
private static class DefaultValues
{
public const string DefaultStringPlaceholder = "\0";
public const string NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name";
public const string RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
public const string LocalAuthority = "LOCAL AUTHORITY";
public const string StringValueType = "http://www.w3.org/2001/XMLSchema#string";
}
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using Microsoft.AspNet.Security.DataHandler.Encoder;
using Microsoft.AspNet.Security.DataHandler.Serializer;
using Microsoft.AspNet.Security.DataProtection;
namespace Microsoft.AspNet.Security.DataHandler
{
public class TicketDataFormat : SecureDataFormat<AuthenticationTicket>
{
public TicketDataFormat(IDataProtector protector) : base(DataSerializers.Ticket, protector, TextEncodings.Base64Url)
{
}
}
}

View File

@ -0,0 +1,28 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
/* TODO:
using System;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace Microsoft.AspNet.Security
{
/// <summary>
/// Interface for providing pinned certificate validation, which checks HTTPS
/// communication against a known good list of certificates to protect against
/// compromised or rogue CAs issuing certificates for hosts without the
/// knowledge of the host owner.
/// </summary>
public interface ICertificateValidator
{
/// <summary>
/// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication.
/// </summary>
/// <param name="sender">An object that contains state information for this validation.</param>
/// <param name="certificate">The certificate used to authenticate the remote party.</param>
/// <param name="chain">The chain of certificate authorities associated with the remote certificate.</param>
/// <param name="sslPolicyErrors">One or more errors associated with the remote certificate.</param>
/// <returns>A Boolean value that determines whether the specified certificate is accepted for authentication.</returns>
bool Validate(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors);
}
}
*/

View File

@ -0,0 +1,252 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Logging;
using Microsoft.AspNet.Security.DataHandler.Encoder;
using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Security.Infrastructure
{
/// <summary>
/// Base class for the per-request work performed by most authentication middleware.
/// </summary>
public abstract class AuthenticationHandler
{
private static readonly RNGCryptoServiceProvider Random = new RNGCryptoServiceProvider();
private object _registration;
private Task<AuthenticationTicket> _authenticate;
private bool _authenticateInitialized;
private object _authenticateSyncLock;
private Task _applyResponse;
private bool _applyResponseInitialized;
private object _applyResponseSyncLock;
private AuthenticationOptions _baseOptions;
protected HttpContext Context { get; private set; }
protected HttpRequest Request
{
get { return Context.Request; }
}
protected HttpResponse Response
{
get { return Context.Response; }
}
protected PathString RequestPathBase { get; private set; }
protected SecurityHelper Helper { get; private set; }
internal AuthenticationOptions BaseOptions
{
get { return _baseOptions; }
}
protected async Task BaseInitializeAsync(AuthenticationOptions options, HttpContext context)
{
_baseOptions = options;
Context = context;
Helper = new SecurityHelper(context);
RequestPathBase = Request.PathBase;
_registration = Request.RegisterAuthenticationHandler(this);
Response.OnSendingHeaders(OnSendingHeaderCallback, this);
await InitializeCoreAsync();
if (BaseOptions.AuthenticationMode == AuthenticationMode.Active)
{
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket != null && ticket.Identity != null)
{
Helper.AddUserIdentity(ticket.Identity);
}
}
}
private static void OnSendingHeaderCallback(object state)
{
AuthenticationHandler handler = (AuthenticationHandler)state;
handler.ApplyResponseAsync().Wait();
}
protected virtual Task InitializeCoreAsync()
{
return Task.FromResult<object>(null);
}
/// <summary>
/// Called once per request after Initialize and Invoke.
/// </summary>
/// <returns>async completion</returns>
internal async Task TeardownAsync()
{
await ApplyResponseAsync();
await TeardownCoreAsync();
Request.UnregisterAuthenticationHandler(_registration);
}
protected virtual Task TeardownCoreAsync()
{
return Task.FromResult<object>(null);
}
/// <summary>
/// Called once by common code after initialization. If an authentication middleware responds directly to
/// specifically known paths it must override this virtual, compare the request path to it's known paths,
/// provide any response information as appropriate, and true to stop further processing.
/// </summary>
/// <returns>Returning false will cause the common code to call the next middleware in line. Returning true will
/// cause the common code to begin the async completion journey without calling the rest of the middleware
/// pipeline.</returns>
public virtual Task<bool> InvokeAsync()
{
return Task.FromResult<bool>(false);
}
/// <summary>
/// Causes the authentication logic in AuthenticateCore to be performed for the current request
/// at most once and returns the results. Calling Authenticate more than once will always return
/// the original value.
///
/// This method should always be called instead of calling AuthenticateCore directly.
/// </summary>
/// <returns>The ticket data provided by the authentication logic</returns>
public Task<AuthenticationTicket> AuthenticateAsync()
{
return LazyInitializer.EnsureInitialized(
ref _authenticate,
ref _authenticateInitialized,
ref _authenticateSyncLock,
AuthenticateCoreAsync);
}
/// <summary>
/// The core authentication logic which must be provided by the handler. Will be invoked at most
/// once per request. Do not call directly, call the wrapping Authenticate method instead.
/// </summary>
/// <returns>The ticket data provided by the authentication logic</returns>
protected abstract Task<AuthenticationTicket> AuthenticateCoreAsync();
/// <summary>
/// Causes the ApplyResponseCore to be invoked at most once per request. This method will be
/// invoked either earlier, when the response headers are sent as a result of a response write or flush,
/// or later, as the last step when the original async call to the middleware is returning.
/// </summary>
/// <returns></returns>
private Task ApplyResponseAsync()
{
return LazyInitializer.EnsureInitialized(
ref _applyResponse,
ref _applyResponseInitialized,
ref _applyResponseSyncLock,
ApplyResponseCoreAsync);
}
/// <summary>
/// Core method that may be overridden by handler. The default behavior is to call two common response
/// activities, one that deals with sign-in/sign-out concerns, and a second to deal with 401 challenges.
/// </summary>
/// <returns></returns>
protected virtual async Task ApplyResponseCoreAsync()
{
await ApplyResponseGrantAsync();
await ApplyResponseChallengeAsync();
}
/// <summary>
/// Override this method to dela with sign-in/sign-out concerns, if an authentication scheme in question
/// deals with grant/revoke as part of it's request flow. (like setting/deleting cookies)
/// </summary>
/// <returns></returns>
protected virtual Task ApplyResponseGrantAsync()
{
return Task.FromResult<object>(null);
}
/// <summary>
/// Override this method to dela with 401 challenge concerns, if an authentication scheme in question
/// deals an authentication interaction as part of it's request flow. (like adding a response header, or
/// changing the 401 result to 302 of a login page or external sign-in location.)
/// </summary>
/// <returns></returns>
protected virtual Task ApplyResponseChallengeAsync()
{
return Task.FromResult<object>(null);
}
protected void GenerateCorrelationId(AuthenticationProperties properties)
{
if (properties == null)
{
throw new ArgumentNullException("properties");
}
string correlationKey = Constants.CorrelationPrefix + BaseOptions.AuthenticationType;
var nonceBytes = new byte[32];
Random.GetBytes(nonceBytes);
string correlationId = TextEncodings.Base64Url.Encode(nonceBytes);
var cookieOptions = new CookieOptions
{
HttpOnly = true,
Secure = Request.IsSecure
};
properties.Dictionary[correlationKey] = correlationId;
Response.Cookies.Append(correlationKey, correlationId, cookieOptions);
}
[SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters",
MessageId = "Microsoft.Owin.Logging.LoggerExtensions.WriteWarning(Microsoft.Owin.Logging.ILogger,System.String,System.String[])",
Justification = "Logging is not Localized")]
protected bool ValidateCorrelationId(AuthenticationProperties properties, ILogger logger)
{
if (properties == null)
{
throw new ArgumentNullException("properties");
}
string correlationKey = Constants.CorrelationPrefix + BaseOptions.AuthenticationType;
string correlationCookie = Request.Cookies[correlationKey];
if (string.IsNullOrWhiteSpace(correlationCookie))
{
logger.WriteWarning("{0} cookie not found.", correlationKey);
return false;
}
Response.Cookies.Delete(correlationKey);
string correlationExtra;
if (!properties.Dictionary.TryGetValue(
correlationKey,
out correlationExtra))
{
logger.WriteWarning("{0} state property not found.", correlationKey);
return false;
}
properties.Dictionary.Remove(correlationKey);
if (!string.Equals(correlationCookie, correlationExtra, StringComparison.Ordinal))
{
logger.WriteWarning("{0} correlation cookie and state property mismatch.", correlationKey);
return false;
}
return true;
}
}
}

View File

@ -0,0 +1,28 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Security.Infrastructure
{
/// <summary>
/// Base class for the per-request work performed by most authentication middleware.
/// </summary>
/// <typeparam name="TOptions">Specifies which type for of AuthenticationOptions property</typeparam>
public abstract class AuthenticationHandler<TOptions> : AuthenticationHandler where TOptions : AuthenticationOptions
{
protected TOptions Options { get; private set; }
/// <summary>
/// Initialize is called once per request to contextualize this instance with appropriate state.
/// </summary>
/// <param name="options">The original options passed by the application control behavior</param>
/// <param name="context">The utility object to observe the current request and response</param>
/// <returns>async completion</returns>
internal Task Initialize(TOptions options, HttpContext context)
{
Options = options;
return BaseInitializeAsync(options, context);
}
}
}

View File

@ -0,0 +1,39 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Security.Infrastructure
{
public abstract class AuthenticationMiddleware<TOptions> where TOptions : AuthenticationOptions
{
private readonly RequestDelegate _next;
protected AuthenticationMiddleware(RequestDelegate next, TOptions options)
{
if (options == null)
{
throw new ArgumentNullException("options");
}
Options = options;
_next = next;
}
public TOptions Options { get; set; }
public override async Task Invoke(HttpContext context)
{
AuthenticationHandler<TOptions> handler = CreateHandler();
await handler.Initialize(Options, context);
if (!await handler.InvokeAsync())
{
await _next(context);
}
await handler.TeardownAsync();
}
protected abstract AuthenticationHandler<TOptions> CreateHandler();
}
}

View File

@ -0,0 +1,49 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.Security.Provider;
namespace Microsoft.AspNet.Security.Infrastructure
{
public class AuthenticationTokenCreateContext : BaseContext
{
private readonly ISecureDataFormat<AuthenticationTicket> _secureDataFormat;
public AuthenticationTokenCreateContext(
HttpContext context,
ISecureDataFormat<AuthenticationTicket> secureDataFormat,
AuthenticationTicket ticket)
: base(context)
{
if (secureDataFormat == null)
{
throw new ArgumentNullException("secureDataFormat");
}
if (ticket == null)
{
throw new ArgumentNullException("ticket");
}
_secureDataFormat = secureDataFormat;
Ticket = ticket;
}
public string Token { get; protected set; }
public AuthenticationTicket Ticket { get; protected set; }
public string SerializeTicket()
{
return _secureDataFormat.Protect(Ticket);
}
public void SetToken(string tokenValue)
{
if (tokenValue == null)
{
throw new ArgumentNullException("tokenValue");
}
Token = tokenValue;
}
}
}

View File

@ -0,0 +1,72 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Security.Infrastructure
{
public class AuthenticationTokenProvider : IAuthenticationTokenProvider
{
public Action<AuthenticationTokenCreateContext> OnCreate { get; set; }
public Func<AuthenticationTokenCreateContext, Task> OnCreateAsync { get; set; }
public Action<AuthenticationTokenReceiveContext> OnReceive { get; set; }
public Func<AuthenticationTokenReceiveContext, Task> OnReceiveAsync { get; set; }
public virtual void Create(AuthenticationTokenCreateContext context)
{
if (OnCreateAsync != null && OnCreate == null)
{
throw new InvalidOperationException(Resources.Exception_AuthenticationTokenDoesNotProvideSyncMethods);
}
if (OnCreate != null)
{
OnCreate.Invoke(context);
}
}
public virtual async Task CreateAsync(AuthenticationTokenCreateContext context)
{
if (OnCreateAsync != null && OnCreate == null)
{
throw new InvalidOperationException(Resources.Exception_AuthenticationTokenDoesNotProvideSyncMethods);
}
if (OnCreateAsync != null)
{
await OnCreateAsync.Invoke(context);
}
else
{
Create(context);
}
}
public virtual void Receive(AuthenticationTokenReceiveContext context)
{
if (OnReceiveAsync != null && OnReceive == null)
{
throw new InvalidOperationException(Resources.Exception_AuthenticationTokenDoesNotProvideSyncMethods);
}
if (OnReceive != null)
{
OnReceive.Invoke(context);
}
}
public virtual async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
if (OnReceiveAsync != null && OnReceive == null)
{
throw new InvalidOperationException(Resources.Exception_AuthenticationTokenDoesNotProvideSyncMethods);
}
if (OnReceiveAsync != null)
{
await OnReceiveAsync.Invoke(context);
}
else
{
Receive(context);
}
}
}
}

View File

@ -0,0 +1,48 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.Security.Provider;
namespace Microsoft.AspNet.Security.Infrastructure
{
public class AuthenticationTokenReceiveContext : BaseContext
{
private readonly ISecureDataFormat<AuthenticationTicket> _secureDataFormat;
public AuthenticationTokenReceiveContext(
HttpContext context,
ISecureDataFormat<AuthenticationTicket> secureDataFormat,
string token) : base(context)
{
if (secureDataFormat == null)
{
throw new ArgumentNullException("secureDataFormat");
}
if (token == null)
{
throw new ArgumentNullException("token");
}
_secureDataFormat = secureDataFormat;
Token = token;
}
public string Token { get; protected set; }
public AuthenticationTicket Ticket { get; protected set; }
public void DeserializeTicket(string protectedData)
{
Ticket = _secureDataFormat.Unprotect(protectedData);
}
public void SetTicket(AuthenticationTicket ticket)
{
if (ticket == null)
{
throw new ArgumentNullException("ticket");
}
Ticket = ticket;
}
}
}

View File

@ -0,0 +1,10 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security.Infrastructure
{
internal static class Constants
{
public static string SecurityAuthenticate = "security.Authenticate";
internal const string CorrelationPrefix = ".AspNet.Correlation.";
}
}

View File

@ -0,0 +1,14 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Threading.Tasks;
namespace Microsoft.AspNet.Security.Infrastructure
{
public interface IAuthenticationTokenProvider
{
void Create(AuthenticationTokenCreateContext context);
Task CreateAsync(AuthenticationTokenCreateContext context);
void Receive(AuthenticationTokenReceiveContext context);
Task ReceiveAsync(AuthenticationTokenReceiveContext context);
}
}

View File

@ -0,0 +1,72 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Security.Infrastructure
{
// TODO: comment function documentations
using AuthenticateCallback = Action<IIdentity, IDictionary<string, string>, IDictionary<string, object>, object>;
using AuthenticateDelegate = Func<string[], Action<IIdentity, IDictionary<string, string>, IDictionary<string, object>, object>, object, Task>;
internal static class OwinRequestExtensions
{
public static object RegisterAuthenticationHandler(this HttpRequest request, AuthenticationHandler handler)
{
var chained = request.Get<AuthenticateDelegate>(Constants.SecurityAuthenticate);
var hook = new Hook(handler, chained);
request.Set<AuthenticateDelegate>(Constants.SecurityAuthenticate, hook.AuthenticateAsync);
return hook;
}
public static void UnregisterAuthenticationHandler(this HttpRequest request, object registration)
{
var hook = registration as Hook;
if (hook == null)
{
throw new InvalidOperationException(Resources.Exception_UnhookAuthenticationStateType);
}
request.Set(Constants.SecurityAuthenticate, hook.Chained);
}
private class Hook
{
private readonly AuthenticationHandler _handler;
public Hook(AuthenticationHandler handler, AuthenticateDelegate chained)
{
_handler = handler;
Chained = chained;
}
public AuthenticateDelegate Chained { get; private set; }
public async Task AuthenticateAsync(
string[] authenticationTypes,
AuthenticateCallback callback,
object state)
{
if (authenticationTypes == null)
{
callback(null, null, _handler.BaseOptions.Description.Properties, state);
}
else if (authenticationTypes.Contains(_handler.BaseOptions.AuthenticationType, StringComparer.Ordinal))
{
AuthenticationTicket ticket = await _handler.AuthenticateAsync();
if (ticket != null && ticket.Identity != null)
{
callback(ticket.Identity, ticket.Properties.Dictionary, _handler.BaseOptions.Description.Properties, state);
}
}
if (Chained != null)
{
await Chained(authenticationTypes, callback, state);
}
}
}
}
}

View File

@ -0,0 +1,188 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Security.Claims;
using System.Security.Principal;
using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Security.Infrastructure
{
/// <summary>
/// Helper code used when implementing authentication middleware
/// </summary>
public struct SecurityHelper
{
private readonly HttpContext _context;
/// <summary>
/// Helper code used when implementing authentication middleware
/// </summary>
/// <param name="context"></param>
public SecurityHelper(HttpContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
_context = context;
}
/// <summary>
/// Add an additional ClaimsIdentity to the ClaimsPrincipal in the "server.User" environment key
/// </summary>
/// <param name="identity"></param>
public void AddUserIdentity(IIdentity identity)
{
if (identity == null)
{
throw new ArgumentNullException("identity");
}
var newClaimsPrincipal = new ClaimsPrincipal(identity);
IPrincipal existingPrincipal = _context.Request.User;
if (existingPrincipal != null)
{
var existingClaimsPrincipal = existingPrincipal as ClaimsPrincipal;
if (existingClaimsPrincipal == null)
{
IIdentity existingIdentity = existingPrincipal.Identity;
if (existingIdentity.IsAuthenticated)
{
newClaimsPrincipal.AddIdentity(existingIdentity as ClaimsIdentity ?? new ClaimsIdentity(existingIdentity));
}
}
else
{
foreach (var existingClaimsIdentity in existingClaimsPrincipal.Identities)
{
if (existingClaimsIdentity.IsAuthenticated)
{
newClaimsPrincipal.AddIdentity(existingClaimsIdentity);
}
}
}
}
_context.Request.User = newClaimsPrincipal;
}
/// <summary>
/// Find response challenge details for a specific authentication middleware
/// </summary>
/// <param name="authenticationType">The authentication type to look for</param>
/// <param name="authenticationMode">The authentication mode the middleware is running under</param>
/// <returns>The information instructing the middleware how it should behave</returns>
public AuthenticationResponseChallenge LookupChallenge(string authenticationType, AuthenticationMode authenticationMode)
{
if (authenticationType == null)
{
throw new ArgumentNullException("authenticationType");
}
AuthenticationResponseChallenge challenge = _context.Authentication.AuthenticationResponseChallenge;
bool challengeHasAuthenticationTypes = challenge != null && challenge.AuthenticationTypes != null && challenge.AuthenticationTypes.Length != 0;
if (challengeHasAuthenticationTypes == false)
{
return authenticationMode == AuthenticationMode.Active ? (challenge ?? new AuthenticationResponseChallenge(null, null)) : null;
}
foreach (var challengeType in challenge.AuthenticationTypes)
{
if (string.Equals(challengeType, authenticationType, StringComparison.Ordinal))
{
return challenge;
}
}
return null;
}
/// <summary>
/// Find response sign-in details for a specific authentication middleware
/// </summary>
/// <param name="authenticationType">The authentication type to look for</param>
/// <returns>The information instructing the middleware how it should behave</returns>
public AuthenticationResponseGrant LookupSignIn(string authenticationType)
{
if (authenticationType == null)
{
throw new ArgumentNullException("authenticationType");
}
AuthenticationResponseGrant grant = _context.Authentication.AuthenticationResponseGrant;
if (grant == null)
{
return null;
}
foreach (var claimsIdentity in grant.Principal.Identities)
{
if (string.Equals(authenticationType, claimsIdentity.AuthenticationType, StringComparison.Ordinal))
{
return new AuthenticationResponseGrant(claimsIdentity, grant.Properties ?? new AuthenticationProperties());
}
}
return null;
}
/// <summary>
/// Find response sign-out details for a specific authentication middleware
/// </summary>
/// <param name="authenticationType">The authentication type to look for</param>
/// <param name="authenticationMode">The authentication mode the middleware is running under</param>
/// <returns>The information instructing the middleware how it should behave</returns>
public AuthenticationResponseRevoke LookupSignOut(string authenticationType, AuthenticationMode authenticationMode)
{
if (authenticationType == null)
{
throw new ArgumentNullException("authenticationType");
}
AuthenticationResponseRevoke revoke = _context.Authentication.AuthenticationResponseRevoke;
if (revoke == null)
{
return null;
}
if (revoke.AuthenticationTypes == null || revoke.AuthenticationTypes.Length == 0)
{
return authenticationMode == AuthenticationMode.Active ? revoke : null;
}
for (int index = 0; index != revoke.AuthenticationTypes.Length; ++index)
{
if (String.Equals(authenticationType, revoke.AuthenticationTypes[index], StringComparison.Ordinal))
{
return revoke;
}
}
return null;
}
#region Value-type equality
public bool Equals(SecurityHelper other)
{
return Equals(_context, other._context);
}
public override bool Equals(object obj)
{
return obj is SecurityHelper && Equals((SecurityHelper)obj);
}
public override int GetHashCode()
{
return (_context != null ? _context.GetHashCode() : 0);
}
public static bool operator ==(SecurityHelper left, SecurityHelper right)
{
return left.Equals(right);
}
public static bool operator !=(SecurityHelper left, SecurityHelper right)
{
return !left.Equals(right);
}
#endregion
}
}

View File

@ -0,0 +1,18 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
namespace Microsoft.AspNet.Security.Notifications
{
public class AuthenticationFailedNotification<TMessage>
{
public AuthenticationFailedNotification()
{
}
public bool Cancel { get; set; }
public Exception Exception { get; set; }
public TMessage ProtocolMessage { get; set; }
public int StatusCode { get; set; }
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security.Notifications
{
public class MessageReceivedNotification<TMessage>
{
public MessageReceivedNotification()
{
}
public bool Cancel { get; set; }
public TMessage ProtocolMessage { get; set; }
public int StatusCode { get; set; }
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security.Notifications
{
public class RedirectFromIdentityProviderNotification
{
public AuthenticationTicket AuthenticationTicket { get; set; }
public string SignInAsAuthenticationType { get; set; }
public bool Cancel { get; set; }
public int StatusCode { get; set; }
public bool IsRequestCompleted { get; set; }
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security.Notifications
{
public class RedirectToIdentityProviderNotification<TMessage>
{
public RedirectToIdentityProviderNotification()
{
}
public bool Cancel { get; set; }
public TMessage ProtocolMessage { get; set; }
public int StatusCode { get; set; }
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security.Notifications
{
public class SecurityTokenReceivedNotification
{
public SecurityTokenReceivedNotification()
{
}
public bool Cancel { get; set; }
public string SecurityToken { get; set; }
public int StatusCode { get; set; }
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security.Notifications
{
public class SecurityTokenValidatedNotification
{
public SecurityTokenValidatedNotification()
{
}
public AuthenticationTicket AuthenticationTicket { get; set; }
public bool Cancel { get; set; }
public int StatusCode { get; set; }
}
}

View File

@ -0,0 +1,26 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Security.Provider
{
public abstract class BaseContext
{
protected BaseContext(HttpContext context)
{
HttpContext = context;
}
public HttpContext HttpContext { get; private set; }
public HttpRequest Request
{
get { return HttpContext.Request; }
}
public HttpResponse Response
{
get { return HttpContext.Response; }
}
}
}

View File

@ -0,0 +1,32 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Security.Provider
{
/// <summary>
/// Base class used for certain event contexts
/// </summary>
public abstract class BaseContext<TOptions>
{
protected BaseContext(HttpContext context, TOptions options)
{
HttpContext = context;
Options = options;
}
public HttpContext HttpContext { get; private set; }
public TOptions Options { get; private set; }
public HttpRequest Request
{
get { return HttpContext.Request; }
}
public HttpResponse Response
{
get { return HttpContext.Response; }
}
}
}

View File

@ -0,0 +1,21 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Security.Provider
{
public abstract class EndpointContext : BaseContext
{
protected EndpointContext(HttpContext context)
: base(context)
{
}
public bool IsRequestCompleted { get; private set; }
public void RequestCompleted()
{
IsRequestCompleted = true;
}
}
}

View File

@ -0,0 +1,34 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Security.Provider
{
/// <summary>
/// Base class used for certain event contexts
/// </summary>
public abstract class EndpointContext<TOptions> : BaseContext<TOptions>
{
/// <summary>
/// Creates an instance of this context
/// </summary>
protected EndpointContext(HttpContext context, TOptions options)
: base(context, options)
{
}
/// <summary>
/// True if the request should not be processed further by other components.
/// </summary>
public bool IsRequestCompleted { get; private set; }
/// <summary>
/// Prevents the request from being processed further by other components.
/// IsRequestCompleted becomes true after calling.
/// </summary>
public void RequestCompleted()
{
IsRequestCompleted = true;
}
}
}

View File

@ -0,0 +1,31 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
using System.Security.Claims;
using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Security.Provider
{
public abstract class ReturnEndpointContext : EndpointContext
{
protected ReturnEndpointContext(
HttpContext context,
AuthenticationTicket ticket)
: base(context)
{
if (ticket != null)
{
Identity = ticket.Identity;
Properties = ticket.Properties;
}
}
public ClaimsIdentity Identity { get; set; }
public AuthenticationProperties Properties { get; set; }
public string SignInAsAuthenticationType { get; set; }
[SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "By design")]
public string RedirectUri { get; set; }
}
}

View File

@ -0,0 +1,99 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34003
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Microsoft.AspNet.Security {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.AspNet.Security.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to The AuthenticationTokenProvider&apos;s required synchronous events have not been registered..
/// </summary>
internal static string Exception_AuthenticationTokenDoesNotProvideSyncMethods {
get {
return ResourceManager.GetString("Exception_AuthenticationTokenDoesNotProvideSyncMethods", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The default data protection provider may only be used when the IAppBuilder.Properties contains an appropriate &apos;host.AppName&apos; key..
/// </summary>
internal static string Exception_DefaultDpapiRequiresAppNameKey {
get {
return ResourceManager.GetString("Exception_DefaultDpapiRequiresAppNameKey", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A default value for SignInAsAuthenticationType was not found in IAppBuilder Properties. This can happen if your authentication middleware are added in the wrong order, or if one is missing..
/// </summary>
internal static string Exception_MissingDefaultSignInAsAuthenticationType {
get {
return ResourceManager.GetString("Exception_MissingDefaultSignInAsAuthenticationType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The state passed to UnhookAuthentication may only be the return value from HookAuthentication..
/// </summary>
internal static string Exception_UnhookAuthenticationStateType {
get {
return ResourceManager.GetString("Exception_UnhookAuthenticationStateType", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Exception_DefaultDpapiRequiresAppNameKey" xml:space="preserve">
<value>The default data protection provider may only be used when the IAppBuilder.Properties contains an appropriate 'host.AppName' key.</value>
</data>
<data name="Exception_UnhookAuthenticationStateType" xml:space="preserve">
<value>The state passed to UnhookAuthentication may only be the return value from HookAuthentication.</value>
</data>
<data name="Exception_MissingDefaultSignInAsAuthenticationType" xml:space="preserve">
<value>A default value for SignInAsAuthenticationType was not found in IAppBuilder Properties. This can happen if your authentication middleware are added in the wrong order, or if one is missing.</value>
</data>
<data name="Exception_AuthenticationTokenDoesNotProvideSyncMethods" xml:space="preserve">
<value>The AuthenticationTokenProvider's required synchronous events have not been registered.</value>
</data>
</root>

View File

@ -0,0 +1,13 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security
{
/// <summary>
/// The algorithm used to generate the subject public key information blob hashes.
/// </summary>
public enum SubjectPublicKeyInfoAlgorithm
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha", Justification = "It is correct.")] Sha1,
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha", Justification = "It is correct.")] Sha256
}
}

View File

@ -0,0 +1,95 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace Microsoft.Win32
{
// TODO: ? [Localizable(false)]
internal static class NativeMethods
{
// ReSharper disable InconsistentNaming
public const int X509_ASN_ENCODING = 0x00000001;
public const int X509_PUBLIC_KEY_INFO = 8;
// ReSharper restore InconsistentNaming
/// <summary>
/// Encodes a structure of the type indicated by the value of the lpszStructType parameter.
/// </summary>
/// <param name="dwCertEncodingType">Type of encoding used.</param>
/// <param name="lpszStructType">The high-order word is zero, the low-order word specifies the integer identifier for the type of the specified structure so
/// we can use the constants in http://msdn.microsoft.com/en-us/library/windows/desktop/aa378145%28v=vs.85%29.aspx</param>
/// <param name="pvStructInfo">A pointer to the structure to be encoded.</param>
/// <param name="pbEncoded">A pointer to a buffer to receive the encoded structure. This parameter can be NULL to retrieve the size of this information for memory allocation purposes.</param>
/// <param name="pcbEncoded">A pointer to a DWORD variable that contains the size, in bytes, of the buffer pointed to by the pbEncoded parameter.</param>
/// <returns></returns>
[DllImport("crypt32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CryptEncodeObject(
UInt32 dwCertEncodingType,
IntPtr lpszStructType,
ref CERT_PUBLIC_KEY_INFO pvStructInfo,
byte[] pbEncoded,
ref UInt32 pcbEncoded);
// ReSharper disable InconsistentNaming
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct CRYPT_BLOB
{
public Int32 cbData;
public IntPtr pbData;
}
[StructLayout(LayoutKind.Sequential)]
internal struct CERT_CONTEXT
{
public Int32 dwCertEncodingType;
public IntPtr pbCertEncoded;
public Int32 cbCertEncoded;
public IntPtr pCertInfo;
public IntPtr hCertStore;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
internal struct CRYPT_ALGORITHM_IDENTIFIER
{
public string pszObjId;
public CRYPT_BLOB Parameters;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
internal struct CRYPT_BIT_BLOB
{
public Int32 cbData;
public IntPtr pbData;
public Int32 cUnusedBits;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct CERT_PUBLIC_KEY_INFO
{
public CRYPT_ALGORITHM_IDENTIFIER Algorithm;
public CRYPT_BIT_BLOB PublicKey;
}
[StructLayout(LayoutKind.Sequential)]
internal class CERT_INFO
{
public Int32 dwVersion;
public CRYPT_BLOB SerialNumber;
public CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
public CRYPT_BLOB Issuer;
public System.Runtime.InteropServices.ComTypes.FILETIME NotBefore;
public System.Runtime.InteropServices.ComTypes.FILETIME NotAfter;
public CRYPT_BLOB Subject;
public CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo;
public CRYPT_BIT_BLOB IssuerUniqueId;
public CRYPT_BIT_BLOB SubjectUniqueId;
public Int32 cExtension;
public IntPtr rgExtension;
}
// ReSharper restore InconsistentNaming
}
}

View File

@ -0,0 +1,40 @@
{
"version": "0.1-alpha-*",
"dependencies": {
"Microsoft.AspNet.DependencyInjection": "0.1-alpha-*",
"Microsoft.AspNet.ConfigurationModel": "0.1-alpha-*",
"Microsoft.AspNet.PipelineCore": "0.1-alpha-*",
"Microsoft.AspNet.Abstractions": "0.1-alpha-*",
"Microsoft.AspNet.FeatureModel": "0.1-alpha-*",
"Microsoft.AspNet.HttpFeature": "0.1-alpha-*",
"Microsoft.AspNet.Logging": "0.1-alpha-*",
"Microsoft.AspNet.Security.DataProtection": "0.1-alpha-*"
},
"configurations": {
"net45": {},
"k10": {
"dependencies": {
"System.Collections": "4.0.0.0",
"System.Console": "4.0.0.0",
"System.ComponentModel": "4.0.0.0",
"System.Diagnostics.Debug": "4.0.10.0",
"System.Diagnostics.Tools": "4.0.0.0",
"System.Globalization": "4.0.10.0",
"System.IO": "4.0.0.0",
"System.IO.Compression": "4.0.0.0",
"System.IO.FileSystem": "4.0.0.0",
"System.IO.FileSystem.Primitives": "4.0.0.0",
"System.Linq": "4.0.0.0",
"System.Reflection": "4.0.10.0",
"System.Resources.ResourceManager": "4.0.0.0",
"System.Runtime": "4.0.20.0",
"System.Runtime.Extensions": "4.0.10.0",
"System.Runtime.InteropServices": "4.0.10.0",
"System.Security.Claims": "0.1-alpha-*",
"System.Security.Principal" : "4.0.0.0",
"System.Threading": "4.0.0.0",
"System.Threading.Tasks": "4.0.0.0"
}
}
}
}