-
Notifications
You must be signed in to change notification settings - Fork 190
Add defaults + split SignIn/SignOut #873
Changes from all commits
8bf0bdc
0d92b28
f8a2cfa
cd17a22
2a2b27e
25fcbb5
45c82a3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System.Security.Claims; | ||
using System.Threading.Tasks; | ||
|
||
namespace Microsoft.AspNetCore.Authentication | ||
{ | ||
/// <summary> | ||
/// Used to determine if a handler supports SignIn. | ||
/// </summary> | ||
public interface IAuthenticationSignInHandler : IAuthenticationSignOutHandler | ||
{ | ||
/// <summary> | ||
/// Handle sign in. | ||
/// </summary> | ||
/// <param name="user">The <see cref="ClaimsPrincipal"/> user.</param> | ||
/// <param name="properties">The <see cref="AuthenticationProperties"/> that contains the extra meta-data arriving with the authentication.</param> | ||
/// <returns>A task.</returns> | ||
Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System.Threading.Tasks; | ||
|
||
namespace Microsoft.AspNetCore.Authentication | ||
{ | ||
/// <summary> | ||
/// Used to determine if a handler supports SignOut. | ||
/// </summary> | ||
public interface IAuthenticationSignOutHandler : IAuthenticationHandler | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the derivation? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We require every handler to implement authenticate/challenge/forbid at a minimum, derivation makes this clearer, if we didn't require this, wouldn't that lead ppl to think they could only implement SignOut and use their handler? |
||
{ | ||
/// <summary> | ||
/// Signout behavior. | ||
/// </summary> | ||
/// <param name="properties">The <see cref="AuthenticationProperties"/> that contains the extra meta-data arriving with the authentication.</param> | ||
/// <returns>A task.</returns> | ||
Task SignOutAsync(AuthenticationProperties properties); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -4,7 +4,6 @@ | |||
using System; | ||||
using System.Collections.Generic; | ||||
using System.Linq; | ||||
using System.Reflection; | ||||
using System.Threading.Tasks; | ||||
using Microsoft.AspNetCore.Http; | ||||
using Microsoft.Extensions.Options; | ||||
|
@@ -36,14 +35,16 @@ public AuthenticationSchemeProvider(IOptions<AuthenticationOptions> options) | |||
|
||||
private IDictionary<string, AuthenticationScheme> _map = new Dictionary<string, AuthenticationScheme>(StringComparer.Ordinal); | ||||
private List<AuthenticationScheme> _requestHandlers = new List<AuthenticationScheme>(); | ||||
private List<AuthenticationScheme> _signOutHandlers = new List<AuthenticationScheme>(); | ||||
private List<AuthenticationScheme> _signInHandlers = new List<AuthenticationScheme>(); | ||||
|
||||
/// <summary> | ||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.AuthenticateAsync(HttpContext, string)"/>. | ||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultAuthenticateScheme"/>. | ||||
/// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned. | ||||
/// </summary> | ||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.AuthenticateAsync(HttpContext, string)"/>.</returns> | ||||
public Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync() | ||||
public virtual Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync() | ||||
{ | ||||
if (_options.DefaultAuthenticateScheme != null) | ||||
{ | ||||
|
@@ -59,20 +60,16 @@ public Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync() | |||
/// <summary> | ||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.ChallengeAsync(HttpContext, string, AuthenticationProperties)"/>. | ||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultChallengeScheme"/>. | ||||
/// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned. | ||||
/// Otherwise, this will fallback to <see cref="GetDefaultAuthenticateSchemeAsync"/>. | ||||
/// </summary> | ||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.ChallengeAsync(HttpContext, string, AuthenticationProperties)"/>.</returns> | ||||
public Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync() | ||||
public virtual Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync() | ||||
{ | ||||
if (_options.DefaultChallengeScheme != null) | ||||
{ | ||||
return GetSchemeAsync(_options.DefaultChallengeScheme); | ||||
} | ||||
if (_map.Count == 1) | ||||
{ | ||||
return Task.FromResult(_map.Values.First()); | ||||
} | ||||
return Task.FromResult<AuthenticationScheme>(null); | ||||
return GetDefaultAuthenticateSchemeAsync(); | ||||
} | ||||
|
||||
/// <summary> | ||||
|
@@ -81,7 +78,7 @@ public Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync() | |||
/// Otherwise, this will fallback to <see cref="GetDefaultChallengeSchemeAsync"/> . | ||||
/// </summary> | ||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.ForbidAsync(HttpContext, string, AuthenticationProperties)"/>.</returns> | ||||
public Task<AuthenticationScheme> GetDefaultForbidSchemeAsync() | ||||
public virtual Task<AuthenticationScheme> GetDefaultForbidSchemeAsync() | ||||
{ | ||||
if (_options.DefaultForbidScheme != null) | ||||
{ | ||||
|
@@ -93,34 +90,40 @@ public Task<AuthenticationScheme> GetDefaultForbidSchemeAsync() | |||
/// <summary> | ||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.SignInAsync(HttpContext, string, System.Security.Claims.ClaimsPrincipal, AuthenticationProperties)"/>. | ||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultSignInScheme"/>. | ||||
/// Otherwise, if only a single scheme exists, that will be used, if more than one exists, null will be returned. | ||||
/// If only a single sign in handler scheme exists, that will be used, if more than one exists, | ||||
/// this will fallback to <see cref="GetDefaultAuthenticateSchemeAsync"/>. | ||||
/// </summary> | ||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.SignInAsync(HttpContext, string, System.Security.Claims.ClaimsPrincipal, AuthenticationProperties)"/>.</returns> | ||||
public Task<AuthenticationScheme> GetDefaultSignInSchemeAsync() | ||||
public virtual Task<AuthenticationScheme> GetDefaultSignInSchemeAsync() | ||||
{ | ||||
if (_options.DefaultSignInScheme != null) | ||||
{ | ||||
return GetSchemeAsync(_options.DefaultSignInScheme); | ||||
} | ||||
if (_map.Count == 1) | ||||
if (_signInHandlers.Count == 1) | ||||
{ | ||||
return Task.FromResult(_map.Values.First()); | ||||
return Task.FromResult(_signInHandlers[0]); | ||||
} | ||||
return Task.FromResult<AuthenticationScheme>(null); | ||||
return GetDefaultAuthenticateSchemeAsync(); | ||||
} | ||||
|
||||
/// <summary> | ||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.SignOutAsync(HttpContext, string, AuthenticationProperties)"/>. | ||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultSignOutScheme"/>. | ||||
/// Otherwise, this will fallback to <see cref="GetDefaultSignInSchemeAsync"/> . | ||||
/// If only a single sign out handler scheme exists, that will be used, if more than one exists, | ||||
/// this will fallback to <see cref="GetDefaultSignInSchemeAsync"/> if that supoorts sign out. | ||||
/// </summary> | ||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.SignOutAsync(HttpContext, string, AuthenticationProperties)"/>.</returns> | ||||
public Task<AuthenticationScheme> GetDefaultSignOutSchemeAsync() | ||||
public virtual Task<AuthenticationScheme> GetDefaultSignOutSchemeAsync() | ||||
{ | ||||
if (_options.DefaultSignOutScheme != null) | ||||
{ | ||||
return GetSchemeAsync(_options.DefaultSignOutScheme); | ||||
} | ||||
if (_signOutHandlers.Count == 1) | ||||
{ | ||||
return Task.FromResult(_signOutHandlers[0]); | ||||
} | ||||
return GetDefaultSignInSchemeAsync(); | ||||
} | ||||
|
||||
|
@@ -129,7 +132,7 @@ public Task<AuthenticationScheme> GetDefaultSignOutSchemeAsync() | |||
/// </summary> | ||||
/// <param name="name">The name of the authenticationScheme.</param> | ||||
/// <returns>The scheme or null if not found.</returns> | ||||
public Task<AuthenticationScheme> GetSchemeAsync(string name) | ||||
public virtual Task<AuthenticationScheme> GetSchemeAsync(string name) | ||||
{ | ||||
if (_map.ContainsKey(name)) | ||||
{ | ||||
|
@@ -142,7 +145,7 @@ public Task<AuthenticationScheme> GetSchemeAsync(string name) | |||
/// Returns the schemes in priority order for request handling. | ||||
/// </summary> | ||||
/// <returns>The schemes in priority order for request handling</returns> | ||||
public Task<IEnumerable<AuthenticationScheme>> GetRequestHandlerSchemesAsync() | ||||
public virtual Task<IEnumerable<AuthenticationScheme>> GetRequestHandlerSchemesAsync() | ||||
{ | ||||
return Task.FromResult<IEnumerable<AuthenticationScheme>>(_requestHandlers); | ||||
} | ||||
|
@@ -151,7 +154,7 @@ public Task<IEnumerable<AuthenticationScheme>> GetRequestHandlerSchemesAsync() | |||
/// Registers a scheme for use by <see cref="IAuthenticationService"/>. | ||||
/// </summary> | ||||
/// <param name="scheme">The scheme.</param> | ||||
public void AddScheme(AuthenticationScheme scheme) | ||||
public virtual void AddScheme(AuthenticationScheme scheme) | ||||
{ | ||||
if (_map.ContainsKey(scheme.Name)) | ||||
{ | ||||
|
@@ -167,6 +170,14 @@ public void AddScheme(AuthenticationScheme scheme) | |||
{ | ||||
_requestHandlers.Add(scheme); | ||||
} | ||||
if (typeof(IAuthenticationSignInHandler).IsAssignableFrom(scheme.HandlerType)) | ||||
{ | ||||
_signInHandlers.Add(scheme); | ||||
} | ||||
if (typeof(IAuthenticationSignOutHandler).IsAssignableFrom(scheme.HandlerType)) | ||||
{ | ||||
_signOutHandlers.Add(scheme); | ||||
} | ||||
_map[scheme.Name] = scheme; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no check that the HandlerType actually implements IAuthenticationHandler, which the doc comments say is required. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's done in the scheme itself, HttpAbstractions/src/Microsoft.AspNetCore.Authentication.Abstractions/AuthenticationScheme.cs Line 31 in 88a797c
|
||||
} | ||||
} | ||||
|
@@ -175,7 +186,7 @@ public void AddScheme(AuthenticationScheme scheme) | |||
/// Removes a scheme, preventing it from being used by <see cref="IAuthenticationService"/>. | ||||
/// </summary> | ||||
/// <param name="name">The name of the authenticationScheme being removed.</param> | ||||
public void RemoveScheme(string name) | ||||
public virtual void RemoveScheme(string name) | ||||
{ | ||||
if (!_map.ContainsKey(name)) | ||||
{ | ||||
|
@@ -186,15 +197,15 @@ public void RemoveScheme(string name) | |||
if (_map.ContainsKey(name)) | ||||
{ | ||||
var scheme = _map[name]; | ||||
_requestHandlers.Remove(_requestHandlers.Where(s => s.Name == name).FirstOrDefault()); | ||||
_requestHandlers.Remove(scheme); | ||||
_signInHandlers.Remove(scheme); | ||||
_signOutHandlers.Remove(scheme); | ||||
_map.Remove(name); | ||||
} | ||||
} | ||||
} | ||||
|
||||
public Task<IEnumerable<AuthenticationScheme>> GetAllSchemesAsync() | ||||
{ | ||||
return Task.FromResult<IEnumerable<AuthenticationScheme>>(_map.Values); | ||||
} | ||||
public virtual Task<IEnumerable<AuthenticationScheme>> GetAllSchemesAsync() | ||||
=> Task.FromResult<IEnumerable<AuthenticationScheme>>(_map.Values); | ||||
} | ||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Tratcher how about we keep this None, but call it NoResult() on the ResultContext's that will get exposed to events?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would leave you with a method and property that have the same name. NoResult is fine here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are currently called Nothing and None(), I just don't see much benefit renaming None => NoResult as we do have usages in the code internally already today (i.e. Identity), we can keep NoResult on ResultContext so the public API for events is still the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NoResult() and None are better than None() and Nothing.