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

[Prototype] Revisit the events model #1243

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f2187e9
Revisit the events model
kevinchalet May 20, 2017
6d73a64
Rename AuthenticationResult back to AuthenticateResult
kevinchalet Jun 10, 2017
038aedb
Rename BaseAuthenticationContext to AuthenticateResultContext
kevinchalet Jun 10, 2017
0ac9842
Rename BaseRemoteAuthenticationContext to RemoteAuthenticateResultCon…
kevinchalet Jun 10, 2017
ced1000
Rename BaseControlContext to HandleRequestContext
kevinchalet Jun 10, 2017
3e64d35
Remove BaseChallengeContext and BaseSignOutContext
kevinchalet Jun 10, 2017
98ed5c9
Move the Properties property to BaseContext
kevinchalet Jun 10, 2017
b3396ec
Rename FailureContext to RemoteFailureContext
kevinchalet Jun 10, 2017
0d4385b
Update RunTokenValidatedEventAsync() to avoid setting both the authen…
kevinchalet Jun 13, 2017
545006d
Fix the samples
kevinchalet Jun 13, 2017
4b7498a
Update AuthenticateResultContext/RemoteAuthenticateResultContext.Prop…
kevinchalet Jun 13, 2017
9d36b6a
Rename RemoteAuthenticationResult.HandleResponse() to Handle(), and S…
kevinchalet Jun 14, 2017
d8094e4
Remove CookieRedirectContext.Skip()/Skipped
kevinchalet Jun 14, 2017
f9f2283
Remove CookieSigningOutContext.Skip()/Skipped
kevinchalet Jun 14, 2017
ac7a3de
Update CookieSignedInContext/CookieSigningInContext to avoid inheriti…
kevinchalet Jun 14, 2017
4d1be28
Replace the AuthenticationSkipped flag by EventResultState
kevinchalet Jun 14, 2017
31fee74
Remove OAuthRedirectToAuthorizationContext.Skip()/Skipped
kevinchalet Jun 14, 2017
ce53b04
Use EventResultState.BypassDefaultLogic in OpenIdConnectHandler.Handl…
kevinchalet Jun 14, 2017
aa28c17
Remove RedirectContext.Skipped to use the State property
kevinchalet Jun 14, 2017
6c54bf4
Remove TwitterRedirectToAuthorizationEndpointContext.Skip()/Skipped
kevinchalet Jun 14, 2017
e72c8b5
Use EventResultState.BypassDefaultLogic in JwtBearerHandler.HandleCha…
kevinchalet Jun 14, 2017
b297452
Update SkipAuthentication()/RejectAuthentication() to nullify the aut…
kevinchalet Jun 15, 2017
576ab93
Fix JwtBearerTests.CustomHeaderReceived() to use CompleteAuthenticati…
kevinchalet Jun 15, 2017
2e98b62
Update CookieAuthenticationHandler.HandleAuthenticateAsync() to use I…
kevinchalet Jun 15, 2017
c600d30
Renew the authentication cookie before calling IsProcessingComplete()
kevinchalet Jun 15, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 173 additions & 0 deletions Security.sln

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion samples/JwtBearerSample/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public void ConfigureServices(IServiceCollection services)
{
OnAuthenticationFailed = c =>
{
c.HandleResponse();
c.SkipAuthentication();

c.Response.StatusCode = 500;
c.Response.ContentType = "text/plain";
Expand Down
2 changes: 1 addition & 1 deletion samples/OpenIdConnect.AzureAdSample/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public void ConfigureServices(IServiceCollection services)
var authContext = new AuthenticationContext(Authority, AuthPropertiesTokenCache.ForCodeRedemption(context.Properties));

var result = await authContext.AcquireTokenByAuthorizationCodeAsync(
context.ProtocolMessage.Code, new Uri(currentUri), credential, Resource);
context.AuthorizationResponse.Code, new Uri(currentUri), credential, Resource);

context.HandleCodeRedemption(result.AccessToken, result.IdToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,20 +155,25 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
return result;
}

var context = new CookieValidatePrincipalContext(Context, Scheme, result.Ticket, Options);
var context = new CookieValidatePrincipalContext(Context, Scheme, Options, result.Ticket);
await Events.ValidatePrincipal(context);

if (context.Principal == null)
if (context.ShouldRenew && context.Ticket != null)
{
return AuthenticateResult.Fail("No principal.");
RequestRefresh(context.Ticket);
}

if (context.ShouldRenew)
if (context.IsProcessingComplete(out var newResult))
{
RequestRefresh(result.Ticket);
return newResult;
}

return AuthenticateResult.Success(new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name));
if (context.Ticket == null)
{
return AuthenticateResult.None();
}

return AuthenticateResult.Success(context.Ticket);
}

private CookieOptions BuildCookieOptions()
Expand Down Expand Up @@ -252,13 +257,14 @@ protected override async Task HandleSignInAsync(ClaimsPrincipal user, Authentica
var result = await EnsureCookieTicket();
var cookieOptions = BuildCookieOptions();

var ticket = new AuthenticationTicket(user, properties, Scheme.Name);

var signInContext = new CookieSigningInContext(
Context,
Scheme,
Options,
user,
properties,
cookieOptions);
cookieOptions,
ticket);

