diff --git a/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationHandler.cs b/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationHandler.cs index 1f2b395b1..89821ac01 100644 --- a/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationHandler.cs +++ b/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationHandler.cs @@ -27,6 +27,8 @@ internal class CookieAuthenticationHandler : AuthenticationHandler _readCookieTask; + private CookieAuthenticationEvents Events => Options.Events.ResolveEvents(Context.RequestServices); + private Task EnsureCookieTicket() { // We only need to read the ticket once @@ -127,7 +129,7 @@ protected override async Task HandleAuthenticateAsync() } var context = new CookieValidatePrincipalContext(Context, result.Ticket, Options); - await Options.Events.ValidatePrincipal(context); + await Events.ValidatePrincipal(context); if (context.Principal == null) { @@ -244,7 +246,7 @@ protected override async Task HandleSignInAsync(SignInContext signin) signInContext.Properties.ExpiresUtc = issuedUtc.Add(Options.ExpireTimeSpan); } - await Options.Events.SigningIn(signInContext); + await Events.SigningIn(signInContext); if (signInContext.Properties.IsPersistent) { @@ -282,7 +284,7 @@ protected override async Task HandleSignInAsync(SignInContext signin) signInContext.Principal, signInContext.Properties); - await Options.Events.SignedIn(signedInContext); + await Events.SignedIn(signedInContext); // Only redirect on the login path var shouldRedirect = Options.LoginPath.HasValue && OriginalPath == Options.LoginPath; @@ -305,7 +307,7 @@ protected override async Task HandleSignOutAsync(SignOutContext signOutContext) new AuthenticationProperties(signOutContext.Properties), cookieOptions); - await Options.Events.SigningOut(context); + await Events.SigningOut(context); Options.CookieManager.DeleteCookie( Context, @@ -343,7 +345,7 @@ private async Task ApplyHeaders(bool shouldRedirectToReturnUrl, AuthenticationPr if (redirectUri != null) { - await Options.Events.RedirectToReturnUrl( + await Events.RedirectToReturnUrl( new CookieRedirectContext(Context, Options, redirectUri, properties)); } } @@ -372,7 +374,7 @@ protected override async Task HandleForbiddenAsync(ChallengeContext contex } var accessDeniedUri = Options.AccessDeniedPath + QueryString.Create(Options.ReturnUrlParameter, returnUrl); var redirectContext = new CookieRedirectContext(Context, Options, BuildRedirectUri(accessDeniedUri), properties); - await Options.Events.RedirectToAccessDenied(redirectContext); + await Events.RedirectToAccessDenied(redirectContext); return true; } @@ -392,7 +394,7 @@ protected override async Task HandleUnauthorizedAsync(ChallengeContext con var loginUri = Options.LoginPath + QueryString.Create(Options.ReturnUrlParameter, redirectUri); var redirectContext = new CookieRedirectContext(Context, Options, BuildRedirectUri(loginUri), properties); - await Options.Events.RedirectToLogin(redirectContext); + await Events.RedirectToLogin(redirectContext); return true; } diff --git a/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationMiddleware.cs b/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationMiddleware.cs index 14d152a81..14055c91b 100644 --- a/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationMiddleware.cs @@ -18,7 +18,8 @@ public CookieAuthenticationMiddleware( IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, UrlEncoder urlEncoder, - IOptions options) + IOptions options, + IServiceProvider services) : base(next, options, loggerFactory, urlEncoder) { if (dataProtectionProvider == null) diff --git a/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationOptions.cs b/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationOptions.cs index b42561250..5781b514d 100644 --- a/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Cookies/CookieAuthenticationOptions.cs @@ -128,7 +128,10 @@ public string CookieName /// calls methods on the provider which give the application control at certain points where processing is occurring. /// If it is not provided a default instance is supplied which does nothing when the methods are called. /// - public ICookieAuthenticationEvents Events { get; set; } + public new CookieAuthenticationEvents Events { + get { return (CookieAuthenticationEvents)base.Events; } + set { base.Events = value; } + } /// /// The TicketDataFormat is used to protect and unprotect the identity and other properties which are stored in the diff --git a/src/Microsoft.AspNetCore.Authentication.Cookies/Events/CookieAuthenticationEvents.cs b/src/Microsoft.AspNetCore.Authentication.Cookies/Events/CookieAuthenticationEvents.cs index 4364a2e54..f772eed1a 100644 --- a/src/Microsoft.AspNetCore.Authentication.Cookies/Events/CookieAuthenticationEvents.cs +++ b/src/Microsoft.AspNetCore.Authentication.Cookies/Events/CookieAuthenticationEvents.cs @@ -9,11 +9,11 @@ namespace Microsoft.AspNetCore.Authentication.Cookies { /// - /// This default implementation of the ICookieAuthenticationEvents may be used if the + /// This default implementation of the CookieAuthenticationEvents 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 CookieAuthenticationEvents : ICookieAuthenticationEvents + public class CookieAuthenticationEvents : AuthenticationEvents { /// /// A delegate assigned to this property will be invoked when the related method is called. @@ -155,5 +155,11 @@ private static bool IsAjaxRequest(HttpRequest request) /// /// Contains information about the event public virtual Task RedirectToAccessDenied(CookieRedirectContext context) => OnRedirectToAccessDenied(context); + + public new CookieAuthenticationEvents ResolveEvents(IServiceProvider services) + { + return base.ResolveEvents(services) as CookieAuthenticationEvents; + } + } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.Cookies/Events/ICookieAuthenticationEvents.cs b/src/Microsoft.AspNetCore.Authentication.Cookies/Events/ICookieAuthenticationEvents.cs deleted file mode 100644 index 1406d872d..000000000 --- a/src/Microsoft.AspNetCore.Authentication.Cookies/Events/ICookieAuthenticationEvents.cs +++ /dev/null @@ -1,64 +0,0 @@ -// 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.Cookies -{ - /// - /// Specifies callback methods which the invokes to enable developer control over the authentication process. /> - /// - public interface ICookieAuthenticationEvents - { - /// - /// Called each time a request principal has been validated by the middleware. By implementing this method the - /// application may alter or reject the principal which has arrived with the request. - /// - /// Contains information about the login session as well as the user . - /// A representing the completed operation. - Task ValidatePrincipal(CookieValidatePrincipalContext 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 . - Task SigningIn(CookieSigningInContext context); - - /// - /// Called when an endpoint has provided sign in information after it is converted into a cookie. - /// - /// Contains information about the login session as well as the user . - Task SignedIn(CookieSignedInContext context); - - /// - /// Called when a SignOut causes a redirect in the cookie middleware. - /// - /// Contains information about the event - Task RedirectToLogout(CookieRedirectContext context); - - /// - /// Called when a SignIn causes a redirect in the cookie middleware. - /// - /// Contains information about the event - Task RedirectToLogin(CookieRedirectContext context); - - /// - /// Called when redirecting back to the return url in the cookie middleware. - /// - /// Contains information about the event - Task RedirectToReturnUrl(CookieRedirectContext context); - - /// - /// Called when an access denied causes a redirect in the cookie middleware. - /// - /// Contains information about the event - Task RedirectToAccessDenied(CookieRedirectContext context); - - /// - /// Called during the sign-out flow to augment the cookie cleanup process. - /// - /// Contains information about the login session as well as information about the authentication cookie. - Task SigningOut(CookieSigningOutContext context); - } -} diff --git a/src/Microsoft.AspNetCore.Authentication.Facebook/FacebookHandler.cs b/src/Microsoft.AspNetCore.Authentication.Facebook/FacebookHandler.cs index be1c8f8f8..4de53fc95 100644 --- a/src/Microsoft.AspNetCore.Authentication.Facebook/FacebookHandler.cs +++ b/src/Microsoft.AspNetCore.Authentication.Facebook/FacebookHandler.cs @@ -1,7 +1,6 @@ // 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; using System.Globalization; using System.Net.Http; using System.Security.Claims; diff --git a/src/Microsoft.AspNetCore.Authentication.Facebook/FacebookMiddleware.cs b/src/Microsoft.AspNetCore.Authentication.Facebook/FacebookMiddleware.cs index ac57e8dde..b457ed689 100644 --- a/src/Microsoft.AspNetCore.Authentication.Facebook/FacebookMiddleware.cs +++ b/src/Microsoft.AspNetCore.Authentication.Facebook/FacebookMiddleware.cs @@ -27,14 +27,16 @@ public class FacebookMiddleware : OAuthMiddleware /// /// /// Configuration options for the middleware. + /// public FacebookMiddleware( RequestDelegate next, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, UrlEncoder encoder, IOptions sharedOptions, - IOptions options) - : base(next, dataProtectionProvider, loggerFactory, encoder, sharedOptions, options) + IOptions options, + IServiceProvider services) + : base(next, dataProtectionProvider, loggerFactory, encoder, sharedOptions, options, services) { if (next == null) { diff --git a/src/Microsoft.AspNetCore.Authentication.Google/GoogleMiddleware.cs b/src/Microsoft.AspNetCore.Authentication.Google/GoogleMiddleware.cs index 5f8afaff2..ea97a4501 100644 --- a/src/Microsoft.AspNetCore.Authentication.Google/GoogleMiddleware.cs +++ b/src/Microsoft.AspNetCore.Authentication.Google/GoogleMiddleware.cs @@ -26,14 +26,16 @@ public class GoogleMiddleware : OAuthMiddleware /// /// /// Configuration options for the middleware. + /// public GoogleMiddleware( RequestDelegate next, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, UrlEncoder encoder, IOptions sharedOptions, - IOptions options) - : base(next, dataProtectionProvider, loggerFactory, encoder, sharedOptions, options) + IOptions options, + IServiceProvider services) + : base(next, dataProtectionProvider, loggerFactory, encoder, sharedOptions, options, services) { if (next == null) { diff --git a/src/Microsoft.AspNetCore.Authentication.JwtBearer/Events/IJwtBearerEvents.cs b/src/Microsoft.AspNetCore.Authentication.JwtBearer/Events/IJwtBearerEvents.cs deleted file mode 100644 index a7b8aeb55..000000000 --- a/src/Microsoft.AspNetCore.Authentication.JwtBearer/Events/IJwtBearerEvents.cs +++ /dev/null @@ -1,33 +0,0 @@ -// 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.JwtBearer -{ - /// - /// Specifies events which the invokes to enable developer control over the authentication process. - /// - public interface IJwtBearerEvents - { - /// - /// Invoked if exceptions are thrown during request processing. The exceptions will be re-thrown after this event unless suppressed. - /// - Task AuthenticationFailed(AuthenticationFailedContext context); - - /// - /// Invoked when a protocol message is first received. - /// - Task MessageReceived(MessageReceivedContext context); - - /// - /// Invoked after the security token has passed validation and a ClaimsIdentity has been generated. - /// - Task TokenValidated(TokenValidatedContext context); - - /// - /// Invoked to apply a challenge sent back to the caller. - /// - Task Challenge(JwtBearerChallengeContext context); - } -} diff --git a/src/Microsoft.AspNetCore.Authentication.JwtBearer/Events/JwtBearerEvents.cs b/src/Microsoft.AspNetCore.Authentication.JwtBearer/Events/JwtBearerEvents.cs index 8ac1c3631..68c5e3c81 100644 --- a/src/Microsoft.AspNetCore.Authentication.JwtBearer/Events/JwtBearerEvents.cs +++ b/src/Microsoft.AspNetCore.Authentication.JwtBearer/Events/JwtBearerEvents.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer /// /// Specifies events which the invokes to enable developer control over the authentication process. /// - public class JwtBearerEvents : IJwtBearerEvents + public class JwtBearerEvents : AuthenticationEvents { /// /// Invoked if exceptions are thrown during request processing. The exceptions will be re-thrown after this event unless suppressed. @@ -39,5 +39,10 @@ public class JwtBearerEvents : IJwtBearerEvents public virtual Task TokenValidated(TokenValidatedContext context) => OnTokenValidated(context); public virtual Task Challenge(JwtBearerChallengeContext context) => OnChallenge(context); + + public new JwtBearerEvents ResolveEvents(IServiceProvider services) + { + return base.ResolveEvents(services) as JwtBearerEvents; + } } } diff --git a/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerHandler.cs b/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerHandler.cs index ee5575251..5128b8112 100644 --- a/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerHandler.cs +++ b/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerHandler.cs @@ -22,6 +22,8 @@ internal class JwtBearerHandler : AuthenticationHandler { private OpenIdConnectConfiguration _configuration; + private JwtBearerEvents Events => Options.Events.ResolveEvents(Context.RequestServices); + /// /// Searches the 'Authorization' header for a 'Bearer' token. If the 'Bearer' token is found, it is validated using set in the options. /// @@ -36,7 +38,7 @@ protected override async Task HandleAuthenticateAsync() var messageReceivedContext = new MessageReceivedContext(Context, Options); // event can set the token - await Options.Events.MessageReceived(messageReceivedContext); + await Events.MessageReceived(messageReceivedContext); if (messageReceivedContext.CheckEventResult(out result)) { return result; @@ -127,7 +129,7 @@ protected override async Task HandleAuthenticateAsync() SecurityToken = validatedToken, }; - await Options.Events.TokenValidated(tokenValidatedContext); + await Events.TokenValidated(tokenValidatedContext); if (tokenValidatedContext.CheckEventResult(out result)) { return result; @@ -153,7 +155,7 @@ protected override async Task HandleAuthenticateAsync() Exception = (validationFailures.Count == 1) ? validationFailures[0] : new AggregateException(validationFailures) }; - await Options.Events.AuthenticationFailed(authenticationFailedContext); + await Events.AuthenticationFailed(authenticationFailedContext); if (authenticationFailedContext.CheckEventResult(out result)) { return result; @@ -173,7 +175,7 @@ protected override async Task HandleAuthenticateAsync() Exception = ex }; - await Options.Events.AuthenticationFailed(authenticationFailedContext); + await Events.AuthenticationFailed(authenticationFailedContext); if (authenticationFailedContext.CheckEventResult(out result)) { return result; @@ -199,7 +201,7 @@ protected override async Task HandleUnauthorizedAsync(ChallengeContext con eventContext.ErrorDescription = CreateErrorDescription(eventContext.AuthenticateFailure); } - await Options.Events.Challenge(eventContext); + await Events.Challenge(eventContext); if (eventContext.HandledResponse) { return true; diff --git a/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerOptions.cs b/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerOptions.cs index 2aedf30d5..bda1f336d 100644 --- a/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerOptions.cs @@ -3,10 +3,8 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.IdentityModel.Tokens.Jwt; using System.Net.Http; -using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; @@ -63,7 +61,11 @@ public JwtBearerOptions() : base() /// The application may implement the interface fully, or it may create an instance of JwtBearerAuthenticationEvents /// and assign delegates only to the events it wants to process. /// - public IJwtBearerEvents Events { get; set; } = new JwtBearerEvents(); + public new JwtBearerEvents Events + { + get { return (JwtBearerEvents)base.Events; } + set { base.Events = value; } + } /// /// The HttpMessageHandler used to retrieve metadata. diff --git a/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountMiddleware.cs b/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountMiddleware.cs index 3ad1bf557..3a830addd 100644 --- a/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountMiddleware.cs +++ b/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountMiddleware.cs @@ -26,14 +26,16 @@ public class MicrosoftAccountMiddleware : OAuthMiddleware /// /// Configuration options for the middleware. + /// public MicrosoftAccountMiddleware( RequestDelegate next, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, UrlEncoder encoder, IOptions sharedOptions, - IOptions options) - : base(next, dataProtectionProvider, loggerFactory, encoder, sharedOptions, options) + IOptions options, + IServiceProvider services) + : base(next, dataProtectionProvider, loggerFactory, encoder, sharedOptions, options, services) { if (next == null) { diff --git a/src/Microsoft.AspNetCore.Authentication.OAuth/Events/IOAuthEvents.cs b/src/Microsoft.AspNetCore.Authentication.OAuth/Events/IOAuthEvents.cs deleted file mode 100644 index 29316732c..000000000 --- a/src/Microsoft.AspNetCore.Authentication.OAuth/Events/IOAuthEvents.cs +++ /dev/null @@ -1,27 +0,0 @@ -// 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.OAuth -{ - /// - /// Specifies callback methods which the invokes to enable developer control over the authentication process. - /// - public interface IOAuthEvents : IRemoteAuthenticationEvents - { - /// - /// Invoked after the provider successfully authenticates a user. This can be used to retrieve user information. - /// This event may not be invoked by sub-classes of OAuthAuthenticationHandler if they override CreateTicketAsync. - /// - /// Contains information about the login session. - /// A representing the completed operation. - Task CreatingTicket(OAuthCreatingTicketContext context); - - /// - /// Called when a Challenge causes a redirect to the authorize endpoint. - /// - /// Contains redirect URI and of the challenge. - Task RedirectToAuthorizationEndpoint(OAuthRedirectToAuthorizationContext context); - } -} diff --git a/src/Microsoft.AspNetCore.Authentication.OAuth/Events/OAuthEvents.cs b/src/Microsoft.AspNetCore.Authentication.OAuth/Events/OAuthEvents.cs index 066b324b7..bec040120 100644 --- a/src/Microsoft.AspNetCore.Authentication.OAuth/Events/OAuthEvents.cs +++ b/src/Microsoft.AspNetCore.Authentication.OAuth/Events/OAuthEvents.cs @@ -8,9 +8,9 @@ namespace Microsoft.AspNetCore.Authentication.OAuth { /// - /// Default implementation. + /// Default implementation. /// - public class OAuthEvents : RemoteAuthenticationEvents, IOAuthEvents + public class OAuthEvents : RemoteAuthenticationEvents { /// /// Gets or sets the function that is invoked when the CreatingTicket method is invoked. diff --git a/src/Microsoft.AspNetCore.Authentication.OAuth/OAuthMiddleware.cs b/src/Microsoft.AspNetCore.Authentication.OAuth/OAuthMiddleware.cs index 75139c1c8..e4c58ab00 100644 --- a/src/Microsoft.AspNetCore.Authentication.OAuth/OAuthMiddleware.cs +++ b/src/Microsoft.AspNetCore.Authentication.OAuth/OAuthMiddleware.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -27,14 +28,16 @@ namespace Microsoft.AspNetCore.Authentication.OAuth /// The . /// The configuration options for this middleware. /// Configuration options for the middleware. + /// public OAuthMiddleware( RequestDelegate next, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, UrlEncoder encoder, IOptions sharedOptions, - IOptions options) - : base(next, options, loggerFactory, encoder) + IOptions options, + IServiceProvider services) + : base(next, options, loggerFactory, encoder, services) { if (next == null) { diff --git a/src/Microsoft.AspNetCore.Authentication.OAuth/OAuthOptions.cs b/src/Microsoft.AspNetCore.Authentication.OAuth/OAuthOptions.cs index 9591d9c44..5cd3f61af 100644 --- a/src/Microsoft.AspNetCore.Authentication.OAuth/OAuthOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication.OAuth/OAuthOptions.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using System.ComponentModel; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.OAuth; using Microsoft.AspNetCore.Http.Authentication; @@ -47,11 +46,11 @@ public OAuthOptions() public string UserInformationEndpoint { get; set; } /// - /// Gets or sets the used to handle authentication events. + /// Gets or sets the used to handle authentication events. /// - public new IOAuthEvents Events + public new OAuthEvents Events { - get { return (IOAuthEvents)base.Events; } + get { return (OAuthEvents)base.Events; } set { base.Events = value; } } diff --git a/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/Events/IOpenIdConnectEvents.cs b/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/Events/IOpenIdConnectEvents.cs deleted file mode 100644 index 128fa08a3..000000000 --- a/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/Events/IOpenIdConnectEvents.cs +++ /dev/null @@ -1,58 +0,0 @@ -// 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.OpenIdConnect -{ - /// - /// Specifies events which the invokes to enable developer control over the authentication process. - /// - public interface IOpenIdConnectEvents : IRemoteAuthenticationEvents - { - /// - /// Invoked if exceptions are thrown during request processing. The exceptions will be re-thrown after this event unless suppressed. - /// - Task AuthenticationFailed(AuthenticationFailedContext context); - - /// - /// Invoked after security token validation if an authorization code is present in the protocol message. - /// - Task AuthorizationCodeReceived(AuthorizationCodeReceivedContext context); - - /// - /// Invoked when a protocol message is first received. - /// - Task MessageReceived(MessageReceivedContext context); - - /// - /// Invoked before redirecting to the identity provider to authenticate. - /// - Task RedirectToIdentityProvider(RedirectContext context); - - /// - /// Invoked before redirecting to the identity provider to sign out. - /// - Task RedirectToIdentityProviderForSignOut(RedirectContext context); - - /// - /// Invoked when a request is received on the RemoteSignOutPath. - /// - Task RemoteSignOut(RemoteSignOutContext context); - - /// - /// Invoked after "authorization code" is redeemed for tokens at the token endpoint. - /// - Task TokenResponseReceived(TokenResponseReceivedContext context); - - /// - /// Invoked when an IdToken has been validated and produced an AuthenticationTicket. - /// - Task TokenValidated(TokenValidatedContext context); - - /// - /// Invoked when user information is retrieved from the UserInfoEndpoint. - /// - Task UserInformationReceived(UserInformationReceivedContext context); - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/Events/OpenIdConnectEvents.cs b/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/Events/OpenIdConnectEvents.cs index f39b554ec..fc36d9dc2 100644 --- a/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/Events/OpenIdConnectEvents.cs +++ b/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/Events/OpenIdConnectEvents.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect /// /// Specifies events which the invokes to enable developer control over the authentication process. /// - public class OpenIdConnectEvents : RemoteAuthenticationEvents, IOpenIdConnectEvents + public class OpenIdConnectEvents : RemoteAuthenticationEvents { /// /// Invoked if exceptions are thrown during request processing. The exceptions will be re-thrown after this event unless suppressed. diff --git a/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/OpenIdConnectMiddleware.cs b/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/OpenIdConnectMiddleware.cs index 8d880d0d9..62e03f7c0 100644 --- a/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/OpenIdConnectMiddleware.cs +++ b/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/OpenIdConnectMiddleware.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Protocols; diff --git a/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/OpenIdConnectOptions.cs b/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/OpenIdConnectOptions.cs index f0b26f75b..af550a78b 100644 --- a/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/OpenIdConnectOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication.OpenIdConnect/OpenIdConnectOptions.cs @@ -102,11 +102,11 @@ public OpenIdConnectOptions(string authenticationScheme) public string MetadataAddress { get; set; } /// - /// Gets or sets the to notify when processing OpenIdConnect messages. + /// Gets or sets the to notify when processing OpenIdConnect messages. /// - public new IOpenIdConnectEvents Events + public new OpenIdConnectEvents Events { - get { return (IOpenIdConnectEvents)base.Events; } + get { return (OpenIdConnectEvents)base.Events; } set { base.Events = value; } } diff --git a/src/Microsoft.AspNetCore.Authentication.Twitter/Events/ITwitterEvents.cs b/src/Microsoft.AspNetCore.Authentication.Twitter/Events/ITwitterEvents.cs deleted file mode 100644 index 006fafc73..000000000 --- a/src/Microsoft.AspNetCore.Authentication.Twitter/Events/ITwitterEvents.cs +++ /dev/null @@ -1,26 +0,0 @@ -// 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.Twitter -{ - /// - /// Specifies callback methods which the invokes to enable developer control over the authentication process. /> - /// - public interface ITwitterEvents : IRemoteAuthenticationEvents - { - /// - /// Invoked whenever Twitter succesfully authenticates a user - /// - /// Contains information about the login session as well as the user . - /// A representing the completed operation. - Task CreatingTicket(TwitterCreatingTicketContext context); - - /// - /// Called when a Challenge causes a redirect to authorize endpoint in the Twitter middleware - /// - /// Contains redirect URI and of the challenge - Task RedirectToAuthorizationEndpoint(TwitterRedirectToAuthorizationEndpointContext context); - } -} diff --git a/src/Microsoft.AspNetCore.Authentication.Twitter/Events/TwitterEvents.cs b/src/Microsoft.AspNetCore.Authentication.Twitter/Events/TwitterEvents.cs index 033227542..d26055b81 100644 --- a/src/Microsoft.AspNetCore.Authentication.Twitter/Events/TwitterEvents.cs +++ b/src/Microsoft.AspNetCore.Authentication.Twitter/Events/TwitterEvents.cs @@ -8,9 +8,9 @@ namespace Microsoft.AspNetCore.Authentication.Twitter { /// - /// Default implementation. + /// Default implementation. /// - public class TwitterEvents : RemoteAuthenticationEvents, ITwitterEvents + public class TwitterEvents : RemoteAuthenticationEvents { /// /// Gets or sets the function that is invoked when the Authenticated method is invoked. diff --git a/src/Microsoft.AspNetCore.Authentication.Twitter/TwitterMiddleware.cs b/src/Microsoft.AspNetCore.Authentication.Twitter/TwitterMiddleware.cs index 67fb903dd..deff57aa3 100644 --- a/src/Microsoft.AspNetCore.Authentication.Twitter/TwitterMiddleware.cs +++ b/src/Microsoft.AspNetCore.Authentication.Twitter/TwitterMiddleware.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -29,14 +30,16 @@ public class TwitterMiddleware : AuthenticationMiddleware /// /// /// Configuration options for the middleware + /// public TwitterMiddleware( RequestDelegate next, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, UrlEncoder encoder, IOptions sharedOptions, - IOptions options) - : base(next, options, loggerFactory, encoder) + IOptions options, + IServiceProvider services) + : base(next, options, loggerFactory, encoder, services) { if (next == null) { @@ -85,6 +88,7 @@ public TwitterMiddleware( { Options.Events = new TwitterEvents(); } + if (Options.StateDataFormat == null) { var dataProtector = dataProtectionProvider.CreateProtector( diff --git a/src/Microsoft.AspNetCore.Authentication.Twitter/TwitterOptions.cs b/src/Microsoft.AspNetCore.Authentication.Twitter/TwitterOptions.cs index bf54b7fbb..73b9ed7a0 100644 --- a/src/Microsoft.AspNetCore.Authentication.Twitter/TwitterOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication.Twitter/TwitterOptions.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.ComponentModel; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Twitter; using Microsoft.AspNetCore.Http; @@ -52,11 +51,11 @@ public TwitterOptions() public ISecureDataFormat StateDataFormat { get; set; } /// - /// Gets or sets the used to handle authentication events. + /// Gets or sets the used to handle authentication events. /// - public new ITwitterEvents Events + public new TwitterEvents Events { - get { return (ITwitterEvents)base.Events; } + get { return (TwitterEvents)base.Events; } set { base.Events = value; } } } diff --git a/src/Microsoft.AspNetCore.Authentication/AuthenticationOptions.cs b/src/Microsoft.AspNetCore.Authentication/AuthenticationOptions.cs index 34ec577f1..35cbe49ba 100644 --- a/src/Microsoft.AspNetCore.Authentication/AuthenticationOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication/AuthenticationOptions.cs @@ -55,5 +55,10 @@ public string AuthenticationScheme /// [EditorBrowsable(EditorBrowsableState.Never)] public ISystemClock SystemClock { get; set; } = new SystemClock(); + + /// + /// Gets or sets the instance used to handle events. + /// + public AuthenticationEvents Events { get; set; } = new AuthenticationEvents(); } } diff --git a/src/Microsoft.AspNetCore.Authentication/Events/AuthenticationEvents.cs b/src/Microsoft.AspNetCore.Authentication/Events/AuthenticationEvents.cs new file mode 100644 index 000000000..60da6481b --- /dev/null +++ b/src/Microsoft.AspNetCore.Authentication/Events/AuthenticationEvents.cs @@ -0,0 +1,29 @@ +// 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; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Authentication +{ + /// + /// Base class for all authentication events. + /// + public class AuthenticationEvents + { + /// + /// If set, this will be used to query the service container for the EventType to use instead of this instance. + /// + public Type EventsType { get; set; } + + public AuthenticationEvents ResolveEvents(IServiceProvider services) + { + if (EventsType != null) + { + var events = services.GetRequiredService(EventsType) as AuthenticationEvents; + return events ?? this; + } + return this; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication/Events/IRemoteAuthenticationEvents.cs b/src/Microsoft.AspNetCore.Authentication/Events/IRemoteAuthenticationEvents.cs deleted file mode 100644 index e2109a065..000000000 --- a/src/Microsoft.AspNetCore.Authentication/Events/IRemoteAuthenticationEvents.cs +++ /dev/null @@ -1,20 +0,0 @@ -// 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 -{ - public interface IRemoteAuthenticationEvents - { - /// - /// Invoked when the remote authentication process has an error. - /// - Task RemoteFailure(FailureContext context); - - /// - /// Invoked before sign in. - /// - Task TicketReceived(TicketReceivedContext context); - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Authentication/Events/RemoteAuthenticationEvents.cs b/src/Microsoft.AspNetCore.Authentication/Events/RemoteAuthenticationEvents.cs index 6e7d6a35c..d50c09495 100644 --- a/src/Microsoft.AspNetCore.Authentication/Events/RemoteAuthenticationEvents.cs +++ b/src/Microsoft.AspNetCore.Authentication/Events/RemoteAuthenticationEvents.cs @@ -7,7 +7,7 @@ namespace Microsoft.AspNetCore.Authentication { - public class RemoteAuthenticationEvents : IRemoteAuthenticationEvents + public class RemoteAuthenticationEvents : AuthenticationEvents { public Func OnRemoteFailure { get; set; } = context => TaskCache.CompletedTask; diff --git a/src/Microsoft.AspNetCore.Authentication/RemoteAuthenticationOptions.cs b/src/Microsoft.AspNetCore.Authentication/RemoteAuthenticationOptions.cs index e990abd05..c6ac27efc 100644 --- a/src/Microsoft.AspNetCore.Authentication/RemoteAuthenticationOptions.cs +++ b/src/Microsoft.AspNetCore.Authentication/RemoteAuthenticationOptions.cs @@ -13,6 +13,11 @@ namespace Microsoft.AspNetCore.Builder /// public class RemoteAuthenticationOptions : AuthenticationOptions { + public RemoteAuthenticationOptions() + { + Events = new RemoteAuthenticationEvents(); + } + /// /// Gets or sets timeout value in milliseconds for back channel communications with the remote identity provider. /// @@ -56,7 +61,14 @@ public string DisplayName /// public TimeSpan RemoteAuthenticationTimeout { get; set; } = TimeSpan.FromMinutes(15); - public IRemoteAuthenticationEvents Events = new RemoteAuthenticationEvents(); + /// + /// Gets or sets the instance used to handle events. + /// + public new RemoteAuthenticationEvents Events + { + get { return (RemoteAuthenticationEvents)base.Events; } + set { base.Events = value; } + } /// /// Defines whether access and refresh tokens should be stored in the diff --git a/test/Microsoft.AspNetCore.Authentication.Test/Cookies/CookieMiddlewareTests.cs b/test/Microsoft.AspNetCore.Authentication.Test/Cookies/CookieMiddlewareTests.cs index e6f881fef..6a33312d3 100644 --- a/test/Microsoft.AspNetCore.Authentication.Test/Cookies/CookieMiddlewareTests.cs +++ b/test/Microsoft.AspNetCore.Authentication.Test/Cookies/CookieMiddlewareTests.cs @@ -441,6 +441,43 @@ public async Task CookieCanBeRejectedAndSignedOutByValidator() Assert.Null(FindClaimValue(transaction2, ClaimTypes.Name)); } + public class RejectEventType : CookieAuthenticationEvents + { + public RejectEventType() + { + OnValidatePrincipal = ctx => + { + ctx.RejectPrincipal(); + ctx.HttpContext.Authentication.SignOutAsync("Cookies"); + return Task.FromResult(0); + }; + } + } + + [Fact] + public async Task CookieEventsTypeUsedIfSet() + { + var clock = new TestClock(); + var options = new CookieAuthenticationOptions + { + SystemClock = clock, + ExpireTimeSpan = TimeSpan.FromMinutes(10), + SlidingExpiration = false + }; + + options.Events.EventsType = typeof(RejectEventType); + var server = CreateServer(options, + context => + context.Authentication.SignInAsync("Cookies", + new ClaimsPrincipal(new ClaimsIdentity(new GenericIdentity("Alice", "Cookies"))))); + + var transaction1 = await SendAsync(server, "http://example.com/testpath"); + + var transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue); + Assert.Contains(".AspNetCore.Cookies=; expires=", transaction2.SetCookie); + Assert.Null(FindClaimValue(transaction2, ClaimTypes.Name)); + } + [Fact] public async Task CookieCanBeRenewedByValidator() { @@ -1365,7 +1402,10 @@ private static TestServer CreateServer(CookieAuthenticationOptions options, Func } }); }) - .ConfigureServices(services => services.AddAuthentication()); + .ConfigureServices(services => { + services.AddAuthentication(); + services.AddScoped(); + }); var server = new TestServer(builder); server.BaseAddress = baseAddress; return server;