Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Commit a7bf561

Browse files
author
Nate McMaster
committed
Add CookieBuilder to CookieAuthenticationOptions and obsolete the duplicated properties
1 parent 968237d commit a7bf561

File tree

8 files changed

+188
-191
lines changed

8 files changed

+188
-191
lines changed

Security.sln

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Microsoft Visual Studio Solution File, Format Version 12.00
22
# Visual Studio 15
3-
VisualStudioVersion = 15.0.26507.0
3+
VisualStudioVersion = 15.0.26621.2
44
MinimumVisualStudioVersion = 10.0.40219.1
55
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4D2B6A51-2F9F-44F5-8131-EA5CAC053652}"
66
EndProject
@@ -59,6 +59,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
5959
build\common.props = build\common.props
6060
build\dependencies.props = build\dependencies.props
6161
build\Key.snk = build\Key.snk
62+
NuGet.config = NuGet.config
6263
build\repo.props = build\repo.props
6364
EndProjectSection
6465
EndProject
@@ -484,4 +485,7 @@ Global
484485
{51563775-C659-4907-9BAF-9995BAB87D01} = {7BF11F3A-60B6-4796-B504-579C67FFBA34}
485486
{58194599-F07D-47A3-9DF2-E21A22C5EF9E} = {4D2B6A51-2F9F-44F5-8131-EA5CAC053652}
486487
EndGlobalSection
488+
GlobalSection(ExtensibilityGlobals) = postSolution
489+
SolutionGuid = {ABF8089E-43D0-4010-84A7-7A9DCFE49357}
490+
EndGlobalSection
487491
EndGlobal

src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationHandler.cs

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414

1515
namespace Microsoft.AspNetCore.Authentication.Cookies
1616
{
17-
public class CookieAuthenticationHandler :
18-
AuthenticationHandler<CookieAuthenticationOptions>,
19-
IAuthenticationSignInHandler,
17+
public class CookieAuthenticationHandler :
18+
AuthenticationHandler<CookieAuthenticationOptions>,
19+
IAuthenticationSignInHandler,
2020
IAuthenticationSignOutHandler
2121
{
2222
private const string HeaderValueNoCache = "no-cache";
@@ -37,7 +37,7 @@ public CookieAuthenticationHandler(IOptionsSnapshot<CookieAuthenticationOptions>
3737
{ }
3838

3939
/// <summary>
40-
/// The handler calls methods on the events which give the application control at certain points where processing is occurring.
40+
/// The handler calls methods on the events which give the application control at certain points where processing is occurring.
4141
/// If it is not provided a default instance is supplied which does nothing when the methods are called.
4242
/// </summary>
4343
protected new CookieAuthenticationEvents Events
@@ -104,7 +104,7 @@ private void RequestRefresh(AuthenticationTicket ticket)
104104

105105
private async Task<AuthenticateResult> ReadCookieTicket()
106106
{
107-
var cookie = Options.CookieManager.GetRequestCookie(Context, Options.CookieName);
107+
var cookie = Options.CookieManager.GetRequestCookie(Context, Options.Cookie.Name);
108108
if (string.IsNullOrEmpty(cookie))
109109
{
110110
return AuthenticateResult.NoResult();
@@ -176,22 +176,9 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
176176

177177
private CookieOptions BuildCookieOptions()
178178
{
179-
var cookieOptions = new CookieOptions
180-
{
181-
Domain = Options.CookieDomain,
182-
SameSite = Options.CookieSameSite,
183-
HttpOnly = Options.CookieHttpOnly,
184-
Path = Options.CookiePath ?? (OriginalPathBase.HasValue ? OriginalPathBase.ToString() : "/"),
185-
};
186-
187-
if (Options.CookieSecure == CookieSecurePolicy.SameAsRequest)
188-
{
189-
cookieOptions.Secure = Request.IsHttps;
190-
}
191-
else
192-
{
193-
cookieOptions.Secure = Options.CookieSecure == CookieSecurePolicy.Always;
194-
}
179+
var cookieOptions = Options.Cookie.Build(Context);
180+
// ignore the 'Expires' value as this will be computed elsewhere
181+
cookieOptions.Expires = null;
195182

196183
return cookieOptions;
197184
}
@@ -239,7 +226,7 @@ protected virtual async Task FinishResponseAsync()
239226

240227
Options.CookieManager.AppendResponseCookie(
241228
Context,
242-
Options.CookieName,
229+
Options.Cookie.Name,
243230
cookieValue,
244231
cookieOptions);
245232

@@ -283,14 +270,14 @@ public async virtual Task SignInAsync(ClaimsPrincipal user, AuthenticationProper
283270

284271
if (!signInContext.Properties.ExpiresUtc.HasValue)
285272
{
286-
signInContext.Properties.ExpiresUtc = issuedUtc.Add(Options.ExpireTimeSpan);
273+
signInContext.Properties.ExpiresUtc = issuedUtc.Add(Options.Cookie.Expiration ?? default(TimeSpan));
287274
}
288275

289276
await Events.SigningIn(signInContext);
290277

291278
if (signInContext.Properties.IsPersistent)
292279
{
293-
var expiresUtc = signInContext.Properties.ExpiresUtc ?? issuedUtc.Add(Options.ExpireTimeSpan);
280+
var expiresUtc = signInContext.Properties.ExpiresUtc ?? issuedUtc.Add(Options.Cookie.Expiration ?? default(TimeSpan));
294281
signInContext.CookieOptions.Expires = expiresUtc.ToUniversalTime();
295282
}
296283

@@ -314,7 +301,7 @@ public async virtual Task SignInAsync(ClaimsPrincipal user, AuthenticationProper
314301

315302
Options.CookieManager.AppendResponseCookie(
316303
Context,
317-
Options.CookieName,
304+
Options.Cookie.Name,
318305
cookieValue,
319306
signInContext.CookieOptions);
320307

@@ -359,7 +346,7 @@ public async virtual Task SignOutAsync(AuthenticationProperties properties)
359346

360347
Options.CookieManager.DeleteCookie(
361348
Context,
362-
Options.CookieName,
349+
Options.Cookie.Name,
363350
context.CookieOptions);
364351

365352
// Only redirect on the logout path

src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationOptions.cs

Lines changed: 124 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using Microsoft.AspNetCore.Authentication.Internal;
56
using Microsoft.AspNetCore.DataProtection;
67
using Microsoft.AspNetCore.Http;
78

@@ -12,85 +13,69 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
1213
/// </summary>
1314
public class CookieAuthenticationOptions : AuthenticationSchemeOptions
1415
{
15-
private string _cookieName;
16+
private CookieBuilder _cookieBuilder = new RequestPathBaseCookieBuilder
17+
{
18+
// the default name is configured in PostConfigureCookieAuthenticationOptions
19+
20+
// To support OAuth authentication, a lax mode is required, see https://github.com/aspnet/Security/issues/1231.
21+
SameSite = SameSiteMode.Lax,
22+
HttpOnly = true,
23+
SecurePolicy = CookieSecurePolicy.SameAsRequest,
24+
Expiration = TimeSpan.FromDays(14),
25+
};
1626

1727
/// <summary>
1828
/// Create an instance of the options initialized with the default values
1929
/// </summary>
2030
public CookieAuthenticationOptions()
2131
{
2232
ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
23-
ExpireTimeSpan = TimeSpan.FromDays(14);
2433
SlidingExpiration = true;
25-
// To support OAuth authentication, a lax mode is required, see https://github.com/aspnet/Security/issues/1231.
26-
CookieSameSite = SameSiteMode.Lax;
27-
CookieHttpOnly = true;
28-
CookieSecure = CookieSecurePolicy.SameAsRequest;
2934
Events = new CookieAuthenticationEvents();
3035
}
3136

3237
/// <summary>
33-
/// Determines the cookie name used to persist the identity. The default value is ".AspNetCore.Cookies".
38+
/// <para>
39+
/// Determines the settings used to create the cookie.
40+
/// </para>
41+
/// <para>
42+
/// <seealso cref="CookieBuilder.SameSite"/> defaults to <see cref="SameSiteMode.Lax"/>.
43+
/// <seealso cref="CookieBuilder.HttpOnly"/> defaults to <c>true</c>.
44+
/// <seealso cref="CookieBuilder.SecurePolicy"/> defaults to <see cref="CookieSecurePolicy.SameAsRequest"/>.
45+
/// <seealso cref="CookieBuilder.Expiration"/> defaults to 14 days.
46+
/// </para>
47+
/// </summary>
48+
/// <remarks>
49+
/// <para>
50+
/// The default value for cookie name is ".AspNetCore.Cookies".
3451
/// This value should be changed if you change the name of the AuthenticationScheme, especially if your
3552
/// system uses the cookie authentication handler multiple times.
36-
/// </summary>
37-
public string CookieName
53+
/// </para>
54+
/// <para>
55+
/// <seealso cref="CookieBuilder.SameSite"/> determines if the browser should allow the cookie to be attached to same-site or cross-site requests.
56+
/// The default is Lax, which means the cookie is only allowed to be attached to cross-site requests using safe HTTP methods and same-site requests.
57+
/// </para>
58+
/// <para>
59+
/// <seealso cref="CookieBuilder.HttpOnly"/> determines if the browser should allow the cookie to be accessed by client-side javascript.
60+
/// 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.
61+
/// </para>
62+
/// <para>
63+
/// <seealso cref="CookieBuilder.Expiration"/> controls how much time the cookie will remain valid from the point it is created. The expiration
64+
/// information is in the protected cookie ticket. Because of that an expired cookie will be ignored
65+
/// even if it is passed to the server after the browser should have purged it
66+
/// </para>
67+
/// </remarks>
68+
public CookieBuilder Cookie
3869
{
39-
get { return _cookieName; }
40-
set
41-
{
42-
if (value == null)
43-
{
44-
throw new ArgumentNullException(nameof(value));
45-
}
46-
47-
_cookieName = value;
48-
}
70+
get => _cookieBuilder;
71+
set => _cookieBuilder = value ?? throw new ArgumentNullException(nameof(value));
4972
}
5073

51-
/// <summary>
52-
/// Determines the domain used to create the cookie. Is not provided by default.
53-
/// </summary>
54-
public string CookieDomain { get; set; }
55-
56-
/// <summary>
57-
/// Determines the path used to create the cookie. The default value is "/" for highest browser compatibility.
58-
/// </summary>
59-
public string CookiePath { get; set; }
60-
61-
/// <summary>
62-
/// Determines if the browser should allow the cookie to be attached to same-site or cross-site requests. The
63-
/// default is Lax, which means the cookie is only allowed to be attached to cross-site requests using safe
64-
/// HTTP methods and same-site requests.
65-
/// </summary>
66-
public SameSiteMode CookieSameSite { get; set; }
67-
68-
/// <summary>
69-
/// Determines if the browser should allow the cookie to be accessed by client-side javascript. The
70-
/// default is true, which means the cookie will only be passed to http requests and is not made available
71-
/// to script on the page.
72-
/// </summary>
73-
public bool CookieHttpOnly { get; set; }
74-
75-
/// <summary>
76-
/// Determines if the cookie should only be transmitted on HTTPS request. The default is to limit the cookie
77-
/// to HTTPS requests if the page which is doing the SignIn is also HTTPS. If you have an HTTPS sign in page
78-
/// and portions of your site are HTTP you may need to change this value.
79-
/// </summary>
80-
public CookieSecurePolicy CookieSecure { get; set; }
81-
8274
/// <summary>
8375
/// If set this will be used by the CookieAuthenticationHandler for data protection.
8476
/// </summary>
8577
public IDataProtectionProvider DataProtectionProvider { get; set; }
8678

87-
/// <summary>
88-
/// Controls how much time the cookie will remain valid from the point it is created. The expiration
89-
/// information is in the protected cookie ticket. Because of that an expired cookie will be ignored
90-
/// even if it is passed to the server after the browser should have purged it
91-
/// </summary>
92-
public TimeSpan ExpireTimeSpan { get; set; }
93-
9479
/// <summary>
9580
/// The SlidingExpiration is set to true to instruct the handler to re-issue a new cookie with a new
9681
/// expiration time any time it processes a request which is more than halfway through the expiration window.
@@ -132,8 +117,8 @@ public string CookieName
132117
/// </summary>
133118
public new CookieAuthenticationEvents Events
134119
{
135-
get { return (CookieAuthenticationEvents)base.Events; }
136-
set { base.Events = value; }
120+
get => (CookieAuthenticationEvents)base.Events;
121+
set => base.Events = value;
137122
}
138123

139124
/// <summary>
@@ -154,5 +139,85 @@ public string CookieName
154139
/// to the client. This can be used to mitigate potential problems with very large identities.
155140
/// </summary>
156141
public ITicketStore SessionStore { get; set; }
142+
143+
#region Obsolete API
144+
/// <summary>
145+
/// <para>
146+
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.Name"/> on <see cref="Cookie"/>.
147+
/// </para>
148+
/// <para>
149+
/// Determines the cookie name used to persist the identity. The default value is ".AspNetCore.Cookies".
150+
/// This value should be changed if you change the name of the AuthenticationScheme, especially if your
151+
/// system uses the cookie authentication handler multiple times.
152+
/// </para>
153+
/// </summary>
154+
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.Domain) + ".")]
155+
public string CookieName { get => Cookie.Name; set => Cookie.Name = value; }
156+
157+
/// <summary>
158+
/// <para>
159+
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.Domain"/> on <see cref="Cookie"/>.
160+
/// </para>
161+
/// <para>
162+
/// Determines the domain used to create the cookie. Is not provided by default.
163+
/// </para>
164+
/// </summary>
165+
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.Domain) + ".")]
166+
public string CookieDomain { get => Cookie.Domain; set => Cookie.Domain = value; }
167+
168+
/// <summary>
169+
/// <para>
170+
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.Path"/> on <see cref="Cookie"/>.
171+
/// </para>
172+
/// <para>
173+
/// Determines the path used to create the cookie. The default value is "/" for highest browser compatibility.
174+
/// </para>
175+
/// </summary>
176+
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.Path) + ".")]
177+
public string CookiePath { get => Cookie.Path; set => Cookie.Path = value; }
178+
179+
/// <summary>
180+
/// <para>
181+
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.HttpOnly"/> on <see cref="Cookie"/>.
182+
/// </para>
183+
/// <para>
184+
/// Determines if the browser should allow the cookie to be accessed by client-side javascript. The
185+
/// default is true, which means the cookie will only be passed to http requests and is not made available
186+
/// to script on the page.
187+
/// </para>
188+
/// </summary>
189+
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.SameSite) + ".")]
190+
public bool CookieHttpOnly { get => Cookie.HttpOnly; set => Cookie.HttpOnly = value; }
191+
192+
/// <summary>
193+
/// <para>
194+
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.SecurePolicy"/> on <see cref="Cookie"/>.
195+
/// </para>
196+
/// <para>
197+
/// Determines if the cookie should only be transmitted on HTTPS request. The default is to limit the cookie
198+
/// to HTTPS requests if the page which is doing the SignIn is also HTTPS. If you have an HTTPS sign in page
199+
/// and portions of your site are HTTP you may need to change this value.
200+
/// </para>
201+
/// </summary>
202+
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.SecurePolicy) + ".")]
203+
public CookieSecurePolicy CookieSecure { get => Cookie.SecurePolicy; set => Cookie.SecurePolicy = value; }
204+
205+
/// <summary>
206+
/// <para>
207+
/// This property is obsolete and will be removed in a future version. The recommended alternative is <seealso cref="CookieBuilder.Expiration"/> on <see cref="Cookie"/>.
208+
/// </para>
209+
/// <para>
210+
/// Controls how much time the cookie will remain valid from the point it is created. The expiration
211+
/// information is in the protected cookie ticket. Because of that an expired cookie will be ignored
212+
/// even if it is passed to the server after the browser should have purged it
213+
/// </para>
214+
/// </summary>
215+
[Obsolete("This property is obsolete and will be removed in a future version. The recommended alternative is " + nameof(Cookie) + "." + nameof(CookieBuilder.Expiration) + ".")]
216+
public TimeSpan ExpireTimeSpan
217+
{
218+
get => Cookie.Expiration ?? default(TimeSpan);
219+
set => Cookie.Expiration = value;
220+
}
221+
#endregion
157222
}
158223
}

src/Microsoft.AspNetCore.Authentication.Cookies/Microsoft.AspNetCore.Authentication.Cookies.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@
1919
<ProjectReference Include="..\Microsoft.AspNetCore.Authentication\Microsoft.AspNetCore.Authentication.csproj" />
2020
</ItemGroup>
2121

22+
<ItemGroup>
23+
<Folder Include="Properties\" />
24+
</ItemGroup>
25+
2226
</Project>

src/Microsoft.AspNetCore.Authentication.Cookies/PostConfigureCookieAuthenticationOptions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ public void PostConfigure(string name, CookieAuthenticationOptions options)
2828
{
2929
options.DataProtectionProvider = options.DataProtectionProvider ?? _dp;
3030

31-
if (String.IsNullOrEmpty(options.CookieName))
31+
if (string.IsNullOrEmpty(options.Cookie.Name))
3232
{
33-
options.CookieName = CookieAuthenticationDefaults.CookiePrefix + name;
33+
options.Cookie.Name = CookieAuthenticationDefaults.CookiePrefix + name;
3434
}
3535
if (options.TicketDataFormat == null)
3636
{

0 commit comments

Comments
 (0)