DateTimeOffset issuedUtc;
if (signInContext.Properties.IssuedUtc.HasValue)
Expand All @@ -284,7 +290,8 @@ protected override async Task HandleSignInAsync(ClaimsPrincipal user, Authentica
signInContext.CookieOptions.Expires = expiresUtc.ToUniversalTime();
}

var ticket = new AuthenticationTicket(signInContext.Principal, signInContext.Properties, signInContext.AuthenticationScheme);
ticket = signInContext.Ticket;

if (Options.SessionStore != null)
{
if (_sessionKey != null)
Expand All @@ -311,9 +318,7 @@ protected override async Task HandleSignInAsync(ClaimsPrincipal user, Authentica
Context,
Scheme,
Options,
Scheme.Name,
signInContext.Principal,
signInContext.Properties);
signInContext.Ticket);

await Events.SignedIn(signedInContext);

Expand Down Expand Up @@ -380,7 +385,7 @@ private async Task ApplyHeaders(bool shouldRedirectToReturnUrl, AuthenticationPr
if (redirectUri != null)
{
await Events.RedirectToReturnUrl(
new CookieRedirectContext(Context, Scheme, Options, redirectUri, properties));
new CookieRedirectContext(Context, Scheme, Options, properties, redirectUri));
}
}
}
Expand All @@ -406,7 +411,7 @@ protected override async Task HandleForbiddenAsync(AuthenticationProperties prop
returnUrl = OriginalPathBase + Request.Path + Request.QueryString;
}
var accessDeniedUri = Options.AccessDeniedPath + QueryString.Create(Options.ReturnUrlParameter, returnUrl);
var redirectContext = new CookieRedirectContext(Context, Scheme, Options, BuildRedirectUri(accessDeniedUri), properties);
var redirectContext = new CookieRedirectContext(Context, Scheme, Options, properties, BuildRedirectUri(accessDeniedUri));
await Events.RedirectToAccessDenied(redirectContext);
}

Expand All @@ -419,7 +424,7 @@ protected override async Task HandleChallengeAsync(AuthenticationProperties prop
}

