Initial port of Secuirty base package from Katana.
This commit is contained in:
commit
085188996c
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
@ -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 %*
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"sources": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
var VERSION='0.1'
|
||||
var FULL_VERSION='0.1'
|
||||
var AUTHORS='Microsoft'
|
||||
|
||||
use-standard-lifecycle
|
||||
k-standard-goals
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.";
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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'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 'host.AppName' 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue