diff --git a/Security.sln b/Security.sln
index 5a80619fc3..7628374e9f 100644
--- a/Security.sln
+++ b/Security.sln
@@ -9,6 +9,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4D2B6A51-2F9
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
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Security.Cookies.net45", "src\Microsoft.AspNet.Security.Cookies\Microsoft.AspNet.Security.Cookies.net45.csproj", "{4579FEC1-3C4C-4F56-ADDB-850F947FDC2D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Security.Cookies.k10", "src\Microsoft.AspNet.Security.Cookies\Microsoft.AspNet.Security.Cookies.k10.csproj", "{17DD587C-CFB8-407C-A674-1C99F5CE9C7E}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CookieSample.net45", "samples\CookieSample\CookieSample.net45.csproj", "{3C25520E-1AF0-4535-A111-6A1C04D31364}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -23,6 +31,18 @@ Global
{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
+ {4579FEC1-3C4C-4F56-ADDB-850F947FDC2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4579FEC1-3C4C-4F56-ADDB-850F947FDC2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4579FEC1-3C4C-4F56-ADDB-850F947FDC2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4579FEC1-3C4C-4F56-ADDB-850F947FDC2D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {17DD587C-CFB8-407C-A674-1C99F5CE9C7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {17DD587C-CFB8-407C-A674-1C99F5CE9C7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {17DD587C-CFB8-407C-A674-1C99F5CE9C7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {17DD587C-CFB8-407C-A674-1C99F5CE9C7E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3C25520E-1AF0-4535-A111-6A1C04D31364}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3C25520E-1AF0-4535-A111-6A1C04D31364}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3C25520E-1AF0-4535-A111-6A1C04D31364}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3C25520E-1AF0-4535-A111-6A1C04D31364}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -30,5 +50,8 @@ Global
GlobalSection(NestedProjects) = preSolution
{70640501-CCBB-4FD7-8231-329B6A436DE4} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
{F2391907-4463-4650-AEA4-E1B5733105C4} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {4579FEC1-3C4C-4F56-ADDB-850F947FDC2D} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {17DD587C-CFB8-407C-A674-1C99F5CE9C7E} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
+ {3C25520E-1AF0-4535-A111-6A1C04D31364} = {F8C0AA27-F3FB-4286-8E4C-47EF86B539FF}
EndGlobalSection
EndGlobal
diff --git a/samples/CookieSample/Startup.cs b/samples/CookieSample/Startup.cs
new file mode 100644
index 0000000000..9c2c29e185
--- /dev/null
+++ b/samples/CookieSample/Startup.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Linq;
+using System.Security.Claims;
+using Microsoft.AspNet;
+using Microsoft.AspNet.Abstractions;
+using Microsoft.AspNet.Abstractions.Security;
+using Microsoft.AspNet.HttpFeature.Security;
+using Microsoft.AspNet.Security;
+using Microsoft.AspNet.Security.Cookies;
+using Microsoft.AspNet.Security.Infrastructure;
+
+namespace CookieSample
+{
+ public class Startup
+ {
+ public void Configuration(IBuilder app)
+ {
+ Console.WriteLine("Attach");
+ Console.ReadKey();
+
+ app.UseCookieAuthentication(new CookieAuthenticationOptions()
+ {
+
+ });
+
+ app.Run(async context =>
+ {
+ if (context.User == null || !context.User.Identity.IsAuthenticated)
+ {
+ context.Authentication.SignIn(new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("name", "bob") }, CookieAuthenticationDefaults.AuthenticationType)));
+
+ context.Response.ContentType = "text/plain";
+ await context.Response.WriteAsync("Hello First timer");
+ return;
+ }
+
+ context.Response.ContentType = "text/plain";
+ await context.Response.WriteAsync("Hello old timer");
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/CookieSample/project.json b/samples/CookieSample/project.json
new file mode 100644
index 0000000000..b25b4148d6
--- /dev/null
+++ b/samples/CookieSample/project.json
@@ -0,0 +1,39 @@
+{
+ "version": "0.1-alpha-*",
+ "dependencies": {
+ "Microsoft.AspNet.Abstractions": "0.1-alpha-*",
+ "Microsoft.AspNet.Security": "",
+ "Microsoft.AspNet.Security.Cookies": "",
+ "Microsoft.AspNet.Hosting": "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.Server.WebListener": "0.1-alpha-*"
+ },
+ "commands": { "web": "Microsoft.AspNet.Hosting server.name=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:12345" },
+ "configurations": {
+ "net45": {
+ },
+ "k10": {
+ "dependencies": {
+ "System.Console": "4.0.0.0",
+ "System.Collections": "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.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.Text.Encoding": "4.0.10.0",
+ "System.Threading.Tasks": "4.0.0.0"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationDefaults.cs b/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationDefaults.cs
new file mode 100644
index 0000000000..8102911fd2
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationDefaults.cs
@@ -0,0 +1,42 @@
+// 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.Abstractions;
+
+namespace Microsoft.AspNet.Security.Cookies
+{
+ ///
+ /// Default values related to cookie-based authentication middleware
+ ///
+ public static class CookieAuthenticationDefaults
+ {
+ ///
+ /// The default value used for CookieAuthenticationOptions.AuthenticationType
+ ///
+ public const string AuthenticationType = "Cookies";
+
+ ///
+ /// The prefix used to provide a default CookieAuthenticationOptions.CookieName
+ ///
+ public const string CookiePrefix = ".AspNet.";
+
+ ///
+ /// The default value used by UseApplicationSignInCookie for the
+ /// CookieAuthenticationOptions.LoginPath
+ ///
+ [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Login", Justification = "By design")]
+ public static readonly PathString LoginPath = new PathString("/Account/Login");
+
+ ///
+ /// The default value used by UseApplicationSignInCookie for the
+ /// CookieAuthenticationOptions.LogoutPath
+ ///
+ [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Logout", Justification = "By design")]
+ public static readonly PathString LogoutPath = new PathString("/Account/Logout");
+
+ ///
+ /// The default value of the CookieAuthenticationOptions.ReturnUrlParameter
+ ///
+ public const string ReturnUrlParameter = "ReturnUrl";
+ }
+}
diff --git a/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationExtensions.cs b/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationExtensions.cs
new file mode 100644
index 0000000000..91d926ab95
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationExtensions.cs
@@ -0,0 +1,53 @@
+// 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.Logging;
+using Microsoft.AspNet.Security.Cookies;
+using Microsoft.AspNet.Security.DataHandler;
+using Microsoft.AspNet.Security.DataProtection;
+
+namespace Microsoft.AspNet
+{
+ ///
+ /// Extension methods provided by the cookies authentication middleware
+ ///
+ public static class CookieAuthenticationExtensions
+ {
+ ///
+ /// Adds a cookie-based authentication middleware to your web application pipeline.
+ ///
+ /// The IAppBuilder passed to your configuration method
+ /// An options class that controls the middleware behavior
+ /// The original app parameter
+ public static IBuilder UseCookieAuthentication(this IBuilder app, CookieAuthenticationOptions options)
+ {
+ if (app == null)
+ {
+ throw new ArgumentNullException("app");
+ }
+ /*
+ // TODO: Extension methods for this?
+ var loggerFactory = (ILoggerFactory)app.ServiceProvider.GetService(typeof(ILoggerFactory));
+ ILogger logger = loggerFactory.Create(typeof(CookieAuthenticationMiddleware).FullName);
+ */
+ ILogger logger = null;
+
+ if (options.TicketDataFormat == null)
+ {
+ /* TODO: Add DPP extensions
+ IDataProtector dataProtector = app.CreateDataProtector(
+ typeof(CookieAuthenticationMiddleware).FullName,
+ options.AuthenticationType, "v1");
+ */
+ var dataProtectionProvider = (IDataProtectionProvider)app.ServiceProvider.GetService(typeof(IDataProtectionProvider));
+ IDataProtector dataProtector = dataProtectionProvider.CreateProtector(string.Join(";", typeof(CookieAuthenticationMiddleware).FullName, options.AuthenticationType, "v1"));
+ options.TicketDataFormat = new TicketDataFormat(dataProtector);
+ }
+
+ app.Use(next => new CookieAuthenticationMiddleware(next, logger, options).Invoke);
+ // TODO: ? app.UseStageMarker(PipelineStage.Authenticate);
+ return app;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationHandler.cs b/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationHandler.cs
new file mode 100644
index 0000000000..5378223c14
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationHandler.cs
@@ -0,0 +1,249 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNet.Security.Infrastructure;
+using Microsoft.AspNet.Logging;
+using Microsoft.AspNet.PipelineCore.Collections;
+using Microsoft.AspNet.Abstractions;
+using Microsoft.AspNet.HttpFeature.Security;
+
+namespace Microsoft.AspNet.Security.Cookies
+{
+ internal class CookieAuthenticationHandler : AuthenticationHandler
+ {
+ private const string HeaderNameCacheControl = "Cache-Control";
+ private const string HeaderNamePragma = "Pragma";
+ private const string HeaderNameExpires = "Expires";
+ private const string HeaderValueNoCache = "no-cache";
+ private const string HeaderValueMinusOne = "-1";
+
+ private readonly ILogger _logger;
+
+ private bool _shouldRenew;
+ private DateTimeOffset _renewIssuedUtc;
+ private DateTimeOffset _renewExpiresUtc;
+
+ public CookieAuthenticationHandler(ILogger logger)
+ {
+ /*
+ if (logger == null)
+ {
+ throw new ArgumentNullException("logger");
+ }*/
+ _logger = logger;
+ }
+
+ protected override AuthenticationTicket AuthenticateCore()
+ {
+ return AuthenticateCoreAsync().Result;
+ }
+
+ protected override async Task AuthenticateCoreAsync()
+ {
+ IReadableStringCollection cookies = Request.Cookies;
+ string cookie = cookies[Options.CookieName];
+ if (string.IsNullOrWhiteSpace(cookie))
+ {
+ return null;
+ }
+
+ AuthenticationTicket ticket = Options.TicketDataFormat.Unprotect(cookie);
+
+ if (ticket == null)
+ {
+ // TODO: _logger.WriteWarning(@"Unprotect ticket failed");
+ return null;
+ }
+
+ DateTimeOffset currentUtc = Options.SystemClock.UtcNow;
+ DateTimeOffset? issuedUtc = ticket.Properties.IssuedUtc;
+ DateTimeOffset? expiresUtc = ticket.Properties.ExpiresUtc;
+
+ if (expiresUtc != null && expiresUtc.Value < currentUtc)
+ {
+ return null;
+ }
+
+ if (issuedUtc != null && expiresUtc != null && Options.SlidingExpiration)
+ {
+ TimeSpan timeElapsed = currentUtc.Subtract(issuedUtc.Value);
+ TimeSpan timeRemaining = expiresUtc.Value.Subtract(currentUtc);
+
+ if (timeRemaining < timeElapsed)
+ {
+ _shouldRenew = true;
+ _renewIssuedUtc = currentUtc;
+ TimeSpan timeSpan = expiresUtc.Value.Subtract(issuedUtc.Value);
+ _renewExpiresUtc = currentUtc.Add(timeSpan);
+ }
+ }
+
+ var context = new CookieValidateIdentityContext(Context, ticket, Options);
+
+ await Options.Provider.ValidateIdentity(context);
+
+ return new AuthenticationTicket(context.Identity, context.Properties);
+ }
+
+ protected override void ApplyResponseGrant()
+ {
+ ApplyResponseGrantAsync().Wait();
+ }
+
+ protected override async Task ApplyResponseGrantAsync()
+ {
+ var signin = SignInIdentityContext;
+ bool shouldSignin = signin != null;
+ var signout = SignOutContext;
+ bool shouldSignout = signout != null;
+
+ if (shouldSignin || shouldSignout || _shouldRenew)
+ {
+ var cookieOptions = new CookieOptions
+ {
+ Domain = Options.CookieDomain,
+ HttpOnly = Options.CookieHttpOnly,
+ Path = Options.CookiePath ?? "/",
+ };
+ if (Options.CookieSecure == CookieSecureOption.SameAsRequest)
+ {
+ cookieOptions.Secure = Request.IsSecure;
+ }
+ else
+ {
+ cookieOptions.Secure = Options.CookieSecure == CookieSecureOption.Always;
+ }
+
+ if (shouldSignin)
+ {
+ var context = new CookieResponseSignInContext(
+ Context,
+ Options,
+ Options.AuthenticationType,
+ signin.Identity,
+ signin.Properties,
+ cookieOptions);
+
+ DateTimeOffset issuedUtc = Options.SystemClock.UtcNow;
+ DateTimeOffset expiresUtc = issuedUtc.Add(Options.ExpireTimeSpan);
+
+ context.Properties.IssuedUtc = issuedUtc;
+ context.Properties.ExpiresUtc = expiresUtc;
+
+ Options.Provider.ResponseSignIn(context);
+
+ if (context.Properties.IsPersistent)
+ {
+ cookieOptions.Expires = expiresUtc.ToUniversalTime().DateTime;
+ }
+
+ var model = new AuthenticationTicket(context.Identity, context.Properties);
+ string cookieValue = Options.TicketDataFormat.Protect(model);
+
+ Response.Cookies.Append(
+ Options.CookieName,
+ cookieValue,
+ cookieOptions);
+ }
+ else if (shouldSignout)
+ {
+ var context = new CookieResponseSignOutContext(
+ Context,
+ Options,
+ cookieOptions);
+
+ Options.Provider.ResponseSignOut(context);
+
+ Response.Cookies.Delete(
+ Options.CookieName,
+ cookieOptions);
+ }
+ else if (_shouldRenew)
+ {
+ AuthenticationTicket model = await AuthenticateAsync();
+
+ model.Properties.IssuedUtc = _renewIssuedUtc;
+ model.Properties.ExpiresUtc = _renewExpiresUtc;
+
+ string cookieValue = Options.TicketDataFormat.Protect(model);
+
+ if (model.Properties.IsPersistent)
+ {
+ cookieOptions.Expires = _renewExpiresUtc.ToUniversalTime().DateTime;
+ }
+
+ Response.Cookies.Append(
+ Options.CookieName,
+ cookieValue,
+ cookieOptions);
+ }
+
+ Response.Headers.Set(
+ HeaderNameCacheControl,
+ HeaderValueNoCache);
+
+ Response.Headers.Set(
+ HeaderNamePragma,
+ HeaderValueNoCache);
+
+ Response.Headers.Set(
+ HeaderNameExpires,
+ HeaderValueMinusOne);
+
+ bool shouldLoginRedirect = shouldSignin && Options.LoginPath.HasValue && Request.Path == Options.LoginPath;
+ bool shouldLogoutRedirect = shouldSignout && Options.LogoutPath.HasValue && Request.Path == Options.LogoutPath;
+
+ if ((shouldLoginRedirect || shouldLogoutRedirect) && Response.StatusCode == 200)
+ {
+ IReadableStringCollection query = Request.Query;
+ string redirectUri = query.Get(Options.ReturnUrlParameter);
+ if (!string.IsNullOrWhiteSpace(redirectUri)
+ && IsHostRelative(redirectUri))
+ {
+ var redirectContext = new CookieApplyRedirectContext(Context, Options, redirectUri);
+ Options.Provider.ApplyRedirect(redirectContext);
+ }
+ }
+ }
+ }
+
+ private static bool IsHostRelative(string path)
+ {
+ if (string.IsNullOrEmpty(path))
+ {
+ return false;
+ }
+ if (path.Length == 1)
+ {
+ return path[0] == '/';
+ }
+ return path[0] == '/' && path[1] != '/' && path[1] != '\\';
+ }
+
+ protected override void ApplyResponseChallenge()
+ {
+ if (Response.StatusCode != 401 || !Options.LoginPath.HasValue || ChallengeContext == null)
+ {
+ return;
+ }
+
+ string currentUri =
+ Request.PathBase +
+ Request.Path +
+ Request.QueryString;
+
+ string loginUri =
+ Request.Scheme +
+ "://" +
+ Request.Host +
+ Request.PathBase +
+ Options.LoginPath +
+ new QueryString(Options.ReturnUrlParameter, currentUri);
+
+ var redirectContext = new CookieApplyRedirectContext(Context, Options, loginUri);
+ Options.Provider.ApplyRedirect(redirectContext);
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationMiddleware.cs
new file mode 100644
index 0000000000..b0ad64125f
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationMiddleware.cs
@@ -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 Microsoft.AspNet.Abstractions;
+using Microsoft.AspNet.Logging;
+using Microsoft.AspNet.Security.DataHandler;
+using Microsoft.AspNet.Security.DataProtection;
+using Microsoft.AspNet.Security.Infrastructure;
+
+namespace Microsoft.AspNet.Security.Cookies
+{
+ internal class CookieAuthenticationMiddleware : AuthenticationMiddleware
+ {
+ private readonly ILogger _logger;
+
+ public CookieAuthenticationMiddleware(RequestDelegate next, ILogger logger, CookieAuthenticationOptions options)
+ : base(next, options)
+ {
+ if (Options.Provider == null)
+ {
+ Options.Provider = new CookieAuthenticationProvider();
+ }
+ if (String.IsNullOrEmpty(Options.CookieName))
+ {
+ Options.CookieName = CookieAuthenticationDefaults.CookiePrefix + Options.AuthenticationType;
+ }/*
+ if (logger == null)
+ {
+ throw new ArgumentNullException("logger");
+ }*/
+ _logger = logger;
+ }
+
+ protected override AuthenticationHandler CreateHandler()
+ {
+ return new CookieAuthenticationHandler(_logger);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationOptions.cs b/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationOptions.cs
new file mode 100644
index 0000000000..389a611c33
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/CookieAuthenticationOptions.cs
@@ -0,0 +1,137 @@
+// 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 Microsoft.AspNet.Abstractions;
+using Microsoft.AspNet.Security.Infrastructure;
+
+namespace Microsoft.AspNet.Security.Cookies
+{
+ ///
+ /// Contains the options used by the CookiesAuthenticationMiddleware
+ ///
+ public class CookieAuthenticationOptions : AuthenticationOptions
+ {
+ private string _cookieName;
+
+ ///
+ /// Create an instance of the options initialized with the default values
+ ///
+ public CookieAuthenticationOptions()
+ : base(CookieAuthenticationDefaults.AuthenticationType)
+ {
+ ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
+ CookiePath = "/";
+ ExpireTimeSpan = TimeSpan.FromDays(14);
+ SlidingExpiration = true;
+ CookieHttpOnly = true;
+ CookieSecure = CookieSecureOption.SameAsRequest;
+ SystemClock = new SystemClock();
+ Provider = new CookieAuthenticationProvider();
+ }
+
+ ///
+ /// Determines the cookie name used to persist the identity. The default value is ".AspNet.Cookies".
+ /// This value should be changed if you change the name of the AuthenticationType, especially if your
+ /// system uses the cookie authentication middleware multiple times.
+ ///
+ public string CookieName
+ {
+ get { return _cookieName; }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+ _cookieName = value;
+ }
+ }
+
+ ///
+ /// Determines the domain used to create the cookie. Is not provided by default.
+ ///
+ public string CookieDomain { get; set; }
+
+ ///
+ /// Determines the path used to create the cookie. The default value is "/" for highest browser compatability.
+ ///
+ public string CookiePath { get; set; }
+
+ ///
+ /// Determines if the browser should allow the cookie to be accessed by client-side javascript. The
+ /// default is true, which means the cookie will only be passed to http requests and is not made available
+ /// to script on the page.
+ ///
+ public bool CookieHttpOnly { get; set; }
+
+ ///
+ /// Determines if the cookie should only be transmitted on HTTPS request. The default is to limit the cookie
+ /// to HTTPS requests if the page which is doing the SignIn is also HTTPS. If you have an HTTPS sign in page
+ /// and portions of your site are HTTP you may need to change this value.
+ ///
+ public CookieSecureOption CookieSecure { get; set; }
+
+ ///
+ /// Controls how much time the cookie will remain valid from the point it is created. The expiration
+ /// information is in the protected cookie ticket. Because of that an expired cookie will be ignored
+ /// even if it is passed to the server after the browser should have purged it
+ ///
+ public TimeSpan ExpireTimeSpan { get; set; }
+
+ ///
+ /// The SlidingExpiration is set to true to instruct the middleware to re-issue a new cookie with a new
+ /// expiration time any time it processes a request which is more than halfway through the expiration window.
+ ///
+ public bool SlidingExpiration { get; set; }
+
+ ///
+ /// The LoginPath property informs the middleware that it should change an outgoing 401 Unauthorized status
+ /// code into a 302 redirection onto the given login path. The current url which generated the 401 is added
+ /// to the LoginPath as a query string parameter named by the ReturnUrlParameter. Once a request to the
+ /// LoginPath grants a new SignIn identity, the ReturnUrlParameter value is used to redirect the browser back
+ /// to the url which caused the original unauthorized status code.
+ ///
+ /// If the LoginPath is null or empty, the middleware will not look for 401 Unauthorized status codes, and it will
+ /// not redirect automatically when a login occurs.
+ ///
+ [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Login", Justification = "By design")]
+ public PathString LoginPath { get; set; }
+
+ ///
+ /// If the LogoutPath is provided the middleware then a request to that path will redirect based on the ReturnUrlParameter.
+ ///
+ [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Logout", Justification = "By design")]
+ public PathString LogoutPath { get; set; }
+
+ ///
+ /// The ReturnUrlParameter determines the name of the query string parameter which is appended by the middleware
+ /// when a 401 Unauthorized status code is changed to a 302 redirect onto the login path. This is also the query
+ /// string parameter looked for when a request arrives on the login path or logout path, in order to return to the
+ /// original url after the action is performed.
+ ///
+ [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "ReturnUrl is the name of a querystring parameter")]
+ public string ReturnUrlParameter { get; set; }
+
+ ///
+ /// The Provider may be assigned to an instance of an object created by the application at startup time. The middleware
+ /// calls methods on the provider which give the application control at certain points where processing is occuring.
+ /// If it is not provided a default instance is supplied which does nothing when the methods are called.
+ ///
+ public ICookieAuthenticationProvider Provider { get; set; }
+
+ ///
+ /// The TicketDataFormat is used to protect and unprotect the identity and other properties which are stored in the
+ /// cookie value. If it is not provided a default data handler is created using the data protection service contained
+ /// in the IAppBuilder.Properties. The default data protection service is based on machine key when running on ASP.NET,
+ /// and on DPAPI when running in a different process.
+ ///
+ public ISecureDataFormat TicketDataFormat { get; set; }
+
+ ///
+ /// The SystemClock provides access to the system's current time coordinates. If it is not provided a default instance is
+ /// used which calls DateTimeOffset.UtcNow. This is typically not replaced except for unit testing.
+ ///
+ public ISystemClock SystemClock { get; set; }
+ }
+}
diff --git a/src/Microsoft.AspNet.Security.Cookies/CookieSecureOption.cs b/src/Microsoft.AspNet.Security.Cookies/CookieSecureOption.cs
new file mode 100644
index 0000000000..19efae749b
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/CookieSecureOption.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+namespace Microsoft.AspNet.Security.Cookies
+{
+ ///
+ /// Determines how the identity cookie's security property is set.
+ ///
+ public enum CookieSecureOption
+ {
+ ///
+ /// If the URI that provides the cookie is HTTPS, then the cookie will only be returned to the server on
+ /// subsequent HTTPS requests. Otherwise if the URI that provides the cookie is HTTP, then the cookie will
+ /// be returned to the server on all HTTP and HTTPS requests. This is the default value because it ensures
+ /// HTTPS for all authenticated requests on deployed servers, and also supports HTTP for localhost development
+ /// and for servers that do not have HTTPS support.
+ ///
+ SameAsRequest,
+
+ ///
+ /// CookieOptions.Secure is never marked true. Use this value when your login page is HTTPS, but other pages
+ /// on the site which are HTTP also require authentication information. This setting is not recommended because
+ /// the authentication information provided with an HTTP request may be observed and used by other computers
+ /// on your local network or wireless connection.
+ ///
+ Never,
+
+ ///
+ /// CookieOptions.Secure is always marked true. Use this value when your login page and all subsequent pages
+ /// requiring the authenticated identity are HTTPS. Local development will also need to be done with HTTPS urls.
+ ///
+ Always,
+ }
+}
diff --git a/src/Microsoft.AspNet.Security.Cookies/Provider/CookieApplyRedirectContext.cs b/src/Microsoft.AspNet.Security.Cookies/Provider/CookieApplyRedirectContext.cs
new file mode 100644
index 0000000000..69ccc0c386
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/Provider/CookieApplyRedirectContext.cs
@@ -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.Diagnostics.CodeAnalysis;
+using Microsoft.AspNet.Abstractions;
+using Microsoft.AspNet.Security.Provider;
+
+namespace Microsoft.AspNet.Security.Cookies
+{
+ ///
+ /// Context passed when a Challenge, SignIn, or SignOut causes a redirect in the cookie middleware
+ ///
+ public class CookieApplyRedirectContext : BaseContext
+ {
+ ///
+ /// Creates a new context object.
+ ///
+ /// The OWIN request context
+ /// The cookie middleware options
+ /// The initial redirect URI
+ [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "Represents header value")]
+ public CookieApplyRedirectContext(HttpContext context, CookieAuthenticationOptions options, string redirectUri)
+ : base(context, options)
+ {
+ RedirectUri = redirectUri;
+ }
+
+ ///
+ /// Gets or Sets the URI used for the redirect operation.
+ ///
+ [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Represents header value")]
+ public string RedirectUri { get; set; }
+ }
+}
diff --git a/src/Microsoft.AspNet.Security.Cookies/Provider/CookieAuthenticationProvider.cs b/src/Microsoft.AspNet.Security.Cookies/Provider/CookieAuthenticationProvider.cs
new file mode 100644
index 0000000000..6b434c0b2b
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/Provider/CookieAuthenticationProvider.cs
@@ -0,0 +1,83 @@
+// 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.Cookies
+{
+ ///
+ /// This default implementation of the ICookieAuthenticationProvider may be used if the
+ /// application only needs to override a few of the interface methods. This may be used as a base class
+ /// or may be instantiated directly.
+ ///
+ public class CookieAuthenticationProvider : ICookieAuthenticationProvider
+ {
+ ///
+ /// Create a new instance of the default provider.
+ ///
+ public CookieAuthenticationProvider()
+ {
+ OnValidateIdentity = context => Task.FromResult(0);
+ OnResponseSignIn = context => { };
+ OnResponseSignOut = context => { };
+ OnApplyRedirect = DefaultBehavior.ApplyRedirect;
+ }
+
+ ///
+ /// A delegate assigned to this property will be invoked when the related method is called
+ ///
+ public Func OnValidateIdentity { get; set; }
+
+ ///
+ /// A delegate assigned to this property will be invoked when the related method is called
+ ///
+ public Action OnResponseSignIn { get; set; }
+
+ ///
+ /// A delegate assigned to this property will be invoked when the related method is called
+ ///
+ public Action OnResponseSignOut { get; set; }
+
+ ///
+ /// A delegate assigned to this property will be invoked when the related method is called
+ ///
+ public Action OnApplyRedirect { get; set; }
+
+ ///
+ /// Implements the interface method by invoking the related delegate method
+ ///
+ ///
+ ///
+ public virtual Task ValidateIdentity(CookieValidateIdentityContext context)
+ {
+ return OnValidateIdentity.Invoke(context);
+ }
+
+ ///
+ /// Implements the interface method by invoking the related delegate method
+ ///
+ ///
+ public virtual void ResponseSignIn(CookieResponseSignInContext context)
+ {
+ OnResponseSignIn.Invoke(context);
+ }
+
+ ///
+ /// Implements the interface method by invoking the related delegate method
+ ///
+ ///
+ public virtual void ResponseSignOut(CookieResponseSignOutContext context)
+ {
+ OnResponseSignOut.Invoke(context);
+ }
+
+ ///
+ /// Called when a Challenge, SignIn, or SignOut causes a redirect in the cookie middleware
+ ///
+ /// Contains information about the event
+ public void ApplyRedirect(CookieApplyRedirectContext context)
+ {
+ OnApplyRedirect.Invoke(context);
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Security.Cookies/Provider/CookieResponseSignInContext.cs b/src/Microsoft.AspNet.Security.Cookies/Provider/CookieResponseSignInContext.cs
new file mode 100644
index 0000000000..e3098e3590
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/Provider/CookieResponseSignInContext.cs
@@ -0,0 +1,62 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+using System.Security.Claims;
+using Microsoft.AspNet.Abstractions;
+using Microsoft.AspNet.Abstractions.Security;
+using Microsoft.AspNet.Security.Provider;
+
+namespace Microsoft.AspNet.Security.Cookies
+{
+ ///
+ /// Context object passed to the ICookieAuthenticationProvider method ResponseSignIn.
+ ///
+ public class CookieResponseSignInContext : BaseContext
+ {
+ ///
+ /// Creates a new instance of the context object.
+ ///
+ /// The OWIN request context
+ /// The middleware options
+ /// Initializes AuthenticationType property
+ /// Initializes Identity property
+ /// Initializes Extra property
+ /// Initializes options for the authentication cookie.
+ public CookieResponseSignInContext(
+ HttpContext context,
+ CookieAuthenticationOptions options,
+ string authenticationType,
+ ClaimsIdentity identity,
+ AuthenticationProperties properties,
+ CookieOptions cookieOptions)
+ : base(context, options)
+ {
+ AuthenticationType = authenticationType;
+ Identity = identity;
+ Properties = properties;
+ CookieOptions = cookieOptions;
+ }
+
+ ///
+ /// The name of the AuthenticationType creating a cookie
+ ///
+ public string AuthenticationType { get; private set; }
+
+ ///
+ /// Contains the claims about to be converted into the outgoing cookie.
+ /// May be replaced or altered during the ResponseSignIn call.
+ ///
+ public ClaimsIdentity Identity { get; set; }
+
+ ///
+ /// Contains the extra data about to be contained in the outgoing cookie.
+ /// May be replaced or altered during the ResponseSignIn call.
+ ///
+ public AuthenticationProperties Properties { get; set; }
+
+ ///
+ /// The options for creating the outgoing cookie.
+ /// May be replace or altered during the ResponseSignIn call.
+ ///
+ public CookieOptions CookieOptions { get; set; }
+ }
+}
diff --git a/src/Microsoft.AspNet.Security.Cookies/Provider/CookieResponseSignOutContext.cs b/src/Microsoft.AspNet.Security.Cookies/Provider/CookieResponseSignOutContext.cs
new file mode 100644
index 0000000000..e17028982a
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/Provider/CookieResponseSignOutContext.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+using Microsoft.AspNet.Abstractions;
+using Microsoft.AspNet.Security.Provider;
+
+namespace Microsoft.AspNet.Security.Cookies
+{
+ ///
+ /// Context object passed to the ICookieAuthenticationProvider method ResponseSignOut
+ ///
+ public class CookieResponseSignOutContext : BaseContext
+ {
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public CookieResponseSignOutContext(HttpContext context, CookieAuthenticationOptions options, CookieOptions cookieOptions)
+ : base(context, options)
+ {
+ CookieOptions = cookieOptions;
+ }
+
+ ///
+ /// The options for creating the outgoing cookie.
+ /// May be replace or altered during the ResponseSignIn call.
+ ///
+ public CookieOptions CookieOptions
+ {
+ get;
+ set;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Security.Cookies/Provider/CookieValidateIdentityContext.cs b/src/Microsoft.AspNet.Security.Cookies/Provider/CookieValidateIdentityContext.cs
new file mode 100644
index 0000000000..4487582209
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/Provider/CookieValidateIdentityContext.cs
@@ -0,0 +1,67 @@
+// 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;
+using Microsoft.AspNet.Abstractions.Security;
+using Microsoft.AspNet.HttpFeature.Security;
+using Microsoft.AspNet.Security.Infrastructure;
+using Microsoft.AspNet.Security.Provider;
+
+namespace Microsoft.AspNet.Security.Cookies
+{
+ ///
+ /// Context object passed to the ICookieAuthenticationProvider method ValidateIdentity.
+ ///
+ public class CookieValidateIdentityContext : BaseContext
+ {
+ ///
+ /// Creates a new instance of the context object.
+ ///
+ ///
+ /// Contains the initial values for identity and extra data
+ ///
+ public CookieValidateIdentityContext(HttpContext context, AuthenticationTicket ticket, CookieAuthenticationOptions options)
+ : base(context, options)
+ {
+ if (ticket == null)
+ {
+ throw new ArgumentNullException("ticket");
+ }
+
+ Identity = ticket.Identity;
+ Properties = ticket.Properties;
+ }
+
+ ///
+ /// Contains the claims identity arriving with the request. May be altered to change the
+ /// details of the authenticated user.
+ ///
+ public ClaimsIdentity Identity { get; private set; }
+
+ ///
+ /// Contains the extra meta-data arriving with the request ticket. May be altered.
+ ///
+ public AuthenticationProperties Properties { get; private set; }
+
+ ///
+ /// Called to replace the claims identity. The supplied identity will replace the value of the
+ /// Identity property, which determines the identity of the authenticated request.
+ ///
+ /// The identity used as the replacement
+ public void ReplaceIdentity(IIdentity identity)
+ {
+ Identity = new ClaimsIdentity(identity);
+ }
+
+ ///
+ /// Called to reject the incoming identity. This may be done if the application has determined the
+ /// account is no longer active, and the request should be treated as if it was anonymous.
+ ///
+ public void RejectIdentity()
+ {
+ Identity = null;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Security.Cookies/Provider/DefaultBehavior.cs b/src/Microsoft.AspNet.Security.Cookies/Provider/DefaultBehavior.cs
new file mode 100644
index 0000000000..d90acf62ff
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/Provider/DefaultBehavior.cs
@@ -0,0 +1,55 @@
+// 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 Newtonsoft.Json;
+
+namespace Microsoft.AspNet.Security.Cookies
+{
+ internal static class DefaultBehavior
+ {
+ internal static readonly Action ApplyRedirect = context =>
+ {
+ if (IsAjaxRequest(context.Request))
+ {
+ string jsonResponse = JsonConvert.SerializeObject(new
+ {
+ status = context.Response.StatusCode,
+ headers = new
+ {
+ location = context.RedirectUri
+ }
+ }, Formatting.None);
+
+ context.Response.StatusCode = 200;
+ context.Response.Headers.Append("X-Responded-JSON", jsonResponse);
+ }
+ else
+ {
+ context.Response.Redirect(context.RedirectUri);
+ }
+ };
+
+ private static bool IsAjaxRequest(HttpRequest request)
+ {
+ IReadableStringCollection query = request.Query;
+ if (query != null)
+ {
+ if (query["X-Requested-With"] == "XMLHttpRequest")
+ {
+ return true;
+ }
+ }
+
+ IHeaderDictionary headers = request.Headers;
+ if (headers != null)
+ {
+ if (headers["X-Requested-With"] == "XMLHttpRequest")
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Security.Cookies/Provider/ICookieAuthenticationProvider.cs b/src/Microsoft.AspNet.Security.Cookies/Provider/ICookieAuthenticationProvider.cs
new file mode 100644
index 0000000000..f33a22259f
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/Provider/ICookieAuthenticationProvider.cs
@@ -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.Threading.Tasks;
+
+namespace Microsoft.AspNet.Security.Cookies
+{
+ ///
+ /// Specifies callback methods which the invokes to enable developer control over the authentication process. />
+ ///
+ public interface ICookieAuthenticationProvider
+ {
+ ///
+ /// Called each time a request identity has been validated by the middleware. By implementing this method the
+ /// application may alter or reject the identity which has arrived with the request.
+ ///
+ /// Contains information about the login session as well as the user .
+ /// A representing the completed operation.
+ Task ValidateIdentity(CookieValidateIdentityContext context);
+
+ ///
+ /// Called when an endpoint has provided sign in information before it is converted into a cookie. By
+ /// implementing this method the claims and extra information that go into the ticket may be altered.
+ ///
+ /// Contains information about the login session as well as the user .
+ void ResponseSignIn(CookieResponseSignInContext context);
+
+ ///
+ /// Called when a Challenge, SignIn, or SignOut causes a redirect in the cookie middleware
+ ///
+ /// Contains information about the event
+ void ApplyRedirect(CookieApplyRedirectContext context);
+
+ ///
+ ///
+ ///
+ /// Contains information about the login session as well as information about the authentication cookie.
+ void ResponseSignOut(CookieResponseSignOutContext context);
+ }
+}
diff --git a/src/Microsoft.AspNet.Security.Cookies/project.json b/src/Microsoft.AspNet.Security.Cookies/project.json
new file mode 100644
index 0000000000..ee461aabbd
--- /dev/null
+++ b/src/Microsoft.AspNet.Security.Cookies/project.json
@@ -0,0 +1,42 @@
+{
+ "version": "0.1-alpha-*",
+ "dependencies": {
+ "Newtonsoft.Json": "5.0.8",
+ "Microsoft.AspNet.Security": "0.1-alpha-*",
+ "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"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Security/AuthenticationOptions.cs b/src/Microsoft.AspNet.Security/AuthenticationOptions.cs
index 262bce7f3e..bfd63df993 100644
--- a/src/Microsoft.AspNet.Security/AuthenticationOptions.cs
+++ b/src/Microsoft.AspNet.Security/AuthenticationOptions.cs
@@ -1,5 +1,11 @@
// 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 Microsoft.AspNet.Abstractions.Security;
+using Microsoft.AspNet.HttpFeature.Security;
+using Microsoft.AspNet.PipelineCore.Security;
+
namespace Microsoft.AspNet.Security
{
///
diff --git a/src/Microsoft.AspNet.Security/AuthenticationTicket.cs b/src/Microsoft.AspNet.Security/AuthenticationTicket.cs
index ac2e31006f..2b910d9445 100644
--- a/src/Microsoft.AspNet.Security/AuthenticationTicket.cs
+++ b/src/Microsoft.AspNet.Security/AuthenticationTicket.cs
@@ -1,6 +1,12 @@
// 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.Security.Claims;
+using Microsoft.AspNet.Abstractions.Security;
+using Microsoft.AspNet.HttpFeature.Security;
+using Microsoft.AspNet.PipelineCore.Security;
+using Microsoft.AspNet.Security.Infrastructure;
namespace Microsoft.AspNet.Security
{
diff --git a/src/Microsoft.AspNet.Security/CertificateSubjectKeyIdentifierValidator.cs b/src/Microsoft.AspNet.Security/CertificateSubjectKeyIdentifierValidator.cs
index 8c1ade928f..a549c3740d 100644
--- a/src/Microsoft.AspNet.Security/CertificateSubjectKeyIdentifierValidator.cs
+++ b/src/Microsoft.AspNet.Security/CertificateSubjectKeyIdentifierValidator.cs
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
-/* TODO:
+#if NET45
using System;
using System.Collections.Generic;
using System.Net.Security;
@@ -85,4 +85,4 @@ namespace Microsoft.AspNet.Security
}
}
}
-*/
\ No newline at end of file
+#endif
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Security/CertificateSubjectPublicKeyInfoValidator.cs b/src/Microsoft.AspNet.Security/CertificateSubjectPublicKeyInfoValidator.cs
index 119b553f21..0896c72d97 100644
--- a/src/Microsoft.AspNet.Security/CertificateSubjectPublicKeyInfoValidator.cs
+++ b/src/Microsoft.AspNet.Security/CertificateSubjectPublicKeyInfoValidator.cs
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
-/* TODO:
+#if NET45
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -132,4 +132,4 @@ namespace Microsoft.AspNet.Security
}
}
}
-*/
\ No newline at end of file
+#endif
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Security/CertificateThumbprintValidator.cs b/src/Microsoft.AspNet.Security/CertificateThumbprintValidator.cs
index cc1fddf397..464d579011 100644
--- a/src/Microsoft.AspNet.Security/CertificateThumbprintValidator.cs
+++ b/src/Microsoft.AspNet.Security/CertificateThumbprintValidator.cs
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
-/* TODO:
+#if NET45
using System;
using System.Collections.Generic;
using System.Net.Security;
@@ -78,4 +78,4 @@ namespace Microsoft.AspNet.Security
}
}
}
-*/
\ No newline at end of file
+#endif
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Security/DataHandler/PropertiesDataFormat.cs b/src/Microsoft.AspNet.Security/DataHandler/PropertiesDataFormat.cs
index 54d69c4f57..43aab1c990 100644
--- a/src/Microsoft.AspNet.Security/DataHandler/PropertiesDataFormat.cs
+++ b/src/Microsoft.AspNet.Security/DataHandler/PropertiesDataFormat.cs
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+using Microsoft.AspNet.Abstractions.Security;
using Microsoft.AspNet.Security.DataHandler.Encoder;
using Microsoft.AspNet.Security.DataHandler.Serializer;
using Microsoft.AspNet.Security.DataProtection;
diff --git a/src/Microsoft.AspNet.Security/DataHandler/Serializer/DataSerializers.cs b/src/Microsoft.AspNet.Security/DataHandler/Serializer/DataSerializers.cs
index 59585f6f9b..b46f5dcb98 100644
--- a/src/Microsoft.AspNet.Security/DataHandler/Serializer/DataSerializers.cs
+++ b/src/Microsoft.AspNet.Security/DataHandler/Serializer/DataSerializers.cs
@@ -1,5 +1,7 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+using Microsoft.AspNet.Abstractions.Security;
+
namespace Microsoft.AspNet.Security.DataHandler.Serializer
{
public static class DataSerializers
diff --git a/src/Microsoft.AspNet.Security/DataHandler/Serializer/PropertiesSerializer.cs b/src/Microsoft.AspNet.Security/DataHandler/Serializer/PropertiesSerializer.cs
index 2675932fc3..1ba7164059 100644
--- a/src/Microsoft.AspNet.Security/DataHandler/Serializer/PropertiesSerializer.cs
+++ b/src/Microsoft.AspNet.Security/DataHandler/Serializer/PropertiesSerializer.cs
@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
+using Microsoft.AspNet.Abstractions.Security;
namespace Microsoft.AspNet.Security.DataHandler.Serializer
{
diff --git a/src/Microsoft.AspNet.Security/DataHandler/Serializer/TicketSerializer.cs b/src/Microsoft.AspNet.Security/DataHandler/Serializer/TicketSerializer.cs
index 4ca3c0a6af..de3abbd92e 100644
--- a/src/Microsoft.AspNet.Security/DataHandler/Serializer/TicketSerializer.cs
+++ b/src/Microsoft.AspNet.Security/DataHandler/Serializer/TicketSerializer.cs
@@ -1,6 +1,7 @@
// 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.IO;
using System.IO.Compression;
using System.Linq;
@@ -98,7 +99,7 @@ namespace Microsoft.AspNet.Security.DataHandler.Serializer
claims[index] = new Claim(type, value, valueType, issuer, originalIssuer);
}
var identity = new ClaimsIdentity(claims, authenticationType, nameClaimType, roleClaimType);
- AuthenticationProperties properties = PropertiesSerializer.Read(reader);
+ var properties = PropertiesSerializer.Read(reader);
return new AuthenticationTicket(identity, properties);
}
diff --git a/src/Microsoft.AspNet.Security/ICertificateValidator.cs b/src/Microsoft.AspNet.Security/ICertificateValidator.cs
index 8d062aecfe..3b84fb4850 100644
--- a/src/Microsoft.AspNet.Security/ICertificateValidator.cs
+++ b/src/Microsoft.AspNet.Security/ICertificateValidator.cs
@@ -1,5 +1,5 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
-/* TODO:
+#if NET45
using System;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
@@ -25,4 +25,4 @@ namespace Microsoft.AspNet.Security
bool Validate(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors);
}
}
-*/
\ No newline at end of file
+#endif
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Security/Infrastructure/AuthenticationHandler.cs b/src/Microsoft.AspNet.Security/Infrastructure/AuthenticationHandler.cs
index 39d6596d3c..986826f792 100644
--- a/src/Microsoft.AspNet.Security/Infrastructure/AuthenticationHandler.cs
+++ b/src/Microsoft.AspNet.Security/Infrastructure/AuthenticationHandler.cs
@@ -1,25 +1,29 @@
// 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.Linq;
+using System.Security.Claims;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.AspNet.Abstractions;
+using Microsoft.AspNet.Abstractions.Security;
+using Microsoft.AspNet.HttpFeature.Security;
using Microsoft.AspNet.Logging;
using Microsoft.AspNet.Security.DataHandler.Encoder;
-using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Security.Infrastructure
{
///
/// Base class for the per-request work performed by most authentication middleware.
///
- public abstract class AuthenticationHandler
+ public abstract class AuthenticationHandler : IAuthenticationHandler
{
+#if NET45
private static readonly RNGCryptoServiceProvider Random = new RNGCryptoServiceProvider();
-
- private object _registration;
-
+#endif
private Task _authenticate;
private bool _authenticateInitialized;
private object _authenticateSyncLock;
@@ -30,6 +34,10 @@ namespace Microsoft.AspNet.Security.Infrastructure
private AuthenticationOptions _baseOptions;
+ protected IChallengeContext ChallengeContext { get; set; }
+ protected SignInIdentityContext SignInIdentityContext { get; set; }
+ protected ISignOutContext SignOutContext { get; set; }
+
protected HttpContext Context { get; private set; }
protected HttpRequest Request
@@ -43,21 +51,21 @@ namespace Microsoft.AspNet.Security.Infrastructure
}
protected PathString RequestPathBase { get; private set; }
- protected SecurityHelper Helper { get; private set; }
internal AuthenticationOptions BaseOptions
{
get { return _baseOptions; }
}
+ public IAuthenticationHandler PriorHandler { get; set; }
+
protected async Task BaseInitializeAsync(AuthenticationOptions options, HttpContext context)
{
_baseOptions = options;
Context = context;
- Helper = new SecurityHelper(context);
RequestPathBase = Request.PathBase;
- _registration = Request.RegisterAuthenticationHandler(this);
+ RegisterAuthenticationHandler();
Response.OnSendingHeaders(OnSendingHeaderCallback, this);
@@ -68,7 +76,7 @@ namespace Microsoft.AspNet.Security.Infrastructure
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket != null && ticket.Identity != null)
{
- Helper.AddUserIdentity(ticket.Identity);
+ Context.AddUserIdentity(ticket.Identity);
}
}
}
@@ -76,12 +84,12 @@ namespace Microsoft.AspNet.Security.Infrastructure
private static void OnSendingHeaderCallback(object state)
{
AuthenticationHandler handler = (AuthenticationHandler)state;
- handler.ApplyResponseAsync().Wait();
+ handler.ApplyResponse();
}
protected virtual Task InitializeCoreAsync()
{
- return Task.FromResult