var loginUri = Options.LoginPath + QueryString.Create(Options.ReturnUrlParameter, redirectUri);
var redirectContext = new CookieRedirectContext(Context, Scheme, Options, BuildRedirectUri(loginUri), properties);
var redirectContext = new CookieRedirectContext(Context, Scheme, Options, properties, BuildRedirectUri(loginUri));
await Events.RedirectToLogin(redirectContext);
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <summary>
/// Context passed when a Challenge, SignIn, or SignOut causes a redirect in the cookie handler
/// </summary>
public class CookieRedirectContext : BaseCookieContext
public class CookieRedirectContext : BaseContext<CookieAuthenticationOptions>
{
/// <summary>
/// Creates a new context object.
Expand All @@ -20,9 +20,15 @@ public class CookieRedirectContext : BaseCookieContext
/// <param name="options">The cookie handler options</param>
/// <param name="redirectUri">The initial redirect URI</param>
/// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
public CookieRedirectContext(HttpContext context, AuthenticationScheme scheme, CookieAuthenticationOptions options, string redirectUri, AuthenticationProperties properties)
: base(context, scheme, options, properties)
public CookieRedirectContext(
HttpContext context,
AuthenticationScheme scheme,
CookieAuthenticationOptions options,
AuthenticationProperties properties,
string redirectUri)
: base(context, scheme, options)
{
Properties = properties;
RedirectUri = redirectUri;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,47 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <summary>
/// Context object passed to the ICookieAuthenticationEvents method SignedIn.
/// </summary>
public class CookieSignedInContext : BaseCookieContext
public class CookieSignedInContext : BaseContext<CookieAuthenticationOptions>
{
/// <summary>
/// Creates a new instance of the context object.
/// </summary>
/// <param name="context">The HTTP request context</param>
/// <param name="scheme">The scheme data</param>
/// <param name="options">The handler options</param>
/// <param name="authenticationScheme">Initializes AuthenticationScheme property</param>
/// <param name="principal">Initializes Principal property</param>
/// <param name="properties">Initializes Properties property</param>
/// <param name="ticket">Initializes Ticket property</param>
public CookieSignedInContext(
HttpContext context,
AuthenticationScheme scheme,
CookieAuthenticationOptions options,
string authenticationScheme,
ClaimsPrincipal principal,
AuthenticationProperties properties)
: base(context, scheme, options, properties)
AuthenticationTicket ticket)
: base(context, scheme, options)
{
Principal = principal;
Ticket = ticket;
}

/// <summary>
/// Contains the claims that were converted into the outgoing cookie.
/// Gets or set the <see cref="AuthenticationTicket"/> containing
/// the user principal and the authentication properties.
/// </summary>
public ClaimsPrincipal Principal { get; }
public AuthenticationTicket Ticket { get; set; }

/// <summary>
/// Gets the <see cref="ClaimsPrincipal"/> containing the user claims.
/// </summary>
public ClaimsPrincipal Principal => Ticket?.Principal;

public override AuthenticationProperties Properties
{
get => Ticket?.Properties;

set
{
if (Ticket != null)
{
Ticket = new AuthenticationTicket(Principal, value, Scheme.Name);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,56 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <summary>
/// Context object passed to the ICookieAuthenticationEvents method SigningIn.
/// </summary>
public class CookieSigningInContext : BaseCookieContext
public class CookieSigningInContext : BaseContext<CookieAuthenticationOptions>
{
/// <summary>
/// Creates a new instance of the context object.
/// </summary>
/// <param name="context">The HTTP request context</param>
/// <param name="scheme">The scheme data</param>
/// <param name="options">The handler options</param>
/// <param name="principal">Initializes Principal property</param>
/// <param name="properties">Initializes Extra property</param>
/// <param name="ticket">Initializes Ticket property</param>
/// <param name="cookieOptions">Initializes options for the authentication cookie.</param>
public CookieSigningInContext(
HttpContext context,
AuthenticationScheme scheme,
CookieAuthenticationOptions options,
ClaimsPrincipal principal,
AuthenticationProperties properties,
CookieOptions cookieOptions)
: base(context, scheme, options, properties)
CookieOptions cookieOptions,
AuthenticationTicket ticket)
: base(context, scheme, options)
{
Principal = principal;
CookieOptions = cookieOptions;
Ticket = ticket;
}

/// <summary>
/// Contains the claims about to be converted into the outgoing cookie.
/// May be replaced or altered during the SigningIn call.
/// </summary>
public ClaimsPrincipal Principal { get; set; }

/// <summary>
/// The options for creating the outgoing cookie.
/// May be replace or altered during the SigningIn call.
/// </summary>
public CookieOptions CookieOptions { get; set; }

/// <summary>
/// Gets or set the <see cref="AuthenticationTicket"/> containing
/// the user principal and the authentication properties.
/// </summary>
public AuthenticationTicket Ticket { get; set; }

/// <summary>
/// Gets the <see cref="ClaimsPrincipal"/> containing the user claims.
/// </summary>
public ClaimsPrincipal Principal => Ticket?.Principal;

public override AuthenticationProperties Properties
{
get => Ticket?.Properties;

set
{
if (Ticket != null)
{
Ticket = new AuthenticationTicket(Principal, value, Scheme.Name);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <summary>
/// Context object passed to the ICookieAuthenticationEvents method SigningOut
/// </summary>
public class CookieSigningOutContext : BaseCookieContext
public class CookieSigningOutContext : BaseContext<CookieAuthenticationOptions>
{
/// <summary>
///
Expand All @@ -24,8 +24,9 @@ public CookieSigningOutContext(
CookieAuthenticationOptions options,
AuthenticationProperties properties,
CookieOptions cookieOptions)
: base(context, scheme, options, properties)
: base(context, scheme, options)
{
Properties = properties;
CookieOptions = cookieOptions;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <summary>
/// Context object passed to the CookieAuthenticationEvents ValidatePrincipal method.
/// </summary>
public class CookieValidatePrincipalContext : BaseCookieContext
public class CookieValidatePrincipalContext : AuthenticateResultContext<CookieAuthenticationOptions>
{
/// <summary>
/// Creates a new instance of the context object.
Expand All @@ -19,55 +19,19 @@ public class CookieValidatePrincipalContext : BaseCookieContext
/// <param name="scheme"></param>
/// <param name="ticket">Contains the initial values for identity and extra data</param>
/// <param name="options"></param>
public CookieValidatePrincipalContext(HttpContext context, AuthenticationScheme scheme, AuthenticationTicket ticket, CookieAuthenticationOptions options)
: base(context, scheme, options, ticket?.Properties)
public CookieValidatePrincipalContext(
HttpContext context,
AuthenticationScheme scheme,
CookieAuthenticationOptions options,
AuthenticationTicket ticket)
: base(context, scheme, options)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}

if (ticket == null)
{
throw new ArgumentNullException(nameof(ticket));
}

if (options == null)
{
throw new ArgumentNullException(nameof(options));
}

Principal = ticket.Principal;
Ticket = ticket;
}

/// <summary>
/// Contains the claims principal arriving with the request. May be altered to change the
/// details of the authenticated user.
/// </summary>
public ClaimsPrincipal Principal { get; private set; }

/// <summary>
/// If true, the cookie will be renewed
/// </summary>
public bool ShouldRenew { get; set; }

/// <summary>
/// Called to replace the claims principal. The supplied principal will replace the value of the
/// Principal property, which determines the identity of the authenticated request.
/// </summary>
/// <param name="principal">The <see cref="ClaimsPrincipal"/> used as the replacement</param>
public void ReplacePrincipal(ClaimsPrincipal principal)
{
Principal = principal;
}

/// <summary>
/// Called to reject the incoming principal. 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.
/// </summary>
public void RejectPrincipal()
{
Principal = null;
}
}
}
Loading