Refactor Events + Add IAuthenticationBuilder

This commit is contained in:
Hao Kung 2017-06-29 16:27:03 -07:00
Родитель e1cd8c9bc4
Коммит ff9f145a8e
95 изменённых файлов: 1746 добавлений и 1493 удалений

Просмотреть файл

@ -18,9 +18,7 @@ namespace CookieSample
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
});
services.AddCookieAuthentication();
}).AddCookie();
}
public void Configure(IApplicationBuilder app)

Просмотреть файл

@ -19,9 +19,7 @@ namespace CookieSessionSample
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
});
services.AddCookieAuthentication(o => o.SessionStore = new MemoryCacheTicketStore());
}).AddCookie(o => o.SessionStore = new MemoryCacheTicketStore());
}
public void Configure(IApplicationBuilder app)

Просмотреть файл

@ -48,9 +48,7 @@ namespace JwtBearerSample
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
});
services.AddJwtBearerAuthentication(o =>
}).AddJwtBearer(o =>
{
// You also need to update /wwwroot/app/scripts/app.js
o.Authority = Configuration["jwt:authority"];
@ -59,7 +57,7 @@ namespace JwtBearerSample
{
OnAuthenticationFailed = c =>
{
c.HandleResponse();
c.NoResult();
c.Response.StatusCode = 500;
c.Response.ContentType = "text/plain";

Просмотреть файл

@ -48,11 +48,9 @@ namespace OpenIdConnect.AzureAdSample
sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});
services.AddCookieAuthentication();
services.AddOpenIdConnectAuthentication(o =>
})
.AddCookie()
.AddOpenIdConnect(o =>
{
o.ClientId = ClientId;
o.ClientSecret = ClientSecret; // for code flow

Просмотреть файл

@ -45,11 +45,9 @@ namespace OpenIdConnectSample
sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});
services.AddCookieAuthentication();
services.AddOpenIdConnectAuthentication(o =>
})
.AddCookie()
.AddOpenIdConnect(o =>
{
o.ClientId = Configuration["oidc:clientid"];
o.ClientSecret = Configuration["oidc:clientsecret"]; // for code flow

Просмотреть файл

@ -55,13 +55,11 @@ namespace SocialSample
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
});
services.AddCookieAuthentication(o => o.LoginPath = new PathString("/login"));
// You must first create an app with Facebook and add its ID and Secret to your user-secrets.
// https://developers.facebook.com/apps/
services.AddFacebookAuthentication(o =>
})
.AddCookie(o => o.LoginPath = new PathString("/login"))
// You must first create an app with Facebook and add its ID and Secret to your user-secrets.
// https://developers.facebook.com/apps/
.AddFacebook(o =>
{
o.AppId = Configuration["facebook:appid"];
o.AppSecret = Configuration["facebook:appsecret"];
@ -69,11 +67,10 @@ namespace SocialSample
o.Fields.Add("name");
o.Fields.Add("email");
o.SaveTokens = true;
});
// You must first create an app with Google and add its ID and Secret to your user-secrets.
// https://console.developers.google.com/project
services.AddOAuthAuthentication("Google-AccessToken", o =>
})
// You must first create an app with Google and add its ID and Secret to your user-secrets.
// https://console.developers.google.com/project
.AddOAuth("Google-AccessToken", o =>
{
o.ClientId = Configuration["google:clientid"];
o.ClientSecret = Configuration["google:clientsecret"];
@ -84,11 +81,10 @@ namespace SocialSample
o.Scope.Add("profile");
o.Scope.Add("email");
o.SaveTokens = true;
});
// You must first create an app with Google and add its ID and Secret to your user-secrets.
// https://console.developers.google.com/project
services.AddGoogleAuthentication(o =>
})
// You must first create an app with Google and add its ID and Secret to your user-secrets.
// https://console.developers.google.com/project
.AddGoogle(o =>
{
o.ClientId = Configuration["google:clientid"];
o.ClientSecret = Configuration["google:clientsecret"];
@ -104,11 +100,10 @@ namespace SocialSample
};
o.ClaimActions.MapJsonSubKey("urn:google:image", "image", "url");
o.ClaimActions.Remove(ClaimTypes.GivenName);
});
// You must first create an app with Twitter and add its key and Secret to your user-secrets.
// https://apps.twitter.com/
services.AddTwitterAuthentication(o =>
})
// You must first create an app with Twitter and add its key and Secret to your user-secrets.
// https://apps.twitter.com/
.AddTwitter(o =>
{
o.ConsumerKey = Configuration["twitter:consumerkey"];
o.ConsumerSecret = Configuration["twitter:consumersecret"];
@ -126,15 +121,14 @@ namespace SocialSample
return Task.FromResult(0);
}
};
});
/* Azure AD app model v2 has restrictions that prevent the use of plain HTTP for redirect URLs.
Therefore, to authenticate through microsoft accounts, tryout the sample using the following URL:
https://localhost:44318/
*/
// You must first create an app with Microsoft Account and add its ID and Secret to your user-secrets.
// https://apps.dev.microsoft.com/
services.AddOAuthAuthentication("Microsoft-AccessToken", o =>
})
/* Azure AD app model v2 has restrictions that prevent the use of plain HTTP for redirect URLs.
Therefore, to authenticate through microsoft accounts, tryout the sample using the following URL:
https://localhost:44318/
*/
// You must first create an app with Microsoft Account and add its ID and Secret to your user-secrets.
// https://apps.dev.microsoft.com/
.AddOAuth("Microsoft-AccessToken", o =>
{
o.ClientId = Configuration["microsoftaccount:clientid"];
o.ClientSecret = Configuration["microsoftaccount:clientsecret"];
@ -143,20 +137,18 @@ namespace SocialSample
o.TokenEndpoint = MicrosoftAccountDefaults.TokenEndpoint;
o.Scope.Add("https://graph.microsoft.com/user.read");
o.SaveTokens = true;
});
// You must first create an app with Microsoft Account and add its ID and Secret to your user-secrets.
// https://azure.microsoft.com/en-us/documentation/articles/active-directory-v2-app-registration/
services.AddMicrosoftAccountAuthentication(o =>
})
// You must first create an app with Microsoft Account and add its ID and Secret to your user-secrets.
// https://azure.microsoft.com/en-us/documentation/articles/active-directory-v2-app-registration/
.AddMicrosoftAccount(o =>
{
o.ClientId = Configuration["microsoftaccount:clientid"];
o.ClientSecret = Configuration["microsoftaccount:clientsecret"];
o.SaveTokens = true;
});
// You must first create an app with GitHub and add its ID and Secret to your user-secrets.
// https://github.com/settings/applications/
services.AddOAuthAuthentication("GitHub-AccessToken", o =>
})
// You must first create an app with GitHub and add its ID and Secret to your user-secrets.
// https://github.com/settings/applications/
.AddOAuth("GitHub-AccessToken", o =>
{
o.ClientId = Configuration["github-token:clientid"];
o.ClientSecret = Configuration["github-token:clientsecret"];
@ -164,11 +156,10 @@ namespace SocialSample
o.AuthorizationEndpoint = "https://github.com/login/oauth/authorize";
o.TokenEndpoint = "https://github.com/login/oauth/access_token";
o.SaveTokens = true;
});
// You must first create an app with GitHub and add its ID and Secret to your user-secrets.
// https://github.com/settings/applications/
services.AddOAuthAuthentication("GitHub", o =>
})
// You must first create an app with GitHub and add its ID and Secret to your user-secrets.
// https://github.com/settings/applications/
.AddOAuth("GitHub", o =>
{
o.ClientId = Configuration["github:clientid"];
o.ClientSecret = Configuration["github:clientsecret"];

Просмотреть файл

@ -14,7 +14,10 @@ using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Authentication.Cookies
{
public class CookieAuthenticationHandler : AuthenticationHandler<CookieAuthenticationOptions>
public class CookieAuthenticationHandler :
AuthenticationHandler<CookieAuthenticationOptions>,
IAuthenticationSignInHandler,
IAuthenticationSignOutHandler
{
private const string HeaderValueNoCache = "no-cache";
private const string HeaderValueMinusOne = "-1";
@ -104,7 +107,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
var cookie = Options.CookieManager.GetRequestCookie(Context, Options.CookieName);
if (string.IsNullOrEmpty(cookie))
{
return AuthenticateResult.None();
return AuthenticateResult.NoResult();
}
var ticket = Options.TicketDataFormat.Unprotect(cookie, GetTlsTokenBinding());
@ -155,7 +158,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
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)
@ -244,8 +247,15 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
}
}
protected override async Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
public async virtual Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
properties = properties ?? new AuthenticationProperties();
_signInCalled = true;
// Process the request cookie to initialize members like _sessionKey.
@ -284,7 +294,8 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
signInContext.CookieOptions.Expires = expiresUtc.ToUniversalTime();
}
var ticket = new AuthenticationTicket(signInContext.Principal, signInContext.Properties, signInContext.AuthenticationScheme);
var ticket = new AuthenticationTicket(signInContext.Principal, signInContext.Properties, signInContext.Scheme.Name);
if (Options.SessionStore != null)
{
if (_sessionKey != null)
@ -310,20 +321,23 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
var signedInContext = new CookieSignedInContext(
Context,
Scheme,
Options,
Scheme.Name,
signInContext.Principal,
signInContext.Properties);
signInContext.Properties,
Options);
await Events.SignedIn(signedInContext);
// Only redirect on the login path
var shouldRedirect = Options.LoginPath.HasValue && OriginalPath == Options.LoginPath;
await ApplyHeaders(shouldRedirect, signedInContext.Properties);
Logger.SignedIn(Scheme.Name);
}
protected override async Task HandleSignOutAsync(AuthenticationProperties properties)
public async virtual Task SignOutAsync(AuthenticationProperties properties)
{
properties = properties ?? new AuthenticationProperties();
_signOutCalled = true;
// Process the request cookie to initialize members like _sessionKey.
@ -351,6 +365,8 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
// Only redirect on the logout path
var shouldRedirect = Options.LogoutPath.HasValue && OriginalPath == Options.LogoutPath;
await ApplyHeaders(shouldRedirect, context.Properties);
Logger.SignedOut(Scheme.Name);
}
private async Task ApplyHeaders(bool shouldRedirectToReturnUrl, AuthenticationProperties properties)
@ -380,7 +396,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
if (redirectUri != null)
{
await Events.RedirectToReturnUrl(
new CookieRedirectContext(Context, Scheme, Options, redirectUri, properties));
new RedirectContext<CookieAuthenticationOptions>(Context, Scheme, Options, properties, redirectUri));
}
}
}
@ -406,7 +422,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
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 RedirectContext<CookieAuthenticationOptions>(Context, Scheme, Options, properties, BuildRedirectUri(accessDeniedUri));
await Events.RedirectToAccessDenied(redirectContext);
}
@ -419,7 +435,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
}
var loginUri = Options.LoginPath + QueryString.Create(Options.ReturnUrlParameter, redirectUri);
var redirectContext = new CookieRedirectContext(Context, Scheme, Options, BuildRedirectUri(loginUri), properties);
var redirectContext = new RedirectContext<CookieAuthenticationOptions>(Context, Scheme, Options, properties, BuildRedirectUri(loginUri));
await Events.RedirectToLogin(redirectContext);
}

Просмотреть файл

@ -2,16 +2,32 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
{
public static class CookieExtensions
{
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder)
=> builder.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme);
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme)
=> builder.AddCookie(authenticationScheme, configureOptions: null);
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, Action<CookieAuthenticationOptions> configureOptions)
=> builder.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, configureOptions);
public static AuthenticationBuilder AddCookie(this AuthenticationBuilder builder, string authenticationScheme, Action<CookieAuthenticationOptions> configureOptions)
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>());
return builder.AddScheme<CookieAuthenticationOptions, CookieAuthenticationHandler>(authenticationScheme, configureOptions);
}
// REMOVE below once callers have been updated
public static IServiceCollection AddCookieAuthentication(this IServiceCollection services) => services.AddCookieAuthentication(CookieAuthenticationDefaults.AuthenticationScheme);
public static IServiceCollection AddCookieAuthentication(this IServiceCollection services, string authenticationScheme) => services.AddCookieAuthentication(authenticationScheme, configureOptions: null);

Просмотреть файл

@ -1,30 +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;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication.Cookies
{
public class BaseCookieContext : BaseAuthenticationContext
{
public BaseCookieContext(
HttpContext context,
AuthenticationScheme scheme,
CookieAuthenticationOptions options,
AuthenticationProperties properties)
: base(context, scheme.Name, properties)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
Options = options;
}
public CookieAuthenticationOptions Options { get; }
public AuthenticationScheme Scheme { get; }
}
}

Просмотреть файл

@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <summary>
/// A delegate assigned to this property will be invoked when the related method is called.
/// </summary>
public Func<CookieRedirectContext, Task> OnRedirectToLogin { get; set; } = context =>
public Func<RedirectContext<CookieAuthenticationOptions>, Task> OnRedirectToLogin { get; set; } = context =>
{
if (IsAjaxRequest(context.Request))
{
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <summary>
/// A delegate assigned to this property will be invoked when the related method is called.
/// </summary>
public Func<CookieRedirectContext, Task> OnRedirectToAccessDenied { get; set; } = context =>
public Func<RedirectContext<CookieAuthenticationOptions>, Task> OnRedirectToAccessDenied { get; set; } = context =>
{
if (IsAjaxRequest(context.Request))
{
@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <summary>
/// A delegate assigned to this property will be invoked when the related method is called.
/// </summary>
public Func<CookieRedirectContext, Task> OnRedirectToLogout { get; set; } = context =>
public Func<RedirectContext<CookieAuthenticationOptions>, Task> OnRedirectToLogout { get; set; } = context =>
{
if (IsAjaxRequest(context.Request))
{
@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <summary>
/// A delegate assigned to this property will be invoked when the related method is called.
/// </summary>
public Func<CookieRedirectContext, Task> OnRedirectToReturnUrl { get; set; } = context =>
public Func<RedirectContext<CookieAuthenticationOptions>, Task> OnRedirectToReturnUrl { get; set; } = context =>
{
if (IsAjaxRequest(context.Request))
{
@ -135,24 +135,24 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// Implements the interface method by invoking the related delegate method.
/// </summary>
/// <param name="context">Contains information about the event</param>
public virtual Task RedirectToLogout(CookieRedirectContext context) => OnRedirectToLogout(context);
public virtual Task RedirectToLogout(RedirectContext<CookieAuthenticationOptions> context) => OnRedirectToLogout(context);
/// <summary>
/// Implements the interface method by invoking the related delegate method.
/// </summary>
/// <param name="context">Contains information about the event</param>
public virtual Task RedirectToLogin(CookieRedirectContext context) => OnRedirectToLogin(context);
public virtual Task RedirectToLogin(RedirectContext<CookieAuthenticationOptions> context) => OnRedirectToLogin(context);
/// <summary>
/// Implements the interface method by invoking the related delegate method.
/// </summary>
/// <param name="context">Contains information about the event</param>
public virtual Task RedirectToReturnUrl(CookieRedirectContext context) => OnRedirectToReturnUrl(context);
public virtual Task RedirectToReturnUrl(RedirectContext<CookieAuthenticationOptions> context) => OnRedirectToReturnUrl(context);
/// <summary>
/// Implements the interface method by invoking the related delegate method.
/// </summary>
/// <param name="context">Contains information about the event</param>
public virtual Task RedirectToAccessDenied(CookieRedirectContext context) => OnRedirectToAccessDenied(context);
public virtual Task RedirectToAccessDenied(RedirectContext<CookieAuthenticationOptions> context) => OnRedirectToAccessDenied(context);
}
}

Просмотреть файл

@ -9,32 +9,25 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <summary>
/// Context object passed to the ICookieAuthenticationEvents method SignedIn.
/// </summary>
public class CookieSignedInContext : BaseCookieContext
public class CookieSignedInContext : PrincipalContext<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="options">The handler options</param>
public CookieSignedInContext(
HttpContext context,
AuthenticationScheme scheme,
CookieAuthenticationOptions options,
string authenticationScheme,
ClaimsPrincipal principal,
AuthenticationProperties properties)
AuthenticationProperties properties,
CookieAuthenticationOptions options)
: base(context, scheme, options, properties)
{
Principal = principal;
}
/// <summary>
/// Contains the claims that were converted into the outgoing cookie.
/// </summary>
public ClaimsPrincipal Principal { get; }
}
}

Просмотреть файл

@ -7,9 +7,9 @@ using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication.Cookies
{
/// <summary>
/// Context object passed to the ICookieAuthenticationEvents method SigningIn.
/// Context object passed to the <see cref="CookieAuthenticationEvents.SigningIn(CookieSigningInContext)"/>.
/// </summary>
public class CookieSigningInContext : BaseCookieContext
public class CookieSigningInContext : PrincipalContext<CookieAuthenticationOptions>
{
/// <summary>
/// Creates a new instance of the context object.
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <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="properties">The authentication properties.</param>
/// <param name="cookieOptions">Initializes options for the authentication cookie.</param>
public CookieSigningInContext(
HttpContext context,
@ -29,16 +29,10 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
CookieOptions cookieOptions)
: base(context, scheme, options, properties)
{
Principal = principal;
CookieOptions = cookieOptions;
Principal = principal;
}
/// <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.

Просмотреть файл

@ -6,9 +6,9 @@ using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication.Cookies
{
/// <summary>
/// Context object passed to the ICookieAuthenticationEvents method SigningOut
/// Context object passed to the <see cref="CookieAuthenticationEvents.SigningOut(CookieSigningOutContext)"/>
/// </summary>
public class CookieSigningOutContext : BaseCookieContext
public class CookieSigningOutContext : PropertiesContext<CookieAuthenticationOptions>
{
/// <summary>
///
@ -25,9 +25,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
AuthenticationProperties properties,
CookieOptions cookieOptions)
: base(context, scheme, options, properties)
{
CookieOptions = cookieOptions;
}
=> CookieOptions = cookieOptions;
/// <summary>
/// The options for creating the outgoing cookie.

Просмотреть файл

@ -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 : PrincipalContext<CookieAuthenticationOptions>
{
/// <summary>
/// Creates a new instance of the context object.
@ -19,33 +19,17 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// <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)
public CookieValidatePrincipalContext(HttpContext context, AuthenticationScheme scheme, CookieAuthenticationOptions options, AuthenticationTicket ticket)
: base(context, scheme, options, ticket?.Properties)
{
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;
}
/// <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>
@ -56,18 +40,12 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
/// 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;
}
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;
}
public void RejectPrincipal() => Principal = null;
}
}

Просмотреть файл

@ -0,0 +1,35 @@
// 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;
namespace Microsoft.Extensions.Logging
{
internal static class LoggingExtensions
{
private static Action<ILogger, string, Exception> _authSchemeSignedIn;
private static Action<ILogger, string, Exception> _authSchemeSignedOut;
static LoggingExtensions()
{
_authSchemeSignedIn = LoggerMessage.Define<string>(
eventId: 10,
logLevel: LogLevel.Information,
formatString: "AuthenticationScheme: {AuthenticationScheme} signed in.");
_authSchemeSignedOut = LoggerMessage.Define<string>(
eventId: 11,
logLevel: LogLevel.Information,
formatString: "AuthenticationScheme: {AuthenticationScheme} signed out.");
}
public static void SignedIn(this ILogger logger, string authenticationScheme)
{
_authSchemeSignedIn(logger, authenticationScheme, null);
}
public static void SignedOut(this ILogger logger, string authenticationScheme)
{
_authSchemeSignedOut(logger, authenticationScheme, null);
}
}
}

Просмотреть файл

@ -55,6 +55,5 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
options.AccessDeniedPath = CookieAuthenticationDefaults.AccessDeniedPath;
}
}
}
}

Просмотреть файл

@ -19,69 +19,29 @@
"TypeId": "public interface Microsoft.AspNetCore.Authentication.Cookies.ICookieAuthenticationEvents",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieValidatePrincipalContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationTicket ticket, Microsoft.AspNetCore.Builder.CookieAuthenticationOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieValidatePrincipalContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieSigningOutContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.CookieAuthenticationOptions options, Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties properties, Microsoft.AspNetCore.Http.CookieOptions cookieOptions)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieSigningOutContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieSigningOutContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"MemberId": "public System.Void set_Properties(Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties value)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieSignedInContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.CookieAuthenticationOptions options, System.String authenticationScheme, System.Security.Claims.ClaimsPrincipal principal, Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties properties)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieSignedInContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieSigningInContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.CookieAuthenticationOptions options, System.String authenticationScheme, System.Security.Claims.ClaimsPrincipal principal, Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties properties, Microsoft.AspNetCore.Http.CookieOptions cookieOptions)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieSigningInContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieSigningInContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"MemberId": "public System.Void set_Properties(Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties value)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieRedirectContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.CookieAuthenticationOptions options, System.String redirectUri, Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties properties)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieRedirectContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public static class Microsoft.AspNetCore.Builder.CookieAppBuilderExtensions",
"MemberId": "public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseCookieAuthentication(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Builder.CookieAuthenticationOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieRedirectContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieSignedInContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieSigningInContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieSigningOutContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Cookies.CookieValidatePrincipalContext : Microsoft.AspNetCore.Authentication.Cookies.BaseCookieContext",
"Kind": "Removal"
}
]

Просмотреть файл

@ -2,12 +2,24 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Facebook;
namespace Microsoft.Extensions.DependencyInjection
{
public static class FacebookAuthenticationOptionsExtensions
{
public static AuthenticationBuilder AddFacebook(this AuthenticationBuilder builder)
=> builder.AddFacebook(FacebookDefaults.AuthenticationScheme, _ => { });
public static AuthenticationBuilder AddFacebook(this AuthenticationBuilder builder, Action<FacebookOptions> configureOptions)
=> builder.AddFacebook(FacebookDefaults.AuthenticationScheme, configureOptions);
public static AuthenticationBuilder AddFacebook(this AuthenticationBuilder builder, string authenticationScheme, Action<FacebookOptions> configureOptions)
=> builder.AddOAuth<FacebookOptions, FacebookHandler>(authenticationScheme, configureOptions);
// REMOVE below once callers have been updated
public static IServiceCollection AddFacebookAuthentication(this IServiceCollection services)
=> services.AddFacebookAuthentication(FacebookDefaults.AuthenticationScheme, _ => { });

Просмотреть файл

@ -42,13 +42,13 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), properties, Scheme.Name);
var context = new OAuthCreatingTicketContext(ticket, Context, Scheme, Options, Backchannel, tokens, payload);
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload);
context.RunClaimActions();
await Events.CreatingTicket(context);
return context.Ticket;
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
}
private string GenerateAppSecretProof(string accessToken)

Просмотреть файл

@ -2,12 +2,25 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Google;
namespace Microsoft.Extensions.DependencyInjection
{
public static class GoogleExtensions
{
public static AuthenticationBuilder AddGoogle(this AuthenticationBuilder builder)
=> builder.AddGoogle(GoogleDefaults.AuthenticationScheme, _ => { });
public static AuthenticationBuilder AddGoogle(this AuthenticationBuilder builder, Action<GoogleOptions> configureOptions)
=> builder.AddGoogle(GoogleDefaults.AuthenticationScheme, configureOptions);
public static AuthenticationBuilder AddGoogle(this AuthenticationBuilder builder, string authenticationScheme, Action<GoogleOptions> configureOptions)
=> builder.AddOAuth<GoogleOptions, GoogleHandler>(authenticationScheme, configureOptions);
// REMOVE below once callers have been updated
public static IServiceCollection AddGoogleAuthentication(this IServiceCollection services)
=> services.AddGoogleAuthentication(GoogleDefaults.AuthenticationScheme, _ => { });

Просмотреть файл

@ -39,14 +39,11 @@ namespace Microsoft.AspNetCore.Authentication.Google
var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, properties, Scheme.Name);
var context = new OAuthCreatingTicketContext(ticket, Context, Scheme, Options, Backchannel, tokens, payload);
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload);
context.RunClaimActions();
await Events.CreatingTicket(context);
return context.Ticket;
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
}
// TODO: Abstract this properties override pattern into the base class?

Просмотреть файл

@ -6,12 +6,13 @@ using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication.JwtBearer
{
public class AuthenticationFailedContext : BaseJwtBearerContext
public class AuthenticationFailedContext : ResultContext<JwtBearerOptions>
{
public AuthenticationFailedContext(HttpContext context, AuthenticationScheme scheme, JwtBearerOptions options)
: base(context, scheme, options)
{
}
public AuthenticationFailedContext(
HttpContext context,
AuthenticationScheme scheme,
JwtBearerOptions options)
: base(context, scheme, options) { }
public Exception Exception { get; set; }
}

Просмотреть файл

@ -1,32 +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;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication.JwtBearer
{
public class BaseJwtBearerContext : BaseControlContext
{
public BaseJwtBearerContext(HttpContext context, AuthenticationScheme scheme, JwtBearerOptions options)
: base(context)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
if (scheme == null)
{
throw new ArgumentNullException(nameof(scheme));
}
Options = options;
Scheme = scheme;
}
public JwtBearerOptions Options { get; }
public AuthenticationScheme Scheme { get; }
}
}

Просмотреть файл

@ -6,15 +6,14 @@ using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication.JwtBearer
{
public class JwtBearerChallengeContext : BaseJwtBearerContext
public class JwtBearerChallengeContext : PropertiesContext<JwtBearerOptions>
{
public JwtBearerChallengeContext(HttpContext context, AuthenticationScheme scheme, JwtBearerOptions options, AuthenticationProperties properties)
: base(context, scheme, options)
{
Properties = properties;
}
public AuthenticationProperties Properties { get; }
public JwtBearerChallengeContext(
HttpContext context,
AuthenticationScheme scheme,
JwtBearerOptions options,
AuthenticationProperties properties)
: base(context, scheme, options, properties) { }
/// <summary>
/// Any failures encountered during the authentication process.
@ -40,5 +39,15 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
/// WWW-Authenticate header. This property is always null unless explicitly set.
/// </summary>
public string ErrorUri { get; set; }
/// <summary>
/// If true, will skip any default logic for this challenge.
/// </summary>
public bool Handled { get; private set; }
/// <summary>
/// Skips any default logic for this challenge.
/// </summary>
public void HandleResponse() => Handled = true;
}
}

Просмотреть файл

@ -5,12 +5,13 @@ using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication.JwtBearer
{
public class MessageReceivedContext : BaseJwtBearerContext
public class MessageReceivedContext : ResultContext<JwtBearerOptions>
{
public MessageReceivedContext(HttpContext context, AuthenticationScheme scheme, JwtBearerOptions options)
: base(context, scheme, options)
{
}
public MessageReceivedContext(
HttpContext context,
AuthenticationScheme scheme,
JwtBearerOptions options)
: base(context, scheme, options) { }
/// <summary>
/// Bearer Token. This will give application an opportunity to retrieve token from an alternation location.

Просмотреть файл

@ -6,12 +6,13 @@ using Microsoft.IdentityModel.Tokens;
namespace Microsoft.AspNetCore.Authentication.JwtBearer
{
public class TokenValidatedContext : BaseJwtBearerContext
public class TokenValidatedContext : ResultContext<JwtBearerOptions>
{
public TokenValidatedContext(HttpContext context, AuthenticationScheme scheme, JwtBearerOptions options)
: base(context, scheme, options)
{
}
public TokenValidatedContext(
HttpContext context,
AuthenticationScheme scheme,
JwtBearerOptions options)
: base(context, scheme, options) { }
public SecurityToken SecurityToken { get; set; }
}

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
@ -10,6 +11,20 @@ namespace Microsoft.Extensions.DependencyInjection
{
public static class JwtBearerExtensions
{
public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder)
=> builder.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, _ => { });
public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder, Action<JwtBearerOptions> configureOptions)
=> builder.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, configureOptions);
public static AuthenticationBuilder AddJwtBearer(this AuthenticationBuilder builder, string authenticationScheme, Action<JwtBearerOptions> configureOptions)
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<JwtBearerOptions>, JwtBearerPostConfigureOptions>());
return builder.AddScheme<JwtBearerOptions, JwtBearerHandler>(authenticationScheme, configureOptions);
}
// REMOVE once callers updated
public static IServiceCollection AddJwtBearerAuthentication(this IServiceCollection services)
=> services.AddJwtBearerAuthentication(JwtBearerDefaults.AuthenticationScheme, _ => { });

Просмотреть файл

@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Text.Encodings.Web;
@ -13,7 +12,6 @@ using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Net.Http.Headers;
@ -47,7 +45,6 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
string token = null;
AuthenticateResult result = null;
try
{
// Give application opportunity to find from a different location, adjust, or reject token
@ -55,9 +52,9 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
// event can set the token
await Events.MessageReceived(messageReceivedContext);
if (messageReceivedContext.IsProcessingComplete(out result))
if (messageReceivedContext.Result != null)
{
return result;
return messageReceivedContext.Result;
}
// If application retrieved token from somewhere else, use that.
@ -70,7 +67,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
// If no authorization header found, nothing to process further
if (string.IsNullOrEmpty(authorization))
{
return AuthenticateResult.None();
return AuthenticateResult.NoResult();
}
if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
@ -81,7 +78,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
// If no token found, no further work possible
if (string.IsNullOrEmpty(token))
{
return AuthenticateResult.None();
return AuthenticateResult.NoResult();
}
}
@ -138,29 +135,28 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
Logger.TokenValidationSucceeded();
var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), Scheme.Name);
var tokenValidatedContext = new TokenValidatedContext(Context, Scheme, Options)
{
Ticket = ticket,
SecurityToken = validatedToken,
Principal = principal,
SecurityToken = validatedToken
};
await Events.TokenValidated(tokenValidatedContext);
if (tokenValidatedContext.IsProcessingComplete(out result))
if (tokenValidatedContext.Result != null)
{
return result;
return tokenValidatedContext.Result;
}
ticket = tokenValidatedContext.Ticket;
if (Options.SaveToken)
{
ticket.Properties.StoreTokens(new[]
tokenValidatedContext.Properties.StoreTokens(new[]
{
new AuthenticationToken { Name = "access_token", Value = token }
});
}
return AuthenticateResult.Success(ticket);
tokenValidatedContext.Success();
return tokenValidatedContext.Result;
}
}
@ -172,9 +168,9 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
};
await Events.AuthenticationFailed(authenticationFailedContext);
if (authenticationFailedContext.IsProcessingComplete(out result))
if (authenticationFailedContext.Result != null)
{
return result;
return authenticationFailedContext.Result;
}
return AuthenticateResult.Fail(authenticationFailedContext.Exception);
@ -192,9 +188,9 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
};
await Events.AuthenticationFailed(authenticationFailedContext);
if (authenticationFailedContext.IsProcessingComplete(out result))
if (authenticationFailedContext.Result != null)
{
return result;
return authenticationFailedContext.Result;
}
throw;
@ -217,7 +213,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
}
await Events.Challenge(eventContext);
if (eventContext.IsProcessingComplete(out var ignored))
if (eventContext.Handled)
{
return;
}
@ -329,15 +325,5 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
return string.Join("; ", messages);
}
protected override Task HandleSignOutAsync(AuthenticationProperties properties)
{
throw new NotSupportedException();
}
protected override Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
{
throw new NotSupportedException();
}
}
}

Просмотреть файл

@ -15,44 +15,29 @@
"TypeId": "public interface Microsoft.AspNetCore.Authentication.JwtBearer.IJwtBearerEvents",
"Kind": "Removal"
},
{
"TypeId": "public static class Microsoft.AspNetCore.Builder.JwtBearerAppBuilderExtensions",
"MemberId": "public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseJwtBearerAuthentication(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Builder.JwtBearerOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.JwtBearer.AuthenticationFailedContext : Microsoft.AspNetCore.Authentication.JwtBearer.BaseJwtBearerContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.JwtBearerOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.JwtBearer.BaseJwtBearerContext : Microsoft.AspNetCore.Authentication.BaseControlContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.JwtBearerOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.JwtBearer.BaseJwtBearerContext : Microsoft.AspNetCore.Authentication.BaseControlContext",
"MemberId": "public Microsoft.AspNetCore.Builder.JwtBearerOptions get_Options()",
"TypeId": "public class Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerChallengeContext : Microsoft.AspNetCore.Authentication.JwtBearer.BaseJwtBearerContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.JwtBearer.MessageReceivedContext : Microsoft.AspNetCore.Authentication.JwtBearer.BaseJwtBearerContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.JwtBearerOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.JwtBearer.TokenValidatedContext : Microsoft.AspNetCore.Authentication.JwtBearer.BaseJwtBearerContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.JwtBearerOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerChallengeContext : Microsoft.AspNetCore.Authentication.JwtBearer.BaseJwtBearerContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.JwtBearerOptions options, Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties properties)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerChallengeContext : Microsoft.AspNetCore.Authentication.JwtBearer.BaseJwtBearerContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public static class Microsoft.AspNetCore.Builder.JwtBearerAppBuilderExtensions",
"MemberId": "public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseJwtBearerAuthentication(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Builder.JwtBearerOptions options)",
"Kind": "Removal"
}
]

Просмотреть файл

@ -2,12 +2,25 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
namespace Microsoft.Extensions.DependencyInjection
{
public static class MicrosoftAccountExtensions
{
public static AuthenticationBuilder AddMicrosoftAccount(this AuthenticationBuilder builder)
=> builder.AddMicrosoftAccount(MicrosoftAccountDefaults.AuthenticationScheme, _ => { });
public static AuthenticationBuilder AddMicrosoftAccount(this AuthenticationBuilder builder, Action<MicrosoftAccountOptions> configureOptions)
=> builder.AddMicrosoftAccount(MicrosoftAccountDefaults.AuthenticationScheme, configureOptions);
public static AuthenticationBuilder AddMicrosoftAccount(this AuthenticationBuilder builder, string authenticationScheme, Action<MicrosoftAccountOptions> configureOptions)
=> builder.AddOAuth<MicrosoftAccountOptions, MicrosoftAccountHandler>(authenticationScheme, configureOptions);
// REMOVE below once callers have been updated
public static IServiceCollection AddMicrosoftAccountAuthentication(this IServiceCollection services)
=> services.AddMicrosoftAccountAuthentication(MicrosoftAccountDefaults.AuthenticationScheme, _ => { });

Просмотреть файл

@ -32,12 +32,11 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), properties, Scheme.Name);
var context = new OAuthCreatingTicketContext(ticket, Context, Scheme, Options, Backchannel, tokens, payload);
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload);
context.RunClaimActions();
await Events.CreatingTicket(context);
return context.Ticket;
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
}
}
}

Просмотреть файл

@ -13,32 +13,34 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
/// <summary>
/// Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.
/// </summary>
public class OAuthCreatingTicketContext : BaseAuthenticationContext
public class OAuthCreatingTicketContext : ResultContext<OAuthOptions>
{
/// <summary>
/// Initializes a new <see cref="OAuthCreatingTicketContext"/>.
/// </summary>
/// <param name="ticket">The <see cref="AuthenticationTicket"/>.</param>
/// <param name="principal">The <see cref="ClaimsPrincipal"/>.</param>
/// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
/// <param name="context">The HTTP environment.</param>
/// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The options used by the authentication middleware.</param>
/// <param name="backchannel">The HTTP client used by the authentication middleware</param>
/// <param name="tokens">The tokens returned from the token endpoint.</param>
public OAuthCreatingTicketContext(
AuthenticationTicket ticket,
ClaimsPrincipal principal,
AuthenticationProperties properties,
HttpContext context,
AuthenticationScheme scheme,
OAuthOptions options,
HttpClient backchannel,
OAuthTokenResponse tokens)
: this(ticket, context, scheme, options, backchannel, tokens, user: new JObject())
{
}
: this(principal, properties, context, scheme, options, backchannel, tokens, user: new JObject())
{ }
/// <summary>
/// Initializes a new <see cref="OAuthCreatingTicketContext"/>.
/// </summary>
/// <param name="ticket">The <see cref="AuthenticationTicket"/>.</param>
/// <param name="principal">The <see cref="ClaimsPrincipal"/>.</param>
/// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
/// <param name="context">The HTTP environment.</param>
/// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The options used by the authentication middleware.</param>
@ -46,25 +48,16 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
/// <param name="tokens">The tokens returned from the token endpoint.</param>
/// <param name="user">The JSON-serialized user.</param>
public OAuthCreatingTicketContext(
AuthenticationTicket ticket,
ClaimsPrincipal principal,
AuthenticationProperties properties,
HttpContext context,
AuthenticationScheme scheme,
OAuthOptions options,
HttpClient backchannel,
OAuthTokenResponse tokens,
JObject user)
: base(context, scheme.Name, ticket.Properties)
: base(context, scheme, options)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
if (backchannel == null)
{
throw new ArgumentNullException(nameof(backchannel));
@ -80,23 +73,13 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
throw new ArgumentNullException(nameof(user));
}
if (scheme == null)
{
throw new ArgumentNullException(nameof(scheme));
}
TokenResponse = tokens;
Backchannel = backchannel;
User = user;
Options = options;
Scheme = scheme;
Ticket = ticket;
Principal = principal;
Properties = properties;
}
public OAuthOptions Options { get; }
public AuthenticationScheme Scheme { get; }
/// <summary>
/// Gets the JSON-serialized user or an empty
/// <see cref="JObject"/> if it is not available.
@ -146,20 +129,12 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
public HttpClient Backchannel { get; }
/// <summary>
/// The <see cref="AuthenticationTicket"/> that will be created.
/// Gets the main identity exposed by the authentication ticket.
/// This property returns <c>null</c> when the ticket is <c>null</c>.
/// </summary>
public AuthenticationTicket Ticket { get; set; }
public ClaimsIdentity Identity => Principal?.Identity as ClaimsIdentity;
/// <summary>
/// Gets the main identity exposed by <see cref="Ticket"/>.
/// This property returns <c>null</c> when <see cref="Ticket"/> is <c>null</c>.
/// </summary>
public ClaimsIdentity Identity => Ticket?.Principal.Identity as ClaimsIdentity;
public void RunClaimActions()
{
RunClaimActions(User);
}
public void RunClaimActions() => RunClaimActions(User);
public void RunClaimActions(JObject userData)
{

Просмотреть файл

@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
/// <summary>
/// Gets or sets the delegate that is invoked when the RedirectToAuthorizationEndpoint method is invoked.
/// </summary>
public Func<OAuthRedirectToAuthorizationContext, Task> OnRedirectToAuthorizationEndpoint { get; set; } = context =>
public Func<RedirectContext<OAuthOptions>, Task> OnRedirectToAuthorizationEndpoint { get; set; } = context =>
{
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
/// <summary>
/// Called when a Challenge causes a redirect to authorize endpoint in the OAuth handler.
/// </summary>
/// <param name="context">Contains redirect URI and <see cref="Http.Authentication.AuthenticationProperties"/> of the challenge.</param>
public virtual Task RedirectToAuthorizationEndpoint(OAuthRedirectToAuthorizationContext context) => OnRedirectToAuthorizationEndpoint(context);
/// <param name="context">Contains redirect URI and <see cref="AuthenticationProperties"/> of the challenge.</param>
public virtual Task RedirectToAuthorizationEndpoint(RedirectContext<OAuthOptions> context) => OnRedirectToAuthorizationEndpoint(context);
}
}

Просмотреть файл

@ -1,41 +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 Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication.OAuth
{
/// <summary>
/// Context passed when a Challenge causes a redirect to authorize endpoint in the handler.
/// </summary>
public class OAuthRedirectToAuthorizationContext : BaseContext
{
/// <summary>
/// Creates a new context object.
/// </summary>
/// <param name="context">The HTTP request context.</param>
/// <param name="options">The <see cref="OAuthOptions"/>.</param>
/// <param name="properties">The authentication properties of the challenge.</param>
/// <param name="redirectUri">The initial redirect URI.</param>
public OAuthRedirectToAuthorizationContext(HttpContext context, OAuthOptions options, AuthenticationProperties properties, string redirectUri)
: base(context)
{
RedirectUri = redirectUri;
Properties = properties;
Options = options;
}
public OAuthOptions Options { get; }
/// <summary>
/// Gets the URI used for the redirect operation.
/// </summary>
public string RedirectUri { get; private set; }
/// <summary>
/// Gets the authentication properties of the challenge.
/// </summary>
public AuthenticationProperties Properties { get; private set; }
}
}

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
@ -10,6 +11,18 @@ namespace Microsoft.Extensions.DependencyInjection
{
public static class OAuthExtensions
{
public static AuthenticationBuilder AddOAuth(this AuthenticationBuilder builder, string authenticationScheme, Action<OAuthOptions> configureOptions)
=> builder.AddOAuth<OAuthOptions, OAuthHandler<OAuthOptions>>(authenticationScheme, configureOptions);
public static AuthenticationBuilder AddOAuth<TOptions, THandler>(this AuthenticationBuilder builder, string authenticationScheme, Action<TOptions> configureOptions)
where TOptions : OAuthOptions, new()
where THandler : OAuthHandler<TOptions>
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<TOptions>, OAuthPostConfigureOptions<TOptions, THandler>>());
return builder.AddRemoteScheme<TOptions, THandler>(authenticationScheme, authenticationScheme, configureOptions);
}
// REMOVE below once callers have been updated
public static IServiceCollection AddOAuthAuthentication(this IServiceCollection services, string authenticationScheme, Action<OAuthOptions> configureOptions)
{
return services.AddOAuthAuthentication<OAuthOptions, OAuthHandler<OAuthOptions>>(authenticationScheme, configureOptions);

Просмотреть файл

@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
/// <returns>A new instance of the events instance.</returns>
protected override Task<object> CreateEventsAsync() => Task.FromResult<object>(new OAuthEvents());
protected override async Task<AuthenticateResult> HandleRemoteAuthenticateAsync()
protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync()
{
AuthenticationProperties properties = null;
var query = Request.Query;
@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
failureMessage.Append(";Uri=").Append(errorUri);
}
return AuthenticateResult.Fail(failureMessage.ToString());
return HandleRequestResult.Fail(failureMessage.ToString());
}
var code = query["code"];
@ -72,30 +72,30 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return AuthenticateResult.Fail("The oauth state was missing or invalid.");
return HandleRequestResult.Fail("The oauth state was missing or invalid.");
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties))
{
return AuthenticateResult.Fail("Correlation failed.");
return HandleRequestResult.Fail("Correlation failed.");
}
if (StringValues.IsNullOrEmpty(code))
{
return AuthenticateResult.Fail("Code was not found.");
return HandleRequestResult.Fail("Code was not found.");
}
var tokens = await ExchangeCodeAsync(code, BuildRedirectUri(Options.CallbackPath));
if (tokens.Error != null)
{
return AuthenticateResult.Fail(tokens.Error);
return HandleRequestResult.Fail(tokens.Error);
}
if (string.IsNullOrEmpty(tokens.AccessToken))
{
return AuthenticateResult.Fail("Failed to retrieve access token.");
return HandleRequestResult.Fail("Failed to retrieve access token.");
}
var identity = new ClaimsIdentity(ClaimsIssuer);
@ -137,11 +137,11 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
var ticket = await CreateTicketAsync(identity, properties, tokens);
if (ticket != null)
{
return AuthenticateResult.Success(ticket);
return HandleRequestResult.Success(ticket);
}
else
{
return AuthenticateResult.Fail("Failed to retrieve user information from remote server.");
return HandleRequestResult.Fail("Failed to retrieve user information from remote server.");
}
}
@ -185,10 +185,9 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
protected virtual async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
{
var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), properties, Scheme.Name);
var context = new OAuthCreatingTicketContext(ticket, Context, Scheme, Options, Backchannel, tokens);
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens);
await Events.CreatingTicket(context);
return context.Ticket;
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
}
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
@ -202,8 +201,8 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
GenerateCorrelationId(properties);
var authorizationEndpoint = BuildChallengeUrl(properties, BuildRedirectUri(Options.CallbackPath));
var redirectContext = new OAuthRedirectToAuthorizationContext(
Context, Options,
var redirectContext = new RedirectContext<OAuthOptions>(
Context, Scheme, Options,
properties, authorizationEndpoint);
await Events.RedirectToAuthorizationEndpoint(redirectContext);
}

Просмотреть файл

@ -23,24 +23,13 @@
"TypeId": "public interface Microsoft.AspNetCore.Authentication.OAuth.IOAuthEvents : Microsoft.AspNetCore.Authentication.IRemoteAuthenticationEvents",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OAuth.OAuthRedirectToAuthorizationContext : Microsoft.AspNetCore.Authentication.BaseContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.OAuthOptions options, Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties properties, System.String redirectUri)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OAuth.OAuthRedirectToAuthorizationContext : Microsoft.AspNetCore.Authentication.BaseContext",
"MemberId": "public Microsoft.AspNetCore.Builder.OAuthOptions get_Options()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OAuth.OAuthRedirectToAuthorizationContext : Microsoft.AspNetCore.Authentication.BaseContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public static class Microsoft.AspNetCore.Builder.OAuthAppBuilderExtensions",
"MemberId": "public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseOAuthAuthentication(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Builder.OAuthOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OAuth.OAuthRedirectToAuthorizationContext : Microsoft.AspNetCore.Authentication.BaseContext",
"Kind": "Removal"
}
]

Просмотреть файл

@ -2,17 +2,18 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
{
public class AuthenticationFailedContext : BaseOpenIdConnectContext
public class AuthenticationFailedContext : RemoteAuthenticationContext<OpenIdConnectOptions>
{
public AuthenticationFailedContext(HttpContext context, AuthenticationScheme scheme, OpenIdConnectOptions options)
: base(context, scheme, options)
{
}
: base(context, scheme, options, new AuthenticationProperties())
{ }
public OpenIdConnectMessage ProtocolMessage { get; set; }
public Exception Exception { get; set; }
}

Просмотреть файл

@ -3,9 +3,7 @@
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
@ -13,17 +11,19 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
/// <summary>
/// This Context can be used to be informed when an 'AuthorizationCode' is received over the OpenIdConnect protocol.
/// </summary>
public class AuthorizationCodeReceivedContext : BaseOpenIdConnectContext
public class AuthorizationCodeReceivedContext : RemoteAuthenticationContext<OpenIdConnectOptions>
{
/// <summary>
/// Creates a <see cref="AuthorizationCodeReceivedContext"/>
/// </summary>
public AuthorizationCodeReceivedContext(HttpContext context, AuthenticationScheme scheme, OpenIdConnectOptions options)
: base(context, scheme, options)
{
}
public AuthorizationCodeReceivedContext(
HttpContext context,
AuthenticationScheme scheme,
OpenIdConnectOptions options,
AuthenticationProperties properties)
: base(context, scheme, options, properties) { }
public AuthenticationProperties Properties { get; set; }
public OpenIdConnectMessage ProtocolMessage { get; set; }
/// <summary>
/// Gets or sets the <see cref="JwtSecurityToken"/> that was received in the authentication response, if any.

Просмотреть файл

@ -1,25 +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;
using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
{
public class BaseOpenIdConnectContext : BaseControlContext
{
public BaseOpenIdConnectContext(HttpContext context, AuthenticationScheme scheme, OpenIdConnectOptions options)
: base(context)
{
Options = options ?? throw new ArgumentNullException(nameof(options));
Scheme = scheme ?? throw new ArgumentNullException(nameof(scheme));
}
public OpenIdConnectOptions Options { get; }
public AuthenticationScheme Scheme { get; }
public OpenIdConnectMessage ProtocolMessage { get; set; }
}
}

Просмотреть файл

@ -2,21 +2,24 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
{
public class MessageReceivedContext : BaseOpenIdConnectContext
public class MessageReceivedContext : RemoteAuthenticationContext<OpenIdConnectOptions>
{
public MessageReceivedContext(HttpContext context, AuthenticationScheme scheme, OpenIdConnectOptions options)
: base(context, scheme, options)
{
}
public MessageReceivedContext(
HttpContext context,
AuthenticationScheme scheme,
OpenIdConnectOptions options,
AuthenticationProperties properties)
: base(context, scheme, options, properties) { }
public OpenIdConnectMessage ProtocolMessage { get; set; }
/// <summary>
/// Bearer Token. This will give application an opportunity to retrieve token from an alternation location.
/// </summary>
public string Token { get; set; }
public AuthenticationProperties Properties { get; set; }
}
}

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
{
@ -9,14 +10,25 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
/// When a user configures the <see cref="OpenIdConnectHandler"/> to be notified prior to redirecting to an IdentityProvider
/// an instance of <see cref="RedirectContext"/> is passed to the 'RedirectToAuthenticationEndpoint' or 'RedirectToEndSessionEndpoint' events.
/// </summary>
public class RedirectContext : BaseOpenIdConnectContext
public class RedirectContext : PropertiesContext<OpenIdConnectOptions>
{
public RedirectContext(HttpContext context, AuthenticationScheme scheme, OpenIdConnectOptions options, AuthenticationProperties properties)
: base(context, scheme, options)
{
Properties = properties;
}
public RedirectContext(
HttpContext context,
AuthenticationScheme scheme,
OpenIdConnectOptions options,
AuthenticationProperties properties)
: base(context, scheme, options, properties) { }
public AuthenticationProperties Properties { get; }
public OpenIdConnectMessage ProtocolMessage { get; set; }
/// <summary>
/// If true, will skip any default logic for this redirect.
/// </summary>
public bool Handled { get; private set; }
/// <summary>
/// Skips any default logic for this redirect.
/// </summary>
public void HandleResponse() => Handled = true;
}
}

Просмотреть файл

@ -6,16 +6,12 @@ using Microsoft.IdentityModel.Protocols.OpenIdConnect;
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
{
public class RemoteSignOutContext : BaseOpenIdConnectContext
public class RemoteSignOutContext : RemoteAuthenticationContext<OpenIdConnectOptions>
{
public RemoteSignOutContext(
HttpContext context,
AuthenticationScheme scheme,
OpenIdConnectOptions options,
OpenIdConnectMessage message)
: base(context, scheme, options)
{
ProtocolMessage = message;
}
public RemoteSignOutContext(HttpContext context, AuthenticationScheme scheme, OpenIdConnectOptions options, OpenIdConnectMessage message)
: base(context, scheme, options, new AuthenticationProperties())
=> ProtocolMessage = message;
public OpenIdConnectMessage ProtocolMessage { get; set; }
}
}

Просмотреть файл

@ -1,6 +1,7 @@
// 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 Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
@ -9,18 +10,16 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
/// <summary>
/// This Context can be used to be informed when an 'AuthorizationCode' is redeemed for tokens at the token endpoint.
/// </summary>
public class TokenResponseReceivedContext : BaseOpenIdConnectContext
public class TokenResponseReceivedContext : RemoteAuthenticationContext<OpenIdConnectOptions>
{
/// <summary>
/// Creates a <see cref="TokenResponseReceivedContext"/>
/// </summary>
public TokenResponseReceivedContext(HttpContext context, AuthenticationScheme scheme, OpenIdConnectOptions options, AuthenticationProperties properties)
: base(context, scheme, options)
{
Properties = properties;
}
public TokenResponseReceivedContext(HttpContext context, AuthenticationScheme scheme, OpenIdConnectOptions options, ClaimsPrincipal user, AuthenticationProperties properties)
: base(context, scheme, options, properties)
=> Principal = user;
public AuthenticationProperties Properties { get; }
public OpenIdConnectMessage ProtocolMessage { get; set; }
/// <summary>
/// Gets or sets the <see cref="OpenIdConnectMessage"/> that contains the tokens received after redeeming the code at the token endpoint.

Просмотреть файл

@ -2,26 +2,23 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using Microsoft.AspNetCore.Builder;
using System.Security.Claims;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
{
public class TokenValidatedContext : BaseOpenIdConnectContext
public class TokenValidatedContext : RemoteAuthenticationContext<OpenIdConnectOptions>
{
/// <summary>
/// Creates a <see cref="TokenValidatedContext"/>
/// </summary>
public TokenValidatedContext(HttpContext context, AuthenticationScheme scheme, OpenIdConnectOptions options)
: base(context, scheme, options)
{
}
public TokenValidatedContext(HttpContext context, AuthenticationScheme scheme, OpenIdConnectOptions options, ClaimsPrincipal principal, AuthenticationProperties properties)
: base(context, scheme, options, properties)
=> Principal = principal;
public OpenIdConnectMessage ProtocolMessage { get; set; }
public AuthenticationProperties Properties { get; set; }
public JwtSecurityToken SecurityToken { get; set; }
public OpenIdConnectMessage TokenEndpointResponse { get; set; }

Просмотреть файл

@ -1,17 +1,20 @@
// 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 Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Newtonsoft.Json.Linq;
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
{
public class UserInformationReceivedContext : BaseOpenIdConnectContext
public class UserInformationReceivedContext : RemoteAuthenticationContext<OpenIdConnectOptions>
{
public UserInformationReceivedContext(HttpContext context, AuthenticationScheme scheme, OpenIdConnectOptions options)
: base(context, scheme, options)
{
}
public UserInformationReceivedContext(HttpContext context, AuthenticationScheme scheme, OpenIdConnectOptions options, ClaimsPrincipal principal, AuthenticationProperties properties)
: base(context, scheme, options, properties)
=> Principal = principal;
public OpenIdConnectMessage ProtocolMessage { get; set; }
public JObject User { get; set; }
}

Просмотреть файл

@ -8,9 +8,7 @@ namespace Microsoft.Extensions.Logging
internal static class LoggingExtensions
{
private static Action<ILogger, Exception> _redirectToIdentityProviderForSignOutHandledResponse;
private static Action<ILogger, Exception> _redirectToIdentityProviderForSignOutSkipped;
private static Action<ILogger, Exception> _redirectToIdentityProviderHandledResponse;
private static Action<ILogger, Exception> _redirectToIdentityProviderSkipped;
private static Action<ILogger, Exception> _updatingConfiguration;
private static Action<ILogger, Exception> _receivedIdToken;
private static Action<ILogger, Exception> _redeemingCodeForTokens;
@ -55,6 +53,7 @@ namespace Microsoft.Extensions.Logging
private static Action<ILogger, Exception> _remoteSignOut;
private static Action<ILogger, Exception> _remoteSignOutSessionIdMissing;
private static Action<ILogger, Exception> _remoteSignOutSessionIdInvalid;
private static Action<ILogger, string, Exception> _signOut;
static LoggingExtensions()
{
@ -63,10 +62,6 @@ namespace Microsoft.Extensions.Logging
eventId: 1,
logLevel: LogLevel.Debug,
formatString: "RedirectToIdentityProviderForSignOut.HandledResponse");
_redirectToIdentityProviderForSignOutSkipped = LoggerMessage.Define(
eventId: 2,
logLevel: LogLevel.Debug,
formatString: "RedirectToIdentityProviderForSignOut.Skipped");
_invalidLogoutQueryStringRedirectUrl = LoggerMessage.Define<string>(
eventId: 3,
logLevel: LogLevel.Warning,
@ -87,10 +82,6 @@ namespace Microsoft.Extensions.Logging
eventId: 6,
logLevel: LogLevel.Debug,
formatString: "RedirectToIdentityProvider.HandledResponse");
_redirectToIdentityProviderSkipped = LoggerMessage.Define(
eventId: 7,
logLevel: LogLevel.Debug,
formatString: "RedirectToIdentityProvider.Skipped");
_invalidAuthenticationRequestUrl = LoggerMessage.Define<string>(
eventId: 8,
logLevel: LogLevel.Warning,
@ -253,6 +244,10 @@ namespace Microsoft.Extensions.Logging
logLevel: LogLevel.Error,
formatString: "The remote signout request was ignored because the 'sid' parameter didn't match " +
"the expected value, which may indicate an unsolicited logout.");
_signOut = LoggerMessage.Define<string>(
eventId: 49,
logLevel: LogLevel.Information,
formatString: "AuthenticationScheme: {AuthenticationScheme} signed out.");
}
public static void UpdatingConfiguration(this ILogger logger)
@ -345,21 +340,11 @@ namespace Microsoft.Extensions.Logging
_redirectToIdentityProviderForSignOutHandledResponse(logger, null);
}
public static void RedirectToIdentityProviderForSignOutSkipped(this ILogger logger)
{
_redirectToIdentityProviderForSignOutSkipped(logger, null);
}
public static void RedirectToIdentityProviderHandledResponse(this ILogger logger)
{
_redirectToIdentityProviderHandledResponse(logger, null);
}
public static void RedirectToIdentityProviderSkipped(this ILogger logger)
{
_redirectToIdentityProviderSkipped(logger, null);
}
public static void UserInformationReceivedHandledResponse(this ILogger logger)
{
_userInformationReceivedHandledResponse(logger, null);
@ -494,5 +479,10 @@ namespace Microsoft.Extensions.Logging
{
_remoteSignOutSessionIdInvalid(logger, null);
}
public static void SignedOut(this ILogger logger, string authenticationScheme)
{
_signOut(logger, authenticationScheme, null);
}
}
}

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
@ -10,6 +11,19 @@ namespace Microsoft.Extensions.DependencyInjection
{
public static class OpenIdConnectExtensions
{
public static AuthenticationBuilder AddOpenIdConnect(this AuthenticationBuilder builder)
=> builder.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, _ => { });
public static AuthenticationBuilder AddOpenIdConnect(this AuthenticationBuilder builder, Action<OpenIdConnectOptions> configureOptions)
=> builder.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, configureOptions);
public static AuthenticationBuilder AddOpenIdConnect(this AuthenticationBuilder builder, string authenticationScheme, Action<OpenIdConnectOptions> configureOptions)
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<OpenIdConnectOptions>, OpenIdConnectPostConfigureOptions>());
return builder.AddRemoteScheme<OpenIdConnectOptions, OpenIdConnectHandler>(authenticationScheme, authenticationScheme, configureOptions);
}
// REMOVE once callers have been updated
public static IServiceCollection AddOpenIdConnectAuthentication(this IServiceCollection services)
=> services.AddOpenIdConnectAuthentication(OpenIdConnectDefaults.AuthenticationScheme, _ => { });

Просмотреть файл

@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
/// <summary>
/// A per-request authentication handler for the OpenIdConnectAuthenticationMiddleware.
/// </summary>
public class OpenIdConnectHandler : RemoteAuthenticationHandler<OpenIdConnectOptions>
public class OpenIdConnectHandler : RemoteAuthenticationHandler<OpenIdConnectOptions>, IAuthenticationSignOutHandler
{
private const string NonceProperty = "N";
private const string UriSchemeDelimiter = "://";
@ -110,15 +110,18 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
var remoteSignOutContext = new RemoteSignOutContext(Context, Scheme, Options, message);
await Events.RemoteSignOut(remoteSignOutContext);
if (remoteSignOutContext.HandledResponse)
if (remoteSignOutContext.Result != null)
{
Logger.RemoteSignOutHandledResponse();
return true;
}
if (remoteSignOutContext.Skipped)
{
Logger.RemoteSignOutSkipped();
return false;
if (remoteSignOutContext.Result.Handled)
{
Logger.RemoteSignOutHandledResponse();
return true;
}
if (remoteSignOutContext.Result.Skipped)
{
Logger.RemoteSignOutSkipped();
return false;
}
}
if (message == null)
@ -161,8 +164,10 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
/// Redirect user to the identity provider for sign out
/// </summary>
/// <returns>A task executing the sign out procedure</returns>
protected override async Task HandleSignOutAsync(AuthenticationProperties properties)
public async virtual Task SignOutAsync(AuthenticationProperties properties)
{
properties = properties ?? new AuthenticationProperties();
Logger.EnteringOpenIdAuthenticationHandlerHandleSignOutAsync(GetType().FullName);
if (_configuration == null && Options.ConfigurationManager != null)
@ -199,16 +204,11 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
};
await Events.RedirectToIdentityProviderForSignOut(redirectContext);
if (redirectContext.HandledResponse)
if (redirectContext.Handled)
{
Logger.RedirectToIdentityProviderForSignOutHandledResponse();
return;
}
else if (redirectContext.Skipped)
{
Logger.RedirectToIdentityProviderForSignOutSkipped();
return;
}
message = redirectContext.ProtocolMessage;
@ -221,8 +221,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
if (string.IsNullOrEmpty(message.IssuerAddress))
{
throw new InvalidOperationException(
"Cannot redirect to the end session endpoint, the configuration may be missing or invalid.");
throw new InvalidOperationException("Cannot redirect to the end session endpoint, the configuration may be missing or invalid.");
}
if (Options.AuthenticationMethod == OpenIdConnectRedirectBehavior.RedirectGet)
@ -266,6 +265,8 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
{
throw new NotImplementedException($"An unsupported authentication method has been configured: {Options.AuthenticationMethod}");
}
Logger.SignedOut(Scheme.Name);
}
/// <summary>
@ -343,16 +344,11 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
};
await Events.RedirectToIdentityProvider(redirectContext);
if (redirectContext.HandledResponse)
if (redirectContext.Handled)
{
Logger.RedirectToIdentityProviderHandledResponse();
return;
}
else if (redirectContext.Skipped)
{
Logger.RedirectToIdentityProviderSkipped();
return;
}
message = redirectContext.ProtocolMessage;
@ -418,8 +414,8 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
/// <summary>
/// Invoked to process incoming OpenIdConnect messages.
/// </summary>
/// <returns>An <see cref="AuthenticationTicket"/> if successful.</returns>
protected override async Task<AuthenticateResult> HandleRemoteAuthenticateAsync()
/// <returns>An <see cref="HandleRequestResult"/>.</returns>
protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync()
{
Logger.EnteringOpenIdAuthenticationHandlerHandleRemoteAuthenticateAsync(GetType().FullName);
@ -437,9 +433,9 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
if (Options.SkipUnrecognizedRequests)
{
// Not for us?
return AuthenticateResult.None();
return HandleRequestResult.SkipHandler();
}
return AuthenticateResult.Fail("An OpenID Connect response cannot contain an " +
return HandleRequestResult.Fail("An OpenID Connect response cannot contain an " +
"identity token or an access token when using response_mode=query");
}
}
@ -459,13 +455,11 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
if (Options.SkipUnrecognizedRequests)
{
// Not for us?
return AuthenticateResult.None();
return HandleRequestResult.SkipHandler();
}
return AuthenticateResult.Fail("No message.");
return HandleRequestResult.Fail("No message.");
}
AuthenticateResult result;
try
{
AuthenticationProperties properties = null;
@ -475,9 +469,9 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
}
var messageReceivedContext = await RunMessageReceivedEventAsync(authorizationResponse, properties);
if (messageReceivedContext.IsProcessingComplete(out result))
if (messageReceivedContext.Result != null)
{
return result;
return messageReceivedContext.Result;
}
authorizationResponse = messageReceivedContext.ProtocolMessage;
properties = messageReceivedContext.Properties;
@ -491,9 +485,9 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
Logger.NullOrEmptyAuthorizationResponseState();
if (Options.SkipUnrecognizedRequests)
{
return AuthenticateResult.None();
return HandleRequestResult.SkipHandler();
}
return AuthenticateResult.Fail(Resources.MessageStateIsNullOrEmpty);
return HandleRequestResult.Fail(Resources.MessageStateIsNullOrEmpty);
}
// if state exists and we failed to 'unprotect' this is not a message we should process.
@ -506,9 +500,9 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
if (Options.SkipUnrecognizedRequests)
{
// Not for us?
return AuthenticateResult.None();
return HandleRequestResult.SkipHandler();
}
return AuthenticateResult.Fail(Resources.MessageStateIsInvalid);
return HandleRequestResult.Fail(Resources.MessageStateIsInvalid);
}
string userstate = null;
@ -517,13 +511,13 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
if (!ValidateCorrelationId(properties))
{
return AuthenticateResult.Fail("Correlation failed.");
return HandleRequestResult.Fail("Correlation failed.");
}
// if any of the error fields are set, throw error null
if (!string.IsNullOrEmpty(authorizationResponse.Error))
{
return AuthenticateResult.Fail(CreateOpenIdConnectProtocolException(authorizationResponse, response: null));
return HandleRequestResult.Fail(CreateOpenIdConnectProtocolException(authorizationResponse, response: null));
}
if (_configuration == null && Options.ConfigurationManager != null)
@ -534,7 +528,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
PopulateSessionProperties(authorizationResponse, properties);
AuthenticationTicket ticket = null;
ClaimsPrincipal user = null;
JwtSecurityToken jwt = null;
string nonce = null;
var validationParameters = Options.TokenValidationParameters.Clone();
@ -543,7 +537,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
if (!string.IsNullOrEmpty(authorizationResponse.IdToken))
{
Logger.ReceivedIdToken();
ticket = ValidateToken(authorizationResponse.IdToken, properties, validationParameters, out jwt);
user = ValidateToken(authorizationResponse.IdToken, properties, validationParameters, out jwt);
nonce = jwt.Payload.Nonce;
if (!string.IsNullOrEmpty(nonce))
@ -551,14 +545,14 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
nonce = ReadNonceCookie(nonce);
}
var tokenValidatedContext = await RunTokenValidatedEventAsync(authorizationResponse, null, properties, ticket, jwt, nonce);
if (tokenValidatedContext.IsProcessingComplete(out result))
var tokenValidatedContext = await RunTokenValidatedEventAsync(authorizationResponse, null, user, properties, jwt, nonce);
if (tokenValidatedContext.Result != null)
{
return result;
return tokenValidatedContext.Result;
}
authorizationResponse = tokenValidatedContext.ProtocolMessage;
user = tokenValidatedContext.Principal;
properties = tokenValidatedContext.Properties;
ticket = tokenValidatedContext.Ticket;
jwt = tokenValidatedContext.SecurityToken;
nonce = tokenValidatedContext.Nonce;
}
@ -576,17 +570,17 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
// Authorization Code or Hybrid flow
if (!string.IsNullOrEmpty(authorizationResponse.Code))
{
var authorizationCodeReceivedContext = await RunAuthorizationCodeReceivedEventAsync(authorizationResponse, properties, ticket, jwt);
if (authorizationCodeReceivedContext.IsProcessingComplete(out result))
var authorizationCodeReceivedContext = await RunAuthorizationCodeReceivedEventAsync(authorizationResponse, user, properties, jwt);
if (authorizationCodeReceivedContext.Result != null)
{
return result;
return authorizationCodeReceivedContext.Result;
}
authorizationResponse = authorizationCodeReceivedContext.ProtocolMessage;
user = authorizationCodeReceivedContext.Principal;
properties = authorizationCodeReceivedContext.Properties;
var tokenEndpointRequest = authorizationCodeReceivedContext.TokenEndpointRequest;
// If the developer redeemed the code themselves...
tokenEndpointResponse = authorizationCodeReceivedContext.TokenEndpointResponse;
ticket = authorizationCodeReceivedContext.Ticket;
jwt = authorizationCodeReceivedContext.JwtSecurityToken;
if (!authorizationCodeReceivedContext.HandledCodeRedemption)
@ -594,14 +588,16 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
tokenEndpointResponse = await RedeemAuthorizationCodeAsync(tokenEndpointRequest);
}
var tokenResponseReceivedContext = await RunTokenResponseReceivedEventAsync(authorizationResponse, tokenEndpointResponse, properties, ticket);
if (tokenResponseReceivedContext.IsProcessingComplete(out result))
var tokenResponseReceivedContext = await RunTokenResponseReceivedEventAsync(authorizationResponse, tokenEndpointResponse, user, properties);
if (tokenResponseReceivedContext.Result != null)
{
return result;
return tokenResponseReceivedContext.Result;
}
authorizationResponse = tokenResponseReceivedContext.ProtocolMessage;
tokenEndpointResponse = tokenResponseReceivedContext.TokenEndpointResponse;
user = tokenResponseReceivedContext.Principal;
properties = tokenResponseReceivedContext.Properties;
// no need to validate signature when token is received using "code flow" as per spec
// [http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation].
@ -610,10 +606,10 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
// At least a cursory validation is required on the new IdToken, even if we've already validated the one from the authorization response.
// And we'll want to validate the new JWT in ValidateTokenResponse.
JwtSecurityToken tokenEndpointJwt;
var tokenEndpointTicket = ValidateToken(tokenEndpointResponse.IdToken, properties, validationParameters, out tokenEndpointJwt);
var tokenEndpointUser = ValidateToken(tokenEndpointResponse.IdToken, properties, validationParameters, out tokenEndpointJwt);
// Avoid reading & deleting the nonce cookie, running the event, etc, if it was already done as part of the authorization response validation.
if (ticket == null)
if (user == null)
{
nonce = tokenEndpointJwt.Payload.Nonce;
if (!string.IsNullOrEmpty(nonce))
@ -621,15 +617,15 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
nonce = ReadNonceCookie(nonce);
}
var tokenValidatedContext = await RunTokenValidatedEventAsync(authorizationResponse, tokenEndpointResponse, properties, tokenEndpointTicket, tokenEndpointJwt, nonce);
if (tokenValidatedContext.IsProcessingComplete(out result))
var tokenValidatedContext = await RunTokenValidatedEventAsync(authorizationResponse, tokenEndpointResponse, tokenEndpointUser, properties, tokenEndpointJwt, nonce);
if (tokenValidatedContext.Result != null)
{
return result;
return tokenValidatedContext.Result;
}
authorizationResponse = tokenValidatedContext.ProtocolMessage;
tokenEndpointResponse = tokenValidatedContext.TokenEndpointResponse;
user = tokenValidatedContext.Principal;
properties = tokenValidatedContext.Properties;
ticket = tokenValidatedContext.Ticket;
jwt = tokenValidatedContext.SecurityToken;
nonce = tokenValidatedContext.Nonce;
}
@ -658,23 +654,23 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
if (Options.SaveTokens)
{
SaveTokens(ticket.Properties, tokenEndpointResponse ?? authorizationResponse);
SaveTokens(properties, tokenEndpointResponse ?? authorizationResponse);
}
if (Options.GetClaimsFromUserInfoEndpoint)
{
return await GetUserInformationAsync(tokenEndpointResponse ?? authorizationResponse, jwt, ticket);
return await GetUserInformationAsync(tokenEndpointResponse ?? authorizationResponse, jwt, user, properties);
}
else
{
var identity = (ClaimsIdentity)ticket.Principal.Identity;
var identity = (ClaimsIdentity)user.Identity;
foreach (var action in Options.ClaimActions)
{
action.Run(null, identity, ClaimsIssuer);
}
}
return AuthenticateResult.Success(ticket);
return HandleRequestResult.Success(new AuthenticationTicket(user, properties, Scheme.Name));
}
catch (Exception exception)
{
@ -691,12 +687,12 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
}
var authenticationFailedContext = await RunAuthenticationFailedEventAsync(authorizationResponse, exception);
if (authenticationFailedContext.IsProcessingComplete(out result))
if (authenticationFailedContext.Result != null)
{
return result;
return authenticationFailedContext.Result;
}
return AuthenticateResult.Fail(exception);
return HandleRequestResult.Fail(exception);
}
}
@ -765,21 +761,24 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
/// </summary>
/// <param name="message">message that is being processed</param>
/// <param name="jwt">The <see cref="JwtSecurityToken"/>.</param>
/// <param name="ticket">authentication ticket with claims principal and identities</param>
/// <returns>Authentication ticket with identity with additional claims, if any.</returns>
protected virtual async Task<AuthenticateResult> GetUserInformationAsync(OpenIdConnectMessage message, JwtSecurityToken jwt, AuthenticationTicket ticket)
/// <param name="principal">The claims principal and identities.</param>
/// <param name="properties">The authentication properties.</param>
/// <returns><see cref="HandleRequestResult"/> which is used to determine if the remote authentication was successful.</returns>
protected virtual async Task<HandleRequestResult> GetUserInformationAsync(
OpenIdConnectMessage message, JwtSecurityToken jwt,
ClaimsPrincipal principal, AuthenticationProperties properties)
{
var userInfoEndpoint = _configuration?.UserInfoEndpoint;
if (string.IsNullOrEmpty(userInfoEndpoint))
{
Logger.UserInfoEndpointNotSet();
return AuthenticateResult.Success(ticket);
return HandleRequestResult.Success(new AuthenticationTicket(principal, properties, Scheme.Name));
}
if (string.IsNullOrEmpty(message.AccessToken))
{
Logger.AccessTokenNotAvailable();
return AuthenticateResult.Success(ticket);
return HandleRequestResult.Success(new AuthenticationTicket(principal, properties, Scheme.Name));
}
Logger.RetrievingClaims();
var requestMessage = new HttpRequestMessage(HttpMethod.Get, userInfoEndpoint);
@ -801,16 +800,16 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
}
else
{
return AuthenticateResult.Fail("Unknown response type: " + contentType.MediaType);
return HandleRequestResult.Fail("Unknown response type: " + contentType.MediaType);
}
var userInformationReceivedContext = await RunUserInformationReceivedEventAsync(ticket, message, user);
AuthenticateResult result;
if (userInformationReceivedContext.IsProcessingComplete(out result))
var userInformationReceivedContext = await RunUserInformationReceivedEventAsync(principal, properties, message, user);
if (userInformationReceivedContext.Result != null)
{
return result;
return userInformationReceivedContext.Result;
}
ticket = userInformationReceivedContext.Ticket;
principal = userInformationReceivedContext.Principal;
properties = userInformationReceivedContext.Properties;
user = userInformationReceivedContext.User;
Options.ProtocolValidator.ValidateUserInfoResponse(new OpenIdConnectProtocolValidationContext()
@ -819,14 +818,14 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
ValidatedIdToken = jwt,
});
var identity = (ClaimsIdentity)ticket.Principal.Identity;
var identity = (ClaimsIdentity)principal.Identity;
foreach (var action in Options.ClaimActions)
{
action.Run(user, identity, ClaimsIssuer);
}
return AuthenticateResult.Success(ticket);
return HandleRequestResult.Success(new AuthenticationTicket(principal, properties, Scheme.Name));
}
/// <summary>
@ -983,51 +982,54 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
private async Task<MessageReceivedContext> RunMessageReceivedEventAsync(OpenIdConnectMessage message, AuthenticationProperties properties)
{
Logger.MessageReceived(message.BuildRedirectUrl());
var messageReceivedContext = new MessageReceivedContext(Context, Scheme, Options)
var context = new MessageReceivedContext(Context, Scheme, Options, properties)
{
ProtocolMessage = message,
Properties = properties,
};
await Events.MessageReceived(messageReceivedContext);
if (messageReceivedContext.HandledResponse)
await Events.MessageReceived(context);
if (context.Result != null)
{
Logger.MessageReceivedContextHandledResponse();
}
else if (messageReceivedContext.Skipped)
{
Logger.MessageReceivedContextSkipped();
if (context.Result.Handled)
{
Logger.MessageReceivedContextHandledResponse();
}
else if (context.Result.Skipped)
{
Logger.MessageReceivedContextSkipped();
}
}
return messageReceivedContext;
return context;
}
private async Task<TokenValidatedContext> RunTokenValidatedEventAsync(OpenIdConnectMessage authorizationResponse, OpenIdConnectMessage tokenEndpointResponse, AuthenticationProperties properties, AuthenticationTicket ticket, JwtSecurityToken jwt, string nonce)
private async Task<TokenValidatedContext> RunTokenValidatedEventAsync(OpenIdConnectMessage authorizationResponse, OpenIdConnectMessage tokenEndpointResponse, ClaimsPrincipal user, AuthenticationProperties properties, JwtSecurityToken jwt, string nonce)
{
var tokenValidatedContext = new TokenValidatedContext(Context, Scheme, Options)
var context = new TokenValidatedContext(Context, Scheme, Options, user, properties)
{
ProtocolMessage = authorizationResponse,
TokenEndpointResponse = tokenEndpointResponse,
Properties = properties,
Ticket = ticket,
SecurityToken = jwt,
Nonce = nonce,
};
await Events.TokenValidated(tokenValidatedContext);
if (tokenValidatedContext.HandledResponse)
await Events.TokenValidated(context);
if (context.Result != null)
{
Logger.TokenValidatedHandledResponse();
}
else if (tokenValidatedContext.Skipped)
{
Logger.TokenValidatedSkipped();
if (context.Result.Handled)
{
Logger.TokenValidatedHandledResponse();
}
else if (context.Result.Skipped)
{
Logger.TokenValidatedSkipped();
}
}
return tokenValidatedContext;
return context;
}
private async Task<AuthorizationCodeReceivedContext> RunAuthorizationCodeReceivedEventAsync(OpenIdConnectMessage authorizationResponse, AuthenticationProperties properties, AuthenticationTicket ticket, JwtSecurityToken jwt)
private async Task<AuthorizationCodeReceivedContext> RunAuthorizationCodeReceivedEventAsync(OpenIdConnectMessage authorizationResponse, ClaimsPrincipal user, AuthenticationProperties properties, JwtSecurityToken jwt)
{
Logger.AuthorizationCodeReceived();
@ -1041,102 +1043,112 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
RedirectUri = properties.Items[OpenIdConnectDefaults.RedirectUriForCodePropertiesKey]
};
var authorizationCodeReceivedContext = new AuthorizationCodeReceivedContext(Context, Scheme, Options)
var context = new AuthorizationCodeReceivedContext(Context, Scheme, Options, properties)
{
ProtocolMessage = authorizationResponse,
Properties = properties,
TokenEndpointRequest = tokenEndpointRequest,
Ticket = ticket,
Principal = user,
JwtSecurityToken = jwt,
Backchannel = Backchannel,
Backchannel = Backchannel
};
await Events.AuthorizationCodeReceived(authorizationCodeReceivedContext);
if (authorizationCodeReceivedContext.HandledResponse)
await Events.AuthorizationCodeReceived(context);
if (context.Result != null)
{
Logger.AuthorizationCodeReceivedContextHandledResponse();
}
else if (authorizationCodeReceivedContext.Skipped)
{
Logger.AuthorizationCodeReceivedContextSkipped();
if (context.Result.Handled)
{
Logger.AuthorizationCodeReceivedContextHandledResponse();
}
else if (context.Result.Skipped)
{
Logger.AuthorizationCodeReceivedContextSkipped();
}
}
return authorizationCodeReceivedContext;
return context;
}
private async Task<TokenResponseReceivedContext> RunTokenResponseReceivedEventAsync(
OpenIdConnectMessage message,
OpenIdConnectMessage tokenEndpointResponse,
AuthenticationProperties properties,
AuthenticationTicket ticket)
ClaimsPrincipal user,
AuthenticationProperties properties)
{
Logger.TokenResponseReceived();
var eventContext = new TokenResponseReceivedContext(Context, Scheme, Options, properties)
var context = new TokenResponseReceivedContext(Context, Scheme, Options, user, properties)
{
ProtocolMessage = message,
TokenEndpointResponse = tokenEndpointResponse,
Ticket = ticket
};
await Events.TokenResponseReceived(eventContext);
if (eventContext.HandledResponse)
await Events.TokenResponseReceived(context);
if (context.Result != null)
{
Logger.TokenResponseReceivedHandledResponse();
}
else if (eventContext.Skipped)
{
Logger.TokenResponseReceivedSkipped();
if (context.Result.Handled)
{
Logger.TokenResponseReceivedHandledResponse();
}
else if (context.Result.Skipped)
{
Logger.TokenResponseReceivedSkipped();
}
}
return eventContext;
return context;
}
private async Task<UserInformationReceivedContext> RunUserInformationReceivedEventAsync(AuthenticationTicket ticket, OpenIdConnectMessage message, JObject user)
private async Task<UserInformationReceivedContext> RunUserInformationReceivedEventAsync(ClaimsPrincipal principal, AuthenticationProperties properties, OpenIdConnectMessage message, JObject user)
{
Logger.UserInformationReceived(user.ToString());
var userInformationReceivedContext = new UserInformationReceivedContext(Context, Scheme, Options)
var context = new UserInformationReceivedContext(Context, Scheme, Options, principal, properties)
{
Ticket = ticket,
ProtocolMessage = message,
User = user,
};
await Events.UserInformationReceived(userInformationReceivedContext);
if (userInformationReceivedContext.HandledResponse)
await Events.UserInformationReceived(context);
if (context.Result != null)
{
Logger.UserInformationReceivedHandledResponse();
}
else if (userInformationReceivedContext.Skipped)
{
Logger.UserInformationReceivedSkipped();
if (context.Result.Handled)
{
Logger.UserInformationReceivedHandledResponse();
}
else if (context.Result.Skipped)
{
Logger.UserInformationReceivedSkipped();
}
}
return userInformationReceivedContext;
return context;
}
private async Task<AuthenticationFailedContext> RunAuthenticationFailedEventAsync(OpenIdConnectMessage message, Exception exception)
{
var authenticationFailedContext = new AuthenticationFailedContext(Context, Scheme, Options)
var context = new AuthenticationFailedContext(Context, Scheme, Options)
{
ProtocolMessage = message,
Exception = exception
};
await Events.AuthenticationFailed(authenticationFailedContext);
if (authenticationFailedContext.HandledResponse)
await Events.AuthenticationFailed(context);
if (context.Result != null)
{
Logger.AuthenticationFailedContextHandledResponse();
}
else if (authenticationFailedContext.Skipped)
{
Logger.AuthenticationFailedContextSkipped();
if (context.Result.Handled)
{
Logger.AuthenticationFailedContextHandledResponse();
}
else if (context.Result.Skipped)
{
Logger.AuthenticationFailedContextSkipped();
}
}
return authenticationFailedContext;
return context;
}
private AuthenticationTicket ValidateToken(string idToken, AuthenticationProperties properties, TokenValidationParameters validationParameters, out JwtSecurityToken jwt)
// Note this modifies properties if Options.UseTokenLifetime
private ClaimsPrincipal ValidateToken(string idToken, AuthenticationProperties properties, TokenValidationParameters validationParameters, out JwtSecurityToken jwt)
{
if (!Options.SecurityTokenValidator.CanReadToken(idToken))
{
@ -1173,24 +1185,22 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
throw new SecurityTokenException(string.Format(CultureInfo.InvariantCulture, Resources.UnableToValidateToken, idToken));
}
var ticket = new AuthenticationTicket(principal, properties, Scheme.Name);
if (Options.UseTokenLifetime)
{
var issued = validatedToken.ValidFrom;
if (issued != DateTime.MinValue)
{
ticket.Properties.IssuedUtc = issued;
properties.IssuedUtc = issued;
}
var expires = validatedToken.ValidTo;
if (expires != DateTime.MinValue)
{
ticket.Properties.ExpiresUtc = expires;
properties.ExpiresUtc = expires;
}
}
return ticket;
return principal;
}
/// <summary>

Просмотреть файл

@ -4,13 +4,8 @@
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;

Просмотреть файл

@ -19,99 +19,45 @@
"TypeId": "public interface Microsoft.AspNetCore.Authentication.OpenIdConnect.IOpenIdConnectEvents : Microsoft.AspNetCore.Authentication.IRemoteAuthenticationEvents",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.AuthenticationFailedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.OpenIdConnectOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.AuthorizationCodeReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.OpenIdConnectOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.AuthorizationCodeReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.AuthorizationCodeReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public System.Void set_Properties(Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties value)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext : Microsoft.AspNetCore.Authentication.BaseControlContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.OpenIdConnectOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext : Microsoft.AspNetCore.Authentication.BaseControlContext",
"MemberId": "public Microsoft.AspNetCore.Builder.OpenIdConnectOptions get_Options()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.MessageReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.OpenIdConnectOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.MessageReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.MessageReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public System.Void set_Properties(Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties value)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.TokenValidatedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.OpenIdConnectOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.TokenValidatedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.TokenValidatedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public System.Void set_Properties(Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties value)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.UserInformationReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.OpenIdConnectOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.RedirectContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.OpenIdConnectOptions options, Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties properties)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.RedirectContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.TokenResponseReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.OpenIdConnectOptions options, Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties properties)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.TokenResponseReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.RemoteSignOutContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.OpenIdConnectOptions options, Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectMessage message)",
"Kind": "Removal"
},
{
"TypeId": "public static class Microsoft.AspNetCore.Builder.OpenIdConnectAppBuilderExtensions",
"MemberId": "public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseOpenIdConnectAuthentication(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Builder.OpenIdConnectOptions options)",
"Kind": "Removal"
}
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.AuthenticationFailedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.AuthorizationCodeReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext : Microsoft.AspNetCore.Authentication.BaseControlContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.MessageReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.RedirectContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.RemoteSignOutContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.TokenResponseReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.TokenValidatedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.OpenIdConnect.UserInformationReceivedContext : Microsoft.AspNetCore.Authentication.OpenIdConnect.BaseOpenIdConnectContext",
"Kind": "Removal"
}
]

Просмотреть файл

@ -1,30 +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 Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication.Twitter
{
/// <summary>
/// Base class for other Twitter contexts.
/// </summary>
public class BaseTwitterContext : BaseAuthenticationContext
{
/// <summary>
/// Initializes a <see cref="BaseTwitterContext"/>
/// </summary>
/// <param name="context">The HTTP environment</param>
/// <param name="scheme">The scheme data</param>
/// <param name="options">The options for Twitter</param>
/// <param name="properties">The AuthenticationProperties</param>
public BaseTwitterContext(HttpContext context, AuthenticationScheme scheme, TwitterOptions options, AuthenticationProperties properties)
: base(context, scheme.Name, properties)
{
Options = options;
}
public TwitterOptions Options { get; }
public AuthenticationScheme Scheme { get; }
}
}

Просмотреть файл

@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
/// <summary>
/// Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.
/// </summary>
public class TwitterCreatingTicketContext : BaseTwitterContext
public class TwitterCreatingTicketContext : ResultContext<TwitterOptions>
{
/// <summary>
/// Initializes a <see cref="TwitterCreatingTicketContext"/>
@ -19,29 +19,33 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
/// <param name="context">The HTTP environment</param>
/// <param name="scheme">The scheme data</param>
/// <param name="options">The options for Twitter</param>
/// <param name="principal">The <see cref="ClaimsPrincipal"/>.</param>
/// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
/// <param name="userId">Twitter user ID</param>
/// <param name="screenName">Twitter screen name</param>
/// <param name="accessToken">Twitter access token</param>
/// <param name="accessTokenSecret">Twitter access token secret</param>
/// <param name="user">User details</param>
/// <param name="properties">AuthenticationProperties.</param>
public TwitterCreatingTicketContext(
HttpContext context,
AuthenticationScheme scheme,
TwitterOptions options,
ClaimsPrincipal principal,
AuthenticationProperties properties,
string userId,
string screenName,
string accessToken,
string accessTokenSecret,
JObject user)
: base(context, scheme, options, properties)
: base(context, scheme, options)
{
UserId = userId;
ScreenName = screenName;
AccessToken = accessToken;
AccessTokenSecret = accessTokenSecret;
User = user ?? new JObject();
Principal = principal;
Properties = properties;
}
/// <summary>
@ -69,10 +73,5 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
/// <see cref="JObject"/> if it is not available.
/// </summary>
public JObject User { get; }
/// <summary>
/// Gets the <see cref="ClaimsPrincipal"/> representing the user
/// </summary>
public ClaimsPrincipal Principal { get; set; }
}
}

Просмотреть файл

@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
/// <summary>
/// Gets or sets the delegate that is invoked when the ApplyRedirect method is invoked.
/// </summary>
public Func<TwitterRedirectToAuthorizationEndpointContext, Task> OnRedirectToAuthorizationEndpoint { get; set; } = context =>
public Func<RedirectContext<TwitterOptions>, Task> OnRedirectToAuthorizationEndpoint { get; set; } = context =>
{
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
@ -36,6 +36,6 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
/// Called when a Challenge causes a redirect to authorize endpoint in the Twitter handler
/// </summary>
/// <param name="context">Contains redirect URI and <see cref="Http.Authentication.AuthenticationProperties"/> of the challenge </param>
public virtual Task RedirectToAuthorizationEndpoint(TwitterRedirectToAuthorizationEndpointContext context) => OnRedirectToAuthorizationEndpoint(context);
public virtual Task RedirectToAuthorizationEndpoint(RedirectContext<TwitterOptions> context) => OnRedirectToAuthorizationEndpoint(context);
}
}

Просмотреть файл

@ -1,35 +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 Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication.Twitter
{
/// <summary>
/// The Context passed when a Challenge causes a redirect to authorize endpoint in the Twitter handler.
/// </summary>
public class TwitterRedirectToAuthorizationEndpointContext : BaseTwitterContext
{
/// <summary>
/// Creates a new context object.
/// </summary>
/// <param name="context">The HTTP request context.</param>
/// <param name="scheme">The scheme data</param>
/// <param name="options">The Twitter handler options.</param>
/// <param name="properties">The authentication properties of the challenge.</param>
/// <param name="redirectUri">The initial redirect URI.</param>
public TwitterRedirectToAuthorizationEndpointContext(HttpContext context, AuthenticationScheme scheme,
TwitterOptions options, AuthenticationProperties properties, string redirectUri)
: base(context, scheme, options, properties)
{
RedirectUri = redirectUri;
Properties = properties;
}
/// <summary>
/// Gets the URI used for the redirect operation.
/// </summary>
public string RedirectUri { get; private set; }
}
}

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Twitter;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
@ -10,6 +11,19 @@ namespace Microsoft.Extensions.DependencyInjection
{
public static class TwitterExtensions
{
public static AuthenticationBuilder AddTwitter(this AuthenticationBuilder builder)
=> builder.AddTwitter(TwitterDefaults.AuthenticationScheme, _ => { });
public static AuthenticationBuilder AddTwitter(this AuthenticationBuilder builder, Action<TwitterOptions> configureOptions)
=> builder.AddTwitter(TwitterDefaults.AuthenticationScheme, configureOptions);
public static AuthenticationBuilder AddTwitter(this AuthenticationBuilder builder, string authenticationScheme, Action<TwitterOptions> configureOptions)
{
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<TwitterOptions>, TwitterPostConfigureOptions>());
return builder.AddRemoteScheme<TwitterOptions, TwitterHandler>(authenticationScheme, authenticationScheme, configureOptions);
}
// REMOVE below once callers have been updated.
public static IServiceCollection AddTwitterAuthentication(this IServiceCollection services)
=> services.AddTwitterAuthentication(TwitterDefaults.AuthenticationScheme, _ => { });

Просмотреть файл

@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
protected override Task<object> CreateEventsAsync() => Task.FromResult<object>(new TwitterEvents());
protected override async Task<AuthenticateResult> HandleRemoteAuthenticateAsync()
protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync()
{
AuthenticationProperties properties = null;
var query = Request.Query;
@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
if (requestToken == null)
{
return AuthenticateResult.Fail("Invalid state cookie.");
return HandleRequestResult.Fail("Invalid state cookie.");
}
properties = requestToken.Properties;
@ -66,18 +66,18 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
var returnedToken = query["oauth_token"];
if (StringValues.IsNullOrEmpty(returnedToken))
{
return AuthenticateResult.Fail("Missing oauth_token");
return HandleRequestResult.Fail("Missing oauth_token");
}
if (!string.Equals(returnedToken, requestToken.Token, StringComparison.Ordinal))
{
return AuthenticateResult.Fail("Unmatched token");
return HandleRequestResult.Fail("Unmatched token");
}
var oauthVerifier = query["oauth_verifier"];
if (StringValues.IsNullOrEmpty(oauthVerifier))
{
return AuthenticateResult.Fail("Missing or blank oauth_verifier");
return HandleRequestResult.Fail("Missing or blank oauth_verifier");
}
var cookieOptions = new CookieOptions
@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
});
}
return AuthenticateResult.Success(await CreateTicketAsync(identity, properties, accessToken, user));
return HandleRequestResult.Success(await CreateTicketAsync(identity, properties, accessToken, user));
}
protected virtual async Task<AuthenticationTicket> CreateTicketAsync(
@ -127,18 +127,9 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
action.Run(user, identity, ClaimsIssuer);
}
var context = new TwitterCreatingTicketContext(Context, Scheme, Options, properties, token.UserId, token.ScreenName, token.Token, token.TokenSecret, user)
{
Principal = new ClaimsPrincipal(identity)
};
var context = new TwitterCreatingTicketContext(Context, Scheme, Options, new ClaimsPrincipal(identity), properties, token.UserId, token.ScreenName, token.Token, token.TokenSecret, user);
await Events.CreatingTicket(context);
if (context.Principal?.Identity == null)
{
return null;
}
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
}
@ -165,7 +156,7 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
Response.Cookies.Append(StateCookie, Options.StateDataFormat.Protect(requestToken), cookieOptions);
var redirectContext = new TwitterRedirectToAuthorizationEndpointContext(Context, Scheme, Options, properties, twitterAuthenticationEndpoint);
var redirectContext = new RedirectContext<TwitterOptions>(Context, Scheme, Options, properties, twitterAuthenticationEndpoint);
await Events.RedirectToAuthorizationEndpoint(redirectContext);
}

Просмотреть файл

@ -19,31 +19,6 @@
"TypeId": "public interface Microsoft.AspNetCore.Authentication.Twitter.ITwitterEvents : Microsoft.AspNetCore.Authentication.IRemoteAuthenticationEvents",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Twitter.TwitterRedirectToAuthorizationEndpointContext : Microsoft.AspNetCore.Authentication.Twitter.BaseTwitterContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.TwitterOptions options, Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties properties, System.String redirectUri)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Twitter.TwitterRedirectToAuthorizationEndpointContext : Microsoft.AspNetCore.Authentication.Twitter.BaseTwitterContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Twitter.TwitterCreatingTicketContext : Microsoft.AspNetCore.Authentication.Twitter.BaseTwitterContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.TwitterOptions options, System.String userId, System.String screenName, System.String accessToken, System.String accessTokenSecret, Newtonsoft.Json.Linq.JObject user)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Twitter.TwitterCreatingTicketContext : Microsoft.AspNetCore.Authentication.Twitter.BaseTwitterContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Twitter.TwitterCreatingTicketContext : Microsoft.AspNetCore.Authentication.Twitter.BaseTwitterContext",
"MemberId": "public System.Void set_Properties(Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties value)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Twitter.RequestToken",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
@ -58,5 +33,13 @@
"TypeId": "public static class Microsoft.AspNetCore.Builder.TwitterAppBuilderExtensions",
"MemberId": "public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseTwitterAuthentication(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Builder.TwitterOptions options)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Twitter.TwitterCreatingTicketContext : Microsoft.AspNetCore.Authentication.Twitter.BaseTwitterContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.Twitter.TwitterRedirectToAuthorizationEndpointContext : Microsoft.AspNetCore.Authentication.Twitter.BaseTwitterContext",
"Kind": "Removal"
}
]

Просмотреть файл

@ -0,0 +1,103 @@
// 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;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Authentication
{
/// <summary>
/// Used to configure authentication
/// </summary>
public class AuthenticationBuilder
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="services">The services being configured.</param>
public AuthenticationBuilder(IServiceCollection services)
=> Services = services;
/// <summary>
/// The services being configured.
/// </summary>
public virtual IServiceCollection Services { get; }
/// <summary>
/// Adds a <see cref="AuthenticationScheme"/> which can be used by <see cref="IAuthenticationService"/>.
/// </summary>
/// <typeparam name="TOptions">The <see cref="AuthenticationSchemeOptions"/> type to configure the handler."/>.</typeparam>
/// <typeparam name="THandler">The <see cref="AuthenticationHandler{TOptions}"/> used to handle this scheme.</typeparam>
/// <param name="authenticationScheme">The name of this scheme.</param>
/// <param name="displayName">The display name of this scheme.</param>
/// <param name="configureOptions">Used to configure the scheme options.</param>
/// <returns>The builder.</returns>
public virtual AuthenticationBuilder AddScheme<TOptions, THandler>(string authenticationScheme, string displayName, Action<TOptions> configureOptions)
where TOptions : AuthenticationSchemeOptions, new()
where THandler : AuthenticationHandler<TOptions>
{
Services.Configure<AuthenticationOptions>(o =>
{
o.AddScheme(authenticationScheme, scheme => {
scheme.HandlerType = typeof(THandler);
scheme.DisplayName = displayName;
});
});
if (configureOptions != null)
{
Services.Configure(authenticationScheme, configureOptions);
}
Services.AddTransient<THandler>();
return this;
}
/// <summary>
/// Adds a <see cref="AuthenticationScheme"/> which can be used by <see cref="IAuthenticationService"/>.
/// </summary>
/// <typeparam name="TOptions">The <see cref="AuthenticationSchemeOptions"/> type to configure the handler."/>.</typeparam>
/// <typeparam name="THandler">The <see cref="AuthenticationHandler{TOptions}"/> used to handle this scheme.</typeparam>
/// <param name="authenticationScheme">The name of this scheme.</param>
/// <param name="configureOptions">Used to configure the scheme options.</param>
/// <returns>The builder.</returns>
public virtual AuthenticationBuilder AddScheme<TOptions, THandler>(string authenticationScheme, Action<TOptions> configureOptions)
where TOptions : AuthenticationSchemeOptions, new()
where THandler : AuthenticationHandler<TOptions>
=> AddScheme<TOptions, THandler>(authenticationScheme, displayName: null, configureOptions: configureOptions);
/// <summary>
/// Adds a <see cref="RemoteAuthenticationHandler{TOptions}"/> based <see cref="AuthenticationScheme"/> that supports remote authentication
/// which can be used by <see cref="IAuthenticationService"/>.
/// </summary>
/// <typeparam name="TOptions">The <see cref="RemoteAuthenticationOptions"/> type to configure the handler."/>.</typeparam>
/// <typeparam name="THandler">The <see cref="RemoteAuthenticationHandler{TOptions}"/> used to handle this scheme.</typeparam>
/// <param name="authenticationScheme">The name of this scheme.</param>
/// <param name="displayName">The display name of this scheme.</param>
/// <param name="configureOptions">Used to configure the scheme options.</param>
/// <returns>The builder.</returns>
public virtual AuthenticationBuilder AddRemoteScheme<TOptions, THandler>(string authenticationScheme, string displayName, Action<TOptions> configureOptions)
where TOptions : RemoteAuthenticationOptions, new()
where THandler : RemoteAuthenticationHandler<TOptions>
{
Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<TOptions>, EnsureSignInScheme<TOptions>>());
return AddScheme<TOptions, THandler>(authenticationScheme, displayName, configureOptions: configureOptions);
}
// Used to ensure that there's always a default data protection provider
private class EnsureSignInScheme<TOptions> : IPostConfigureOptions<TOptions> where TOptions : RemoteAuthenticationOptions
{
private readonly AuthenticationOptions _authOptions;
public EnsureSignInScheme(IOptions<AuthenticationOptions> authOptions)
{
_authOptions = authOptions.Value;
}
public void PostConfigure(string name, TOptions options)
{
options.SignInScheme = options.SignInScheme ?? _authOptions.DefaultSignInScheme;
}
}
}
}

Просмотреть файл

@ -178,35 +178,6 @@ namespace Microsoft.AspNetCore.Authentication
protected abstract Task<AuthenticateResult> HandleAuthenticateAsync();
public async Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
properties = properties ?? new AuthenticationProperties();
await HandleSignInAsync(user, properties);
Logger.AuthenticationSchemeSignedIn(Scheme.Name);
}
protected virtual Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
{
return Task.CompletedTask;
}
public async Task SignOutAsync(AuthenticationProperties properties)
{
properties = properties ?? new AuthenticationProperties();
await HandleSignOutAsync(properties);
Logger.AuthenticationSchemeSignedOut(Scheme.Name);
}
protected virtual Task HandleSignOutAsync(AuthenticationProperties properties)
{
return Task.CompletedTask;
}
/// <summary>
/// Override this method to handle Forbid.
/// </summary>

Просмотреть файл

@ -13,7 +13,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary>
public static class AuthenticationServiceCollectionExtensions
{
public static IServiceCollection AddAuthentication(this IServiceCollection services)
public static AuthenticationBuilder AddAuthentication(this IServiceCollection services)
{
if (services == null)
{
@ -24,10 +24,10 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddDataProtection();
services.AddWebEncoders();
services.TryAddSingleton<ISystemClock, SystemClock>();
return services;
return new AuthenticationBuilder(services);
}
public static IServiceCollection AddAuthentication(this IServiceCollection services, Action<AuthenticationOptions> configureOptions) {
public static AuthenticationBuilder AddAuthentication(this IServiceCollection services, Action<AuthenticationOptions> configureOptions) {
if (services == null)
{
throw new ArgumentNullException(nameof(services));
@ -38,11 +38,12 @@ namespace Microsoft.Extensions.DependencyInjection
throw new ArgumentNullException(nameof(configureOptions));
}
services.AddAuthentication();
var builder = services.AddAuthentication();
services.Configure(configureOptions);
return services;
return builder;
}
// REMOVE below once callers have been updated
public static IServiceCollection AddScheme<TOptions, THandler>(this IServiceCollection services, string authenticationScheme, string displayName, Action<AuthenticationSchemeBuilder> configureScheme, Action<TOptions> configureOptions)
where TOptions : AuthenticationSchemeOptions, new()
where THandler : AuthenticationHandler<TOptions>

Просмотреть файл

@ -1,41 +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;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication
{
/// <summary>
/// Base context for authentication.
/// </summary>
public abstract class BaseAuthenticationContext : BaseContext
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="authenticationScheme">The name of the scheme.</param>
/// <param name="properties">The properties.</param>
protected BaseAuthenticationContext(HttpContext context, string authenticationScheme, AuthenticationProperties properties) : base(context)
{
if (string.IsNullOrEmpty(authenticationScheme))
{
throw new ArgumentException(nameof(authenticationScheme));
}
AuthenticationScheme = authenticationScheme;
Properties = properties ?? new AuthenticationProperties();
}
/// <summary>
/// The name of the scheme.
/// </summary>
public string AuthenticationScheme { get; }
/// <summary>
/// Contains the extra meta-data arriving with the authentication. May be altered.
/// </summary>
public AuthenticationProperties Properties { get; protected set; }
}
}

Просмотреть файл

@ -9,22 +9,44 @@ namespace Microsoft.AspNetCore.Authentication
/// <summary>
/// Base class used by other context classes.
/// </summary>
public abstract class BaseContext
public abstract class BaseContext<TOptions> where TOptions : AuthenticationSchemeOptions
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="context">The request context.</param>
protected BaseContext(HttpContext context)
/// <param name="context">The context.</param>
/// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The authentication options associated with the scheme.</param>
protected BaseContext(HttpContext context, AuthenticationScheme scheme, TOptions options)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (scheme == null)
{
throw new ArgumentNullException(nameof(scheme));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
HttpContext = context;
Scheme = scheme;
Options = options;
}
/// <summary>
/// The authentication scheme.
/// </summary>
public AuthenticationScheme Scheme { get; }
/// <summary>
/// Gets the authentication options associated with the scheme.
/// </summary>
public TOptions Options { get; }
/// <summary>
/// The context.
/// </summary>
@ -33,17 +55,11 @@ namespace Microsoft.AspNetCore.Authentication
/// <summary>
/// The request.
/// </summary>
public HttpRequest Request
{
get { return HttpContext.Request; }
}
public HttpRequest Request => HttpContext.Request;
/// <summary>
/// The response.
/// </summary>
public HttpResponse Response
{
get { return HttpContext.Response; }
}
public HttpResponse Response => HttpContext.Response;
}
}

Просмотреть файл

@ -1,78 +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 Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication
{
public class BaseControlContext : BaseContext
{
protected BaseControlContext(HttpContext context) : base(context)
{
}
public EventResultState State { get; set; }
public bool HandledResponse
{
get { return State == EventResultState.HandledResponse; }
}
public bool Skipped
{
get { return State == EventResultState.Skipped; }
}
/// <summary>
/// Discontinue all processing for this request and return to the client.
/// The caller is responsible for generating the full response.
/// Set the <see cref="Ticket"/> to trigger SignIn.
/// </summary>
public void HandleResponse()
{
State = EventResultState.HandledResponse;
}
/// <summary>
/// Discontinue processing the request in the current handler.
/// SignIn will not be called.
/// </summary>
public void Skip()
{
State = EventResultState.Skipped;
}
/// <summary>
/// Gets or set the <see cref="Ticket"/> to return if this event signals it handled the event.
/// </summary>
public AuthenticationTicket Ticket { get; set; }
/// <summary>
/// Returns true if the handler should be done processing.
/// </summary>
/// <param name="result">The result.</param>
/// <returns>Whether the handler should be done processing.</returns>
public bool IsProcessingComplete(out AuthenticateResult result)
{
if (HandledResponse)
{
if (Ticket == null)
{
result = AuthenticateResult.Handle();
}
else
{
result = AuthenticateResult.Success(Ticket);
}
return true;
}
else if (Skipped)
{
result = AuthenticateResult.None();
return true;
}
result = null;
return false;
}
}
}

Просмотреть файл

@ -1,23 +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.
namespace Microsoft.AspNetCore.Authentication
{
public enum EventResultState
{
/// <summary>
/// Continue with normal processing.
/// </summary>
Continue,
/// <summary>
/// Discontinue processing the request.
/// </summary>
Skipped,
/// <summary>
/// Discontinue all processing for this request.
/// </summary>
HandledResponse
}
}

Просмотреть файл

@ -0,0 +1,32 @@
// 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 Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication
{
public class HandleRequestContext<TOptions> : BaseContext<TOptions> where TOptions : AuthenticationSchemeOptions
{
protected HandleRequestContext(
HttpContext context,
AuthenticationScheme scheme,
TOptions options)
: base(context, scheme, options) { }
/// <summary>
/// The <see cref="HandleRequestResult"/> which is used by the handler.
/// </summary>
public HandleRequestResult Result { get; protected set; }
/// <summary>
/// Discontinue all processing for this request and return to the client.
/// The caller is responsible for generating the full response.
/// </summary>
public void HandleResponse() => Result = HandleRequestResult.Handle();
/// <summary>
/// Discontinue processing the request in the current handler.
/// </summary>
public void SkipHandler() => Result = HandleRequestResult.SkipHandler();
}
}

Просмотреть файл

@ -0,0 +1,30 @@
// 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.Security.Claims;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication
{
/// <summary>
/// Base context for authentication events which deal with a ClaimsPrincipal.
/// </summary>
public abstract class PrincipalContext<TOptions> : PropertiesContext<TOptions> where TOptions : AuthenticationSchemeOptions
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The authentication options associated with the scheme.</param>
/// <param name="properties">The authentication properties.</param>
protected PrincipalContext(HttpContext context, AuthenticationScheme scheme, TOptions options, AuthenticationProperties properties)
: base(context, scheme, options, properties) { }
/// <summary>
/// Gets the <see cref="ClaimsPrincipal"/> containing the user claims.
/// </summary>
public virtual ClaimsPrincipal Principal { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,31 @@
// 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 Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication
{
/// <summary>
/// Base context for authentication events which contain <see cref="AuthenticationProperties"/>.
/// </summary>
public abstract class PropertiesContext<TOptions> : BaseContext<TOptions> where TOptions : AuthenticationSchemeOptions
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The authentication options associated with the scheme.</param>
/// <param name="properties">The authentication properties.</param>
protected PropertiesContext(HttpContext context, AuthenticationScheme scheme, TOptions options, AuthenticationProperties properties)
: base(context, scheme, options)
{
Properties = properties ?? new AuthenticationProperties();
}
/// <summary>
/// Gets or sets the <see cref="AuthenticationProperties"/>.
/// </summary>
public virtual AuthenticationProperties Properties { get; protected set; }
}
}

Просмотреть файл

@ -1,28 +1,32 @@
// 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 Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Authentication;
namespace Microsoft.AspNetCore.Authentication.Cookies
namespace Microsoft.AspNetCore.Authentication
{
/// <summary>
/// Context passed when a Challenge, SignIn, or SignOut causes a redirect in the cookie handler
/// Context passed for redirect events.
/// </summary>
public class CookieRedirectContext : BaseCookieContext
public class RedirectContext<TOptions> : PropertiesContext<TOptions> where TOptions : AuthenticationSchemeOptions
{
/// <summary>
/// Creates a new context object.
/// </summary>
/// <param name="context">The HTTP request context</param>
/// <param name="scheme">The scheme data</param>
/// <param name="options">The cookie handler options</param>
/// <param name="options">The 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)
public RedirectContext(
HttpContext context,
AuthenticationScheme scheme,
TOptions options,
AuthenticationProperties properties,
string redirectUri)
: base(context, scheme, options, properties)
{
Properties = properties;
RedirectUri = redirectUri;
}

Просмотреть файл

@ -0,0 +1,49 @@
// 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.Security.Claims;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication
{
/// <summary>
/// Base context for remote authentication.
/// </summary>
public abstract class RemoteAuthenticationContext<TOptions> : HandleRequestContext<TOptions> where TOptions : AuthenticationSchemeOptions
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The authentication options associated with the scheme.</param>
/// <param name="properties">The authentication properties.</param>
protected RemoteAuthenticationContext(
HttpContext context,
AuthenticationScheme scheme,
TOptions options,
AuthenticationProperties properties)
: base(context, scheme, options)
=> Properties = properties ?? new AuthenticationProperties();
/// <summary>
/// Gets the <see cref="ClaimsPrincipal"/> containing the user claims.
/// </summary>
public ClaimsPrincipal Principal { get; set; }
/// <summary>
/// Gets or sets the <see cref="AuthenticationProperties"/>.
/// </summary>
public virtual AuthenticationProperties Properties { get; set; }
/// <summary>
/// Calls success creating a ticket with the <see cref="Principal"/> and <see cref="Properties"/>.
/// </summary>
public void Success() => Result = HandleRequestResult.Success(new AuthenticationTicket(Principal, Properties, Scheme.Name));
public void Fail(Exception failure) => Result = HandleRequestResult.Fail(failure);
public void Fail(string failureMessage) => Result = HandleRequestResult.Fail(failureMessage);
}
}

Просмотреть файл

@ -8,14 +8,14 @@ namespace Microsoft.AspNetCore.Authentication
{
public class RemoteAuthenticationEvents
{
public Func<FailureContext, Task> OnRemoteFailure { get; set; } = context => Task.CompletedTask;
public Func<RemoteFailureContext, Task> OnRemoteFailure { get; set; } = context => Task.CompletedTask;
public Func<TicketReceivedContext, Task> OnTicketReceived { get; set; } = context => Task.CompletedTask;
/// <summary>
/// Invoked when there is a remote failure
/// </summary>
public virtual Task RemoteFailure(FailureContext context) => OnRemoteFailure(context);
public virtual Task RemoteFailure(RemoteFailureContext context) => OnRemoteFailure(context);
/// <summary>
/// Invoked after the remote ticket has been received.

Просмотреть файл

@ -9,10 +9,14 @@ namespace Microsoft.AspNetCore.Authentication
/// <summary>
/// Provides failure context information to handler providers.
/// </summary>
public class FailureContext : BaseControlContext
public class RemoteFailureContext : HandleRequestContext<RemoteAuthenticationOptions>
{
public FailureContext(HttpContext context, Exception failure)
: base(context)
public RemoteFailureContext(
HttpContext context,
AuthenticationScheme scheme,
RemoteAuthenticationOptions options,
Exception failure)
: base(context, scheme, options)
{
Failure = failure;
}

Просмотреть файл

@ -0,0 +1,65 @@
// 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.Security.Claims;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Authentication
{
/// <summary>
/// Base context for events that produce AuthenticateResults.
/// </summary>
public abstract class ResultContext<TOptions> : BaseContext<TOptions> where TOptions : AuthenticationSchemeOptions
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="scheme">The authentication scheme.</param>
/// <param name="options">The authentication options associated with the scheme.</param>
protected ResultContext(HttpContext context, AuthenticationScheme scheme, TOptions options)
: base(context, scheme, options) { }
/// <summary>
/// Gets or sets the <see cref="ClaimsPrincipal"/> containing the user claims.
/// </summary>
public ClaimsPrincipal Principal { get; set; }
private AuthenticationProperties _properties;
/// <summary>
/// Gets or sets the <see cref="AuthenticationProperties"/>.
/// </summary>
public AuthenticationProperties Properties {
get => _properties ?? (_properties = new AuthenticationProperties());
set => _properties = value;
}
/// <summary>
/// Gets the <see cref="AuthenticateResult"/> result.
/// </summary>
public AuthenticateResult Result { get; private set; }
/// <summary>
/// Calls success creating a ticket with the <see cref="Principal"/> and <see cref="Properties"/>.
/// </summary>
public void Success() => Result = HandleRequestResult.Success(new AuthenticationTicket(Principal, Properties, Scheme.Name));
/// <summary>
/// Indicates that there was no information returned for this authentication scheme.
/// </summary>
public void NoResult() => Result = AuthenticateResult.NoResult();
/// <summary>
/// Indicates that there was a failure during authentication.
/// </summary>
/// <param name="failure"></param>
public void Fail(Exception failure) => Result = AuthenticateResult.Fail(failure);
/// <summary>
/// Indicates that there was a failure during authentication.
/// </summary>
/// <param name="failureMessage"></param>
public void Fail(string failureMessage) => Result = AuthenticateResult.Fail(failureMessage);
}
}

Просмотреть файл

@ -3,30 +3,21 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Authentication;
namespace Microsoft.AspNetCore.Authentication
{
/// <summary>
/// Provides context information to handler providers.
/// </summary>
public class TicketReceivedContext : BaseControlContext
public class TicketReceivedContext : RemoteAuthenticationContext<RemoteAuthenticationOptions>
{
public TicketReceivedContext(HttpContext context, RemoteAuthenticationOptions options, AuthenticationTicket ticket)
: base(context)
{
Options = options;
Ticket = ticket;
if (ticket != null)
{
Principal = ticket.Principal;
Properties = ticket.Properties;
}
}
public ClaimsPrincipal Principal { get; set; }
public AuthenticationProperties Properties { get; set; }
public RemoteAuthenticationOptions Options { get; set; }
public TicketReceivedContext(
HttpContext context,
AuthenticationScheme scheme,
RemoteAuthenticationOptions options,
AuthenticationTicket ticket)
: base(context, scheme, options, ticket?.Properties)
=> Principal = ticket?.Principal;
public string ReturnUri { get; set; }
}

Просмотреть файл

@ -9,14 +9,8 @@ namespace Microsoft.Extensions.Logging
{
private static Action<ILogger, string, Exception> _authSchemeAuthenticated;
private static Action<ILogger, string, Exception> _authSchemeNotAuthenticated;
private static Action<ILogger, string, string, Exception> _authSchemeNotAuthenticatedWithFailure;
private static Action<ILogger, string, Exception> _authSchemeSignedIn;
private static Action<ILogger, string, Exception> _authSchemeSignedOut;
private static Action<ILogger, string, Exception> _authSchemeChallenged;
private static Action<ILogger, string, Exception> _authSchemeForbidden;
private static Action<ILogger, string, Exception> _userAuthorizationFailed;
private static Action<ILogger, string, Exception> _userAuthorizationSucceeded;
private static Action<ILogger, string, Exception> _userPrincipalMerged;
private static Action<ILogger, string, Exception> _remoteAuthenticationError;
private static Action<ILogger, Exception> _signInHandled;
private static Action<ILogger, Exception> _signInSkipped;
@ -26,18 +20,6 @@ namespace Microsoft.Extensions.Logging
static LoggingExtensions()
{
_userAuthorizationSucceeded = LoggerMessage.Define<string>(
eventId: 1,
logLevel: LogLevel.Information,
formatString: "Authorization was successful for user: {UserName}.");
_userAuthorizationFailed = LoggerMessage.Define<string>(
eventId: 2,
logLevel: LogLevel.Information,
formatString: "Authorization failed for user: {UserName}.");
_userPrincipalMerged = LoggerMessage.Define<string>(
eventId: 3,
logLevel: LogLevel.Information,
formatString: "HttpContext.User merged via AutomaticAuthentication from authenticationScheme: {AuthenticationScheme}.");
_remoteAuthenticationError = LoggerMessage.Define<string>(
eventId: 4,
logLevel: LogLevel.Information,
@ -50,10 +32,6 @@ namespace Microsoft.Extensions.Logging
eventId: 6,
logLevel: LogLevel.Debug,
formatString: "The SigningIn event returned Skipped.");
_authSchemeNotAuthenticatedWithFailure = LoggerMessage.Define<string, string>(
eventId: 7,
logLevel: LogLevel.Information,
formatString: "{AuthenticationScheme} was not authenticated. Failure message: {FailureMessage}");
_authSchemeAuthenticated = LoggerMessage.Define<string>(
eventId: 8,
logLevel: LogLevel.Information,
@ -62,14 +40,6 @@ namespace Microsoft.Extensions.Logging
eventId: 9,
logLevel: LogLevel.Debug,
formatString: "AuthenticationScheme: {AuthenticationScheme} was not authenticated.");
_authSchemeSignedIn = LoggerMessage.Define<string>(
eventId: 10,
logLevel: LogLevel.Information,
formatString: "AuthenticationScheme: {AuthenticationScheme} signed in.");
_authSchemeSignedOut = LoggerMessage.Define<string>(
eventId: 11,
logLevel: LogLevel.Information,
formatString: "AuthenticationScheme: {AuthenticationScheme} signed out.");
_authSchemeChallenged = LoggerMessage.Define<string>(
eventId: 12,
logLevel: LogLevel.Information,
@ -102,21 +72,6 @@ namespace Microsoft.Extensions.Logging
_authSchemeNotAuthenticated(logger, authenticationScheme, null);
}
public static void AuthenticationSchemeNotAuthenticatedWithFailure(this ILogger logger, string authenticationScheme, string failureMessage)
{
_authSchemeNotAuthenticatedWithFailure(logger, authenticationScheme, failureMessage, null);
}
public static void AuthenticationSchemeSignedIn(this ILogger logger, string authenticationScheme)
{
_authSchemeSignedIn(logger, authenticationScheme, null);
}
public static void AuthenticationSchemeSignedOut(this ILogger logger, string authenticationScheme)
{
_authSchemeSignedOut(logger, authenticationScheme, null);
}
public static void AuthenticationSchemeChallenged(this ILogger logger, string authenticationScheme)
{
_authSchemeChallenged(logger, authenticationScheme, null);
@ -127,21 +82,6 @@ namespace Microsoft.Extensions.Logging
_authSchemeForbidden(logger, authenticationScheme, null);
}
public static void UserAuthorizationSucceeded(this ILogger logger, string userName)
{
_userAuthorizationSucceeded(logger, userName, null);
}
public static void UserAuthorizationFailed(this ILogger logger, string userName)
{
_userAuthorizationFailed(logger, userName, null);
}
public static void UserPrinicpalMerged(this ILogger logger, string authenticationScheme)
{
_userPrincipalMerged(logger, authenticationScheme, null);
}
public static void RemoteAuthenticationError(this ILogger logger, string errorMessage)
{
_remoteAuthenticationError(logger, errorMessage, null);

Просмотреть файл

@ -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.Security.Claims;
using System.Security.Cryptography;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
@ -35,19 +34,13 @@ namespace Microsoft.AspNetCore.Authentication
}
protected RemoteAuthenticationHandler(IOptionsSnapshot<TOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{
}
: base(options, logger, encoder, clock) { }
protected override Task<object> CreateEventsAsync()
{
return Task.FromResult<object>(new RemoteAuthenticationEvents());
}
=> Task.FromResult<object>(new RemoteAuthenticationEvents());
public virtual Task<bool> ShouldHandleRequestAsync()
{
return Task.FromResult(Options.CallbackPath == Request.Path);
}
=> Task.FromResult(Options.CallbackPath == Request.Path);
public virtual async Task<bool> HandleRequestAsync()
{
@ -69,7 +62,7 @@ namespace Microsoft.AspNetCore.Authentication
{
return true;
}
else if (authResult.Nothing)
else if (authResult.Skipped || authResult.None)
{
return false;
}
@ -89,25 +82,28 @@ namespace Microsoft.AspNetCore.Authentication
if (exception != null)
{
Logger.RemoteAuthenticationError(exception.Message);
var errorContext = new FailureContext(Context, exception);
var errorContext = new RemoteFailureContext(Context, Scheme, Options, exception);
await Events.RemoteFailure(errorContext);
if (errorContext.HandledResponse)
if (errorContext.Result != null)
{
return true;
}
else if (errorContext.Skipped)
{
return false;
if (errorContext.Result.Handled)
{
return true;
}
else if (errorContext.Result.Skipped)
{
return false;
}
}
throw new AggregateException("Unhandled remote failure.", exception);
throw exception;
}
// We have a ticket if we get here
var ticketContext = new TicketReceivedContext(Context, Options, ticket)
var ticketContext = new TicketReceivedContext(Context, Scheme, Options, ticket)
{
ReturnUri = ticket.Properties.RedirectUri,
ReturnUri = ticket.Properties.RedirectUri
};
// REVIEW: is this safe or good?
ticket.Properties.RedirectUri = null;
@ -117,15 +113,18 @@ namespace Microsoft.AspNetCore.Authentication
await Events.TicketReceived(ticketContext);
if (ticketContext.HandledResponse)
if (ticketContext.Result != null)
{
Logger.SigninHandled();
return true;
}
else if (ticketContext.Skipped)
{
Logger.SigninSkipped();
return false;
if (ticketContext.Result.Handled)
{
Logger.SigninHandled();
return true;
}
else if (ticketContext.Result.Skipped)
{
Logger.SigninSkipped();
return false;
}
}
await Context.SignInAsync(SignInScheme, ticketContext.Principal, ticketContext.Properties);
@ -145,7 +144,7 @@ namespace Microsoft.AspNetCore.Authentication
///
/// The method process the request on the endpoint defined by CallbackPath.
/// </summary>
protected abstract Task<AuthenticateResult> HandleRemoteAuthenticateAsync();
protected abstract Task<HandleRequestResult> HandleRemoteAuthenticateAsync();
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
@ -174,20 +173,8 @@ namespace Microsoft.AspNetCore.Authentication
return AuthenticateResult.Fail("Remote authentication does not directly support AuthenticateAsync");
}
protected override Task HandleSignOutAsync(AuthenticationProperties properties)
{
throw new NotSupportedException();
}
protected override Task HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
{
throw new NotSupportedException();
}
protected override Task HandleForbiddenAsync(AuthenticationProperties properties)
{
return Context.ForbidAsync(SignInScheme);
}
=> Context.ForbidAsync(SignInScheme);
protected virtual void GenerateCorrelationId(AuthenticationProperties properties)
{

Просмотреть файл

@ -23,11 +23,6 @@ namespace Microsoft.AspNetCore.Authentication
{
throw new ArgumentException(Resources.FormatException_OptionMustBeProvided(nameof(CallbackPath)), nameof(CallbackPath));
}
if (string.IsNullOrEmpty(SignInScheme))
{
throw new ArgumentException(Resources.FormatException_OptionMustBeProvided(nameof(SignInScheme)), nameof(SignInScheme));
}
}
/// <summary>

Просмотреть файл

@ -0,0 +1,78 @@
// 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;
namespace Microsoft.AspNetCore.Authentication
{
/// <summary>
/// Contains the result of an Authenticate call
/// </summary>
public class HandleRequestResult : AuthenticateResult
{
/// <summary>
/// Indicates that stage of authentication was directly handled by
/// user intervention and no further processing should be attempted.
/// </summary>
public bool Handled { get; private set; }
/// <summary>
/// Indicates that the default authentication logic should be
/// skipped and that the rest of the pipeline should be invoked.
/// </summary>
public bool Skipped { get; private set; }
/// <summary>
/// Indicates that authentication was successful.
/// </summary>
/// <param name="ticket">The ticket representing the authentication result.</param>
/// <returns>The result.</returns>
public static new HandleRequestResult Success(AuthenticationTicket ticket)
{
if (ticket == null)
{
throw new ArgumentNullException(nameof(ticket));
}
return new HandleRequestResult() { Ticket = ticket };
}
/// <summary>
/// Indicates that there was a failure during authentication.
/// </summary>
/// <param name="failure">The failure exception.</param>
/// <returns>The result.</returns>
public static new HandleRequestResult Fail(Exception failure)
{
return new HandleRequestResult() { Failure = failure };
}
/// <summary>
/// Indicates that there was a failure during authentication.
/// </summary>
/// <param name="failureMessage">The failure message.</param>
/// <returns>The result.</returns>
public static new HandleRequestResult Fail(string failureMessage)
{
return new HandleRequestResult() { Failure = new Exception(failureMessage) };
}
/// <summary>
/// Discontinue all processing for this request and return to the client.
/// The caller is responsible for generating the full response.
/// </summary>
/// <returns>The result.</returns>
public static HandleRequestResult Handle()
{
return new HandleRequestResult() { Handled = true };
}
/// <summary>
/// Discontinue processing the request in the current handler.
/// </summary>
/// <returns>The result.</returns>
public static HandleRequestResult SkipHandler()
{
return new HandleRequestResult() { Skipped = true };
}
}
}

Просмотреть файл

@ -83,44 +83,34 @@
"TypeId": "public static class Microsoft.AspNetCore.Builder.ClaimsTransformationAppBuilderExtensions",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.TicketReceivedContext : Microsoft.AspNetCore.Authentication.BaseControlContext",
"MemberId": "public .ctor(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.RemoteAuthenticationOptions options, Microsoft.AspNetCore.Authentication.AuthenticationTicket ticket)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.TicketReceivedContext : Microsoft.AspNetCore.Authentication.BaseControlContext",
"MemberId": "public Microsoft.AspNetCore.Builder.RemoteAuthenticationOptions get_Options()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.TicketReceivedContext : Microsoft.AspNetCore.Authentication.BaseControlContext",
"MemberId": "public Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties get_Properties()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.TicketReceivedContext : Microsoft.AspNetCore.Authentication.BaseControlContext",
"MemberId": "public System.Void set_Options(Microsoft.AspNetCore.Builder.RemoteAuthenticationOptions value)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.TicketReceivedContext : Microsoft.AspNetCore.Authentication.BaseControlContext",
"MemberId": "public System.Void set_Properties(Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties value)",
"Kind": "Removal"
},
{
"TypeId": "public static class Microsoft.Extensions.DependencyInjection.AuthenticationServiceCollectionExtensions",
"MemberId": "public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddAuthentication(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<Microsoft.AspNetCore.Authentication.SharedAuthenticationOptions> configureOptions)",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.BaseControlContext : Microsoft.AspNetCore.Authentication.BaseContext",
"MemberId": "public System.Boolean CheckEventResult(out Microsoft.AspNetCore.Authentication.AuthenticateResult result)",
"TypeId": "public abstract class Microsoft.AspNetCore.Authentication.BaseContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.BaseControlContext : Microsoft.AspNetCore.Authentication.BaseContext",
"MemberId": "public System.Void SkipToNextMiddleware()",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.FailureContext : Microsoft.AspNetCore.Authentication.BaseControlContext",
"Kind": "Removal"
},
{
"TypeId": "public class Microsoft.AspNetCore.Authentication.TicketReceivedContext : Microsoft.AspNetCore.Authentication.BaseControlContext",
"Kind": "Removal"
},
{
"TypeId": "public static class Microsoft.Extensions.DependencyInjection.AuthenticationServiceCollectionExtensions",
"MemberId": "public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddAuthentication(this Microsoft.Extensions.DependencyInjection.IServiceCollection services)",
"Kind": "Removal"
},
{
"TypeId": "public enum Microsoft.AspNetCore.Authentication.EventResultState",
"Kind": "Removal"
}
]

Просмотреть файл

@ -52,13 +52,13 @@ namespace Microsoft.AspNetCore.Authorization.Policy
else
{
context.User = new ClaimsPrincipal(new ClaimsIdentity());
return AuthenticateResult.None();
return AuthenticateResult.NoResult();
}
}
return (context.User?.Identity?.IsAuthenticated ?? false)
? AuthenticateResult.Success(new AuthenticationTicket(context.User, "context.User"))
: AuthenticateResult.None();
: AuthenticateResult.NoResult();
}
/// <summary>

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
@ -29,7 +30,8 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
[Fact]
public async Task VerifySchemeDefaults()
{
var services = new ServiceCollection().AddCookieAuthentication();
var services = new ServiceCollection();
services.AddAuthentication().AddCookie();
var sp = services.BuildServiceProvider();
var schemeProvider = sp.GetRequiredService<IAuthenticationSchemeProvider>();
var scheme = await schemeProvider.GetSchemeAsync(CookieAuthenticationDefaults.AuthenticationScheme);
@ -124,7 +126,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
[Fact]
public async Task SignInCausesDefaultCookieToBeCreated()
{
var server = CreateServerWithServices(s => s.AddCookieAuthentication(o =>
var server = CreateServerWithServices(s => s.AddAuthentication().AddCookie(o =>
{
o.LoginPath = new PathString("/login");
o.CookieName = "TestCookie";
@ -772,7 +774,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
}
app.Map("/login", signoutApp => signoutApp.Run(context => context.ChallengeAsync("Cookies", new AuthenticationProperties() { RedirectUri = "/" })));
})
.ConfigureServices(s => s.AddCookieAuthentication(o => o.LoginPath = new PathString("/page")));
.ConfigureServices(s => s.AddAuthentication().AddCookie(o => o.LoginPath = new PathString("/page")));
var server = new TestServer(builder);
var transaction = await server.SendAsync("http://example.com/login");
@ -803,7 +805,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
await Assert.ThrowsAsync<InvalidOperationException>(() => context.ChallengeAsync(CookieAuthenticationDefaults.AuthenticationScheme));
});
})
.ConfigureServices(services => services.AddCookieAuthentication());
.ConfigureServices(services => services.AddAuthentication().AddCookie());
var server = new TestServer(builder);
var transaction = await server.SendAsync("http://example.com");
@ -821,7 +823,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
})
.ConfigureServices(services =>
{
services.AddCookieAuthentication();
services.AddAuthentication().AddCookie();
services.Configure<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme,
o => o.CookieName = "One");
});
@ -844,7 +846,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
})
.ConfigureServices(services =>
{
services.AddCookieAuthentication("Cookie1");
services.AddAuthentication().AddCookie("Cookie1");
services.Configure<CookieAuthenticationOptions>("Cookie1",
o => o.CookieName = "One");
});
@ -866,7 +868,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
app.Map("/notlogin", signoutApp => signoutApp.Run(context => context.SignInAsync("Cookies",
new ClaimsPrincipal())));
})
.ConfigureServices(services => services.AddCookieAuthentication(o => o.LoginPath = new PathString("/login")));
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.LoginPath = new PathString("/login")));
var server = new TestServer(builder);
var transaction = await server.SendAsync("http://example.com/notlogin?ReturnUrl=%2Fpage");
@ -883,7 +885,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
app.UseAuthentication();
app.Map("/login", signoutApp => signoutApp.Run(context => context.SignInAsync("Cookies", new ClaimsPrincipal())));
})
.ConfigureServices(services => services.AddCookieAuthentication(o => o.LoginPath = new PathString("/login")));
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.LoginPath = new PathString("/login")));
var server = new TestServer(builder);
@ -905,7 +907,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
app.UseAuthentication();
app.Map("/notlogout", signoutApp => signoutApp.Run(context => context.SignOutAsync("Cookies")));
})
.ConfigureServices(services => services.AddCookieAuthentication(o => o.LogoutPath = new PathString("/logout")));
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.LogoutPath = new PathString("/logout")));
var server = new TestServer(builder);
var transaction = await server.SendAsync("http://example.com/notlogout?ReturnUrl=%2Fpage");
@ -922,7 +924,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
app.UseAuthentication();
app.Map("/logout", signoutApp => signoutApp.Run(context => context.SignOutAsync("Cookies")));
})
.ConfigureServices(services => services.AddCookieAuthentication(o => o.LogoutPath = new PathString("/logout")));
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.LogoutPath = new PathString("/logout")));
var server = new TestServer(builder);
var transaction = await server.SendAsync("http://example.com/logout?ReturnUrl=%2Fpage");
@ -943,7 +945,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
app.UseAuthentication();
app.Map("/forbid", signoutApp => signoutApp.Run(context => context.ForbidAsync("Cookies")));
})
.ConfigureServices(services => services.AddCookieAuthentication(o => o.AccessDeniedPath = new PathString("/denied")));
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.AccessDeniedPath = new PathString("/denied")));
var server = new TestServer(builder);
var transaction = await server.SendAsync("http://example.com/forbid");
@ -963,7 +965,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
map.UseAuthentication();
map.Map("/login", signoutApp => signoutApp.Run(context => context.ChallengeAsync("Cookies", new AuthenticationProperties() { RedirectUri = "/" })));
}))
.ConfigureServices(services => services.AddCookieAuthentication(o => o.LoginPath = new PathString("/page")));
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.LoginPath = new PathString("/page")));
var server = new TestServer(builder);
var transaction = await server.SendAsync("http://example.com/base/login");
@ -1073,7 +1075,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
map.UseAuthentication();
map.Map("/forbid", signoutApp => signoutApp.Run(context => context.ForbidAsync("Cookies")));
}))
.ConfigureServices(services => services.AddCookieAuthentication(o => o.AccessDeniedPath = new PathString("/denied")));
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.AccessDeniedPath = new PathString("/denied")));
var server = new TestServer(builder);
var transaction = await server.SendAsync("http://example.com/base/forbid");
@ -1097,7 +1099,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
new ClaimsPrincipal(new ClaimsIdentity(new GenericIdentity("Alice", "Cookies"))),
new AuthenticationProperties()));
})
.ConfigureServices(services => services.AddCookieAuthentication(o =>
.ConfigureServices(services => services.AddAuthentication().AddCookie(o =>
{
o.TicketDataFormat = new TicketDataFormat(dp);
o.CookieName = "Cookie";
@ -1117,7 +1119,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
Describe(context.Response, result);
});
})
.ConfigureServices(services => services.AddCookieAuthentication("Cookies", o =>
.ConfigureServices(services => services.AddAuthentication().AddCookie("Cookies", o =>
{
o.CookieName = "Cookie";
o.TicketDataFormat = new TicketDataFormat(dp);
@ -1132,7 +1134,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
public async Task NullExpiresUtcPropertyIsGuarded()
{
var builder = new WebHostBuilder()
.ConfigureServices(services => services.AddCookieAuthentication(o =>
.ConfigureServices(services => services.AddAuthentication().AddCookie(o =>
{
o.Events = new CookieAuthenticationEvents
{
@ -1229,7 +1231,7 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
=> CreateServerWithServices(s =>
{
s.AddSingleton<ISystemClock>(_clock);
s.AddCookieAuthentication(configureOptions);
s.AddAuthentication().AddCookie(configureOptions);
s.AddSingleton<IClaimsTransformation, ClaimsTransformer>();
}, testpath, baseAddress);
@ -1281,6 +1283,15 @@ namespace Microsoft.AspNetCore.Authentication.Cookies
{
await testpath(context);
}
else if (req.Path == new PathString("/checkforerrors"))
{
var result = await context.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme); // this used to be "Automatic"
if (result.Failure != null)
{
throw new Exception("Failed to authenticate", result.Failure);
}
return;
}
else
{
await next();

Просмотреть файл

@ -85,9 +85,9 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
{
options.DefaultSignInScheme = "External";
options.DefaultAuthenticateScheme = "External";
});
services.AddCookieAuthentication("External", o => { });
services.AddFacebookAuthentication(o =>
})
.AddCookie("External", o => { })
.AddFacebook(o =>
{
o.AppId = "Test App Id";
o.AppSecret = "Test App Secret";
@ -123,12 +123,12 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
}),
services =>
{
services.AddCookieAuthentication("External", o => { });
services.AddFacebookAuthentication(o =>
services.AddAuthentication()
.AddCookie("External", o => { })
.AddFacebook(o =>
{
o.AppId = "Test App Id";
o.AppSecret = "Test App Secret";
o.SignInScheme = "External";
});
},
handler: null);
@ -155,8 +155,9 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
},
services =>
{
services.AddCookieAuthentication("External", o => { });
services.AddFacebookAuthentication(o =>
services.AddAuthentication()
.AddCookie("External", o => { })
.AddFacebook(o =>
{
o.AppId = "Test App Id";
o.AppSecret = "Test App Secret";
@ -185,9 +186,9 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
services.AddAuthentication(options =>
{
options.DefaultSignInScheme = "External";
});
services.AddCookieAuthentication();
services.AddFacebookAuthentication(o =>
})
.AddCookie()
.AddFacebook(o =>
{
o.AppId = "Test App Id";
o.AppSecret = "Test App Secret";
@ -217,19 +218,15 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
var finalUserInfoEndpoint = string.Empty;
var stateFormat = new PropertiesDataFormat(new EphemeralDataProtectionProvider(NullLoggerFactory.Instance).CreateProtector("FacebookTest"));
var server = CreateServer(
app =>
{
app.UseAuthentication();
},
app => app.UseAuthentication(),
services =>
{
services.AddAuthentication(options =>
{
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
});
services.AddCookieAuthentication();
services.AddFacebookAuthentication(o =>
})
.AddCookie()
.AddFacebook(o =>
{
o.AppId = "Test App Id";
o.AppSecret = "Test App Secret";

Просмотреть файл

@ -516,7 +516,7 @@ namespace Microsoft.AspNetCore.Authentication.Google
OnCreatingTicket = context =>
{
var refreshToken = context.RefreshToken;
context.Ticket.Principal.AddIdentity(new ClaimsIdentity(new Claim[] { new Claim("RefreshToken", refreshToken, ClaimValueTypes.String, "Google") }, "Google"));
context.Principal.AddIdentity(new ClaimsIdentity(new Claim[] { new Claim("RefreshToken", refreshToken, ClaimValueTypes.String, "Google") }, "Google"));
return Task.FromResult(0);
}
};
@ -595,7 +595,7 @@ namespace Microsoft.AspNetCore.Authentication.Google
{
OnTicketReceived = context =>
{
context.Ticket.Properties.RedirectUri = null;
context.Properties.RedirectUri = null;
return Task.FromResult(0);
}
};
@ -985,7 +985,7 @@ namespace Microsoft.AspNetCore.Authentication.Google
else if (req.Path == new PathString("/tokens"))
{
var result = await context.AuthenticateAsync(TestExtensions.CookieAuthenticationScheme);
var tokens = result.Ticket.Properties.GetTokens();
var tokens = result.Properties.GetTokens();
res.Describe(tokens);
}
else if (req.Path == new PathString("/me"))
@ -995,17 +995,17 @@ namespace Microsoft.AspNetCore.Authentication.Google
else if (req.Path == new PathString("/authenticate"))
{
var result = await context.AuthenticateAsync(TestExtensions.CookieAuthenticationScheme);
res.Describe(result.Ticket.Principal);
res.Describe(result.Principal);
}
else if (req.Path == new PathString("/authenticateGoogle"))
{
var result = await context.AuthenticateAsync("Google");
res.Describe(result?.Ticket?.Principal);
res.Describe(result?.Principal);
}
else if (req.Path == new PathString("/authenticateFacebook"))
{
var result = await context.AuthenticateAsync("Facebook");
res.Describe(result?.Ticket?.Principal);
res.Describe(result?.Principal);
}
else if (req.Path == new PathString("/unauthorized"))
{
@ -1024,15 +1024,15 @@ namespace Microsoft.AspNetCore.Authentication.Google
}
else if (req.Path == new PathString("/signIn"))
{
await Assert.ThrowsAsync<NotSupportedException>(() => context.SignInAsync("Google", new ClaimsPrincipal()));
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync("Google", new ClaimsPrincipal()));
}
else if (req.Path == new PathString("/signOut"))
{
await Assert.ThrowsAsync<NotSupportedException>(() => context.SignOutAsync("Google"));
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync("Google"));
}
else if (req.Path == new PathString("/forbid"))
{
await Assert.ThrowsAsync<NotSupportedException>(() => context.ForbidAsync("Google"));
await Assert.ThrowsAsync<InvalidOperationException>(() => context.ForbidAsync("Google"));
}
else if (testpath != null)
{
@ -1050,12 +1050,12 @@ namespace Microsoft.AspNetCore.Authentication.Google
services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = TestExtensions.CookieAuthenticationScheme;
o.DefaultSignInScheme = TestExtensions.CookieAuthenticationScheme;
o.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
});
services.AddCookieAuthentication(TestExtensions.CookieAuthenticationScheme);
services.AddGoogleAuthentication(configureOptions);
services.AddFacebookAuthentication(o =>
services.AddAuthentication()
.AddCookie(TestExtensions.CookieAuthenticationScheme)
.AddGoogle(configureOptions)
.AddFacebook(o =>
{
o.AppId = "Test AppId";
o.AppSecret = "Test AppSecrent";

Просмотреть файл

@ -127,11 +127,8 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
new Claim(ClaimsIdentity.DefaultNameClaimType, "bob")
};
context.Ticket = new AuthenticationTicket(
new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name)),
new AuthenticationProperties(), context.Scheme.Name);
context.HandleResponse();
context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
return Task.FromResult<object>(null);
}
@ -338,7 +335,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
{
// Retrieve the NameIdentifier claim from the identity
// returned by the custom security token validator.
var identity = (ClaimsIdentity)context.Ticket.Principal.Identity;
var identity = (ClaimsIdentity)context.Principal.Identity;
var identifier = identity.FindFirst(ClaimTypes.NameIdentifier);
Assert.Equal("Bob le Tout Puissant", identifier.Value);
@ -396,7 +393,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
{
OnMessageReceived = context =>
{
context.Skip();
context.NoResult();
return Task.FromResult(0);
},
OnTokenValidated = context =>
@ -420,7 +417,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
}
[Fact]
public async Task EventOnMessageReceivedHandled_NoMoreEventsExecuted()
public async Task EventOnMessageReceivedReject_NoMoreEventsExecuted()
{
var server = CreateServer(options =>
{
@ -428,7 +425,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
{
OnMessageReceived = context =>
{
context.HandleResponse();
context.Fail("Authentication was aborted from user code.");
context.Response.StatusCode = StatusCodes.Status202Accepted;
return Task.FromResult(0);
},
@ -447,9 +444,12 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
};
});
var response = await SendAsync(server, "http://example.com/checkforerrors", "Bearer Token");
Assert.Equal(HttpStatusCode.Accepted, response.Response.StatusCode);
Assert.Equal(string.Empty, response.ResponseText);
var exception = await Assert.ThrowsAsync<Exception>(delegate
{
return SendAsync(server, "http://example.com/checkforerrors", "Bearer Token");
});
Assert.Equal("Authentication was aborted from user code.", exception.InnerException.Message);
}
[Fact]
@ -461,7 +461,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
{
OnTokenValidated = context =>
{
context.Skip();
context.NoResult();
return Task.FromResult(0);
},
OnAuthenticationFailed = context =>
@ -483,7 +483,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
}
[Fact]
public async Task EventOnTokenValidatedHandled_NoMoreEventsExecuted()
public async Task EventOnTokenValidatedReject_NoMoreEventsExecuted()
{
var server = CreateServer(options =>
{
@ -491,7 +491,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
{
OnTokenValidated = context =>
{
context.HandleResponse();
context.Fail("Authentication was aborted from user code.");
context.Response.StatusCode = StatusCodes.Status202Accepted;
return Task.FromResult(0);
},
@ -508,9 +508,12 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
options.SecurityTokenValidators.Add(new BlobTokenValidator("JWT"));
});
var response = await SendAsync(server, "http://example.com/checkforerrors", "Bearer Token");
Assert.Equal(HttpStatusCode.Accepted, response.Response.StatusCode);
Assert.Equal(string.Empty, response.ResponseText);
var exception = await Assert.ThrowsAsync<Exception>(delegate
{
return SendAsync(server, "http://example.com/checkforerrors", "Bearer Token");
});
Assert.Equal("Authentication was aborted from user code.", exception.InnerException.Message);
}
[Fact]
@ -526,7 +529,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
},
OnAuthenticationFailed = context =>
{
context.Skip();
context.NoResult();
return Task.FromResult(0);
},
OnChallenge = context =>
@ -544,7 +547,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
}
[Fact]
public async Task EventOnAuthenticationFailedHandled_NoMoreEventsExecuted()
public async Task EventOnAuthenticationFailedReject_NoMoreEventsExecuted()
{
var server = CreateServer(options =>
{
@ -556,7 +559,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
},
OnAuthenticationFailed = context =>
{
context.HandleResponse();
context.Fail("Authentication was aborted from user code.");
context.Response.StatusCode = StatusCodes.Status202Accepted;
return Task.FromResult(0);
},
@ -569,9 +572,12 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
options.SecurityTokenValidators.Add(new BlobTokenValidator("JWT"));
});
var response = await SendAsync(server, "http://example.com/checkforerrors", "Bearer Token");
Assert.Equal(HttpStatusCode.Accepted, response.Response.StatusCode);
Assert.Equal(string.Empty, response.ResponseText);
var exception = await Assert.ThrowsAsync<Exception>(delegate
{
return SendAsync(server, "http://example.com/checkforerrors", "Bearer Token");
});
Assert.Equal("Authentication was aborted from user code.", exception.InnerException.Message);
}
[Fact]
@ -583,7 +589,7 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
{
OnChallenge = context =>
{
context.Skip();
context.HandleResponse();
return Task.FromResult(0);
},
};
@ -595,29 +601,6 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
Assert.Equal(string.Empty, response.ResponseText);
}
[Fact]
public async Task EventOnChallengeHandled_ResponseNotModified()
{
var server = CreateServer(o =>
{
o.Events = new JwtBearerEvents()
{
OnChallenge = context =>
{
context.HandleResponse();
context.Response.StatusCode = StatusCodes.Status202Accepted;
return Task.FromResult(0);
},
};
});
var response = await SendAsync(server, "http://example.com/unauthorized", "Bearer Token");
Assert.Equal(HttpStatusCode.Accepted, response.Response.StatusCode);
Assert.Empty(response.Response.Headers.WwwAuthenticate);
Assert.Equal(string.Empty, response.ResponseText);
}
class InvalidTokenValidator : ISecurityTokenValidator
{
public InvalidTokenValidator()
@ -752,11 +735,11 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
}
else if (context.Request.Path == new PathString("/signIn"))
{
await Assert.ThrowsAsync<NotSupportedException>(() => context.SignInAsync(JwtBearerDefaults.AuthenticationScheme, new ClaimsPrincipal()));
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(JwtBearerDefaults.AuthenticationScheme, new ClaimsPrincipal()));
}
else if (context.Request.Path == new PathString("/signOut"))
{
await Assert.ThrowsAsync<NotSupportedException>(() => context.SignOutAsync(JwtBearerDefaults.AuthenticationScheme));
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync(JwtBearerDefaults.AuthenticationScheme));
}
else
{

Просмотреть файл

@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.Authentication.Tests.MicrosoftAccount
OnCreatingTicket = context =>
{
var refreshToken = context.RefreshToken;
context.Ticket.Principal.AddIdentity(new ClaimsIdentity(new Claim[] { new Claim("RefreshToken", refreshToken, ClaimValueTypes.String, "Microsoft") }, "Microsoft"));
context.Principal.AddIdentity(new ClaimsIdentity(new Claim[] { new Claim("RefreshToken", refreshToken, ClaimValueTypes.String, "Microsoft") }, "Microsoft"));
return Task.FromResult<object>(null);
}
};
@ -205,15 +205,15 @@ namespace Microsoft.AspNetCore.Authentication.Tests.MicrosoftAccount
}
else if (req.Path == new PathString("/signIn"))
{
await Assert.ThrowsAsync<NotSupportedException>(() => context.SignInAsync("Microsoft", new ClaimsPrincipal()));
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync("Microsoft", new ClaimsPrincipal()));
}
else if (req.Path == new PathString("/signOut"))
{
await Assert.ThrowsAsync<NotSupportedException>(() => context.SignOutAsync("Microsoft"));
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync("Microsoft"));
}
else if (req.Path == new PathString("/forbid"))
{
await Assert.ThrowsAsync<NotSupportedException>(() => context.ForbidAsync("Microsoft"));
await Assert.ThrowsAsync<InvalidOperationException>(() => context.ForbidAsync("Microsoft"));
}
else
{
@ -226,10 +226,10 @@ namespace Microsoft.AspNetCore.Authentication.Tests.MicrosoftAccount
services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = TestExtensions.CookieAuthenticationScheme;
o.DefaultSignInScheme = TestExtensions.CookieAuthenticationScheme;
});
services.AddCookieAuthentication(TestExtensions.CookieAuthenticationScheme, o => { });
services.AddMicrosoftAccountAuthentication(configureOptions);
services.AddAuthentication()
.AddCookie(TestExtensions.CookieAuthenticationScheme, o => { })
.AddMicrosoftAccount(configureOptions);
});
return new TestServer(builder);
}

Просмотреть файл

@ -143,29 +143,6 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
Assert.Equal(HttpStatusCode.OK, transaction.Response.StatusCode);
}
[Fact]
public async Task ThrowsIfSignInSchemeMissing()
{
var server = CreateServer(
app => { },
services => services.AddOAuthAuthentication("weeblie", o =>
{
o.ClientId = "Whatever;";
o.ClientSecret = "Whatever;";
o.CallbackPath = "/";
o.TokenEndpoint = "/";
o.AuthorizationEndpoint = "/";
}),
context =>
{
// REVIEW: Gross.
Assert.Throws<ArgumentException>("SignInScheme", () => context.ChallengeAsync("weeblie").GetAwaiter().GetResult());
return true;
});
var transaction = await server.SendAsync("http://example.com/challenge");
Assert.Equal(HttpStatusCode.OK, transaction.Response.StatusCode);
}
[Fact]
public async Task RedirectToIdentityProvider_SetsCorrelationIdCookiePath_ToCallBackPath()
{

Просмотреть файл

@ -335,7 +335,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
// This test can be further refined. When one auth handler skips, the authentication responsibility
// will be flowed to the next one. A dummy auth handler can be added to ensure the correct logic.
[Fact]
public async Task OnRedirectToIdentityProviderEventSkipResponse()
public async Task OnRedirectToIdentityProviderEventHandleResponse()
{
var settings = new TestSettings(
opts =>
@ -346,7 +346,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
{
OnRedirectToIdentityProvider = context =>
{
context.Skip();
context.HandleResponse();
return Task.FromResult(0);
}
};

Просмотреть файл

@ -22,8 +22,9 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
var builder = new WebHostBuilder()
.ConfigureServices(services =>
{
services.AddCookieAuthentication();
services.AddOpenIdConnectAuthentication(o =>
services.AddAuthentication()
.AddCookie()
.AddOpenIdConnect(o =>
{
o.Authority = TestServerBuilder.DefaultAuthority;
o.ClientId = Guid.NewGuid().ToString();
@ -45,19 +46,6 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
Assert.Equal(HttpStatusCode.OK, transaction.Response.StatusCode);
}
[Fact]
public Task ThrowsWhenSignInSchemeIsMissing()
{
return TestConfigurationException<ArgumentException>(
o =>
{
o.ClientId = "Test Id";
o.Authority = TestServerBuilder.DefaultAuthority;
o.CallbackPath = "/";
},
ex => Assert.Equal("SignInScheme", ex.ParamName));
}
[Fact]
public Task ThrowsWhenClientIdIsMissing()
{
@ -119,8 +107,9 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
var builder = new WebHostBuilder()
.ConfigureServices(services =>
{
services.AddCookieAuthentication();
services.AddOpenIdConnectAuthentication(options);
services.AddAuthentication()
.AddCookie()
.AddOpenIdConnect(options);
})
.Configure(app => app.UseAuthentication());

Просмотреть файл

@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
private readonly Func<UserInformationReceivedContext, Task> UserNotImpl = context => { throw new NotImplementedException("User"); };
private readonly Func<AuthenticationFailedContext, Task> FailedNotImpl = context => { throw new NotImplementedException("Failed", context.Exception); };
private readonly Func<TicketReceivedContext, Task> TicketNotImpl = context => { throw new NotImplementedException("Ticket"); };
private readonly Func<FailureContext, Task> FailureNotImpl = context => { throw new NotImplementedException("Failure", context.Failure); };
private readonly Func<RemoteFailureContext, Task> FailureNotImpl = context => { throw new NotImplementedException("Failure", context.Failure); };
private readonly Func<RedirectContext, Task> RedirectNotImpl = context => { throw new NotImplementedException("Redirect"); };
private readonly Func<RemoteSignOutContext, Task> RemoteSignOutNotImpl = context => { throw new NotImplementedException("Remote"); };
private readonly RequestDelegate AppNotImpl = context => { throw new NotImplementedException("App"); };
@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnMessageReceived = context =>
{
messageReceived = true;
context.Skip();
context.SkipHandler();
return Task.FromResult(0);
},
OnTokenValidated = TokenNotImpl,
@ -75,6 +75,51 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
Assert.True(messageReceived);
}
[Fact]
public async Task OnMessageReceived_Reject_NoMoreEventsRun()
{
var messageReceived = false;
var remoteFailure = false;
var server = CreateServer(new OpenIdConnectEvents()
{
OnMessageReceived = context =>
{
messageReceived = true;
context.Fail("Authentication was aborted from user code.");
return Task.FromResult(0);
},
OnRemoteFailure = context =>
{
remoteFailure = true;
return Task.FromResult(0);
},
OnTokenValidated = TokenNotImpl,
OnAuthorizationCodeReceived = CodeNotImpl,
OnTokenResponseReceived = TokenResponseNotImpl,
OnUserInformationReceived = UserNotImpl,
OnAuthenticationFailed = FailedNotImpl,
OnTicketReceived = TicketNotImpl,
OnRedirectToIdentityProvider = RedirectNotImpl,
OnRedirectToIdentityProviderForSignOut = RedirectNotImpl,
OnRemoteSignOut = RemoteSignOutNotImpl,
},
context =>
{
return context.Response.WriteAsync(context.Request.Path);
});
var exception = await Assert.ThrowsAsync<Exception>(delegate
{
return PostAsync(server, "signin-oidc", "");
});
Assert.Equal("Authentication was aborted from user code.", exception.Message);
Assert.True(messageReceived);
Assert.True(remoteFailure);
}
[Fact]
public async Task OnMessageReceived_Handled_NoMoreEventsRun()
{
@ -124,7 +169,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnTokenValidated = context =>
{
tokenValidated = true;
context.Skip();
context.SkipHandler();
return Task.FromResult(0);
},
OnAuthorizationCodeReceived = CodeNotImpl,
@ -151,6 +196,57 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
Assert.True(tokenValidated);
}
[Fact]
public async Task OnTokenValidated_Reject_NoMoreEventsRun()
{
var messageReceived = false;
var tokenValidated = false;
var remoteFailure = false;
var server = CreateServer(new OpenIdConnectEvents()
{
OnMessageReceived = context =>
{
messageReceived = true;
return Task.FromResult(0);
},
OnTokenValidated = context =>
{
tokenValidated = true;
context.Fail("Authentication was aborted from user code.");
return Task.FromResult(0);
},
OnRemoteFailure = context =>
{
remoteFailure = true;
return Task.FromResult(0);
},
OnAuthorizationCodeReceived = CodeNotImpl,
OnTokenResponseReceived = TokenResponseNotImpl,
OnUserInformationReceived = UserNotImpl,
OnAuthenticationFailed = FailedNotImpl,
OnTicketReceived = TicketNotImpl,
OnRedirectToIdentityProvider = RedirectNotImpl,
OnRedirectToIdentityProviderForSignOut = RedirectNotImpl,
OnRemoteSignOut = RemoteSignOutNotImpl,
},
context =>
{
return context.Response.WriteAsync(context.Request.Path);
});
var exception = await Assert.ThrowsAsync<Exception>(delegate
{
return PostAsync(server, "signin-oidc", "id_token=my_id_token&state=protected_state");
});
Assert.Equal("Authentication was aborted from user code.", exception.Message);
Assert.True(messageReceived);
Assert.True(tokenValidated);
Assert.True(remoteFailure);
}
[Fact]
public async Task OnTokenValidated_HandledWithoutTicket_NoMoreEventsRun()
{
@ -167,7 +263,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
{
tokenValidated = true;
context.HandleResponse();
context.Ticket = null;
context.Principal = null;
context.Response.StatusCode = StatusCodes.Status202Accepted;
return Task.FromResult(0);
},
@ -209,8 +305,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnTokenValidated = context =>
{
tokenValidated = true;
context.HandleResponse();
// context.Ticket = null;
context.Success();
return Task.FromResult(0);
},
OnAuthorizationCodeReceived = CodeNotImpl,
@ -262,7 +357,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnAuthorizationCodeReceived = context =>
{
codeReceived = true;
context.Skip();
context.SkipHandler();
return Task.FromResult(0);
},
OnTokenResponseReceived = TokenResponseNotImpl,
@ -289,6 +384,63 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
Assert.True(codeReceived);
}
[Fact]
public async Task OnAuthorizationCodeReceived_Reject_NoMoreEventsRun()
{
var messageReceived = false;
var tokenValidated = false;
var codeReceived = false;
var remoteFailure = false;
var server = CreateServer(new OpenIdConnectEvents()
{
OnMessageReceived = context =>
{
messageReceived = true;
return Task.FromResult(0);
},
OnTokenValidated = context =>
{
tokenValidated = true;
return Task.FromResult(0);
},
OnAuthorizationCodeReceived = context =>
{
codeReceived = true;
context.Fail("Authentication was aborted from user code.");
return Task.FromResult(0);
},
OnRemoteFailure = context =>
{
remoteFailure = true;
return Task.FromResult(0);
},
OnTokenResponseReceived = TokenResponseNotImpl,
OnUserInformationReceived = UserNotImpl,
OnAuthenticationFailed = FailedNotImpl,
OnTicketReceived = TicketNotImpl,
OnRedirectToIdentityProvider = RedirectNotImpl,
OnRedirectToIdentityProviderForSignOut = RedirectNotImpl,
OnRemoteSignOut = RemoteSignOutNotImpl,
},
context =>
{
return context.Response.WriteAsync(context.Request.Path);
});
var exception = await Assert.ThrowsAsync<Exception>(delegate
{
return PostAsync(server, "signin-oidc", "id_token=my_id_token&state=protected_state&code=my_code");
});
Assert.Equal("Authentication was aborted from user code.", exception.Message);
Assert.True(messageReceived);
Assert.True(tokenValidated);
Assert.True(codeReceived);
Assert.True(remoteFailure);
}
[Fact]
public async Task OnAuthorizationCodeReceived_HandledWithoutTicket_NoMoreEventsRun()
{
@ -311,7 +463,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
{
codeReceived = true;
context.HandleResponse();
context.Ticket = null;
context.Principal = null;
context.Response.StatusCode = StatusCodes.Status202Accepted;
return Task.FromResult(0);
},
@ -358,8 +510,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnAuthorizationCodeReceived = context =>
{
codeReceived = true;
context.HandleResponse();
// context.Ticket = null;
context.Success();
return Task.FromResult(0);
},
OnTokenResponseReceived = TokenResponseNotImpl,
@ -417,7 +568,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnTokenResponseReceived = context =>
{
tokenResponseReceived = true;
context.Skip();
context.SkipHandler();
return Task.FromResult(0);
},
OnUserInformationReceived = UserNotImpl,
@ -444,6 +595,69 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
Assert.True(tokenResponseReceived);
}
[Fact]
public async Task OnTokenResponseReceived_Reject_NoMoreEventsRun()
{
var messageReceived = false;
var tokenValidated = false;
var codeReceived = false;
var tokenResponseReceived = false;
var remoteFailure = false;
var server = CreateServer(new OpenIdConnectEvents()
{
OnMessageReceived = context =>
{
messageReceived = true;
return Task.FromResult(0);
},
OnTokenValidated = context =>
{
tokenValidated = true;
return Task.FromResult(0);
},
OnAuthorizationCodeReceived = context =>
{
codeReceived = true;
return Task.FromResult(0);
},
OnTokenResponseReceived = context =>
{
tokenResponseReceived = true;
context.Fail("Authentication was aborted from user code.");
return Task.FromResult(0);
},
OnRemoteFailure = context =>
{
remoteFailure = true;
return Task.FromResult(0);
},
OnUserInformationReceived = UserNotImpl,
OnAuthenticationFailed = FailedNotImpl,
OnTicketReceived = TicketNotImpl,
OnRedirectToIdentityProvider = RedirectNotImpl,
OnRedirectToIdentityProviderForSignOut = RedirectNotImpl,
OnRemoteSignOut = RemoteSignOutNotImpl,
},
context =>
{
return context.Response.WriteAsync(context.Request.Path);
});
var exception = await Assert.ThrowsAsync<Exception>(delegate
{
return PostAsync(server, "signin-oidc", "id_token=my_id_token&state=protected_state&code=my_code");
});
Assert.Equal("Authentication was aborted from user code.", exception.Message);
Assert.True(messageReceived);
Assert.True(tokenValidated);
Assert.True(codeReceived);
Assert.True(tokenResponseReceived);
Assert.True(remoteFailure);
}
[Fact]
public async Task OnTokenResponseReceived_HandledWithoutTicket_NoMoreEventsRun()
{
@ -471,7 +685,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnTokenResponseReceived = context =>
{
tokenResponseReceived = true;
context.Ticket = null;
context.Principal = null;
context.HandleResponse();
context.Response.StatusCode = StatusCodes.Status202Accepted;
return Task.FromResult(0);
@ -525,8 +739,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnTokenResponseReceived = context =>
{
tokenResponseReceived = true;
// context.Ticket = null;
context.HandleResponse();
context.Success();
return Task.FromResult(0);
},
OnUserInformationReceived = UserNotImpl,
@ -584,7 +797,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnTokenValidated = context =>
{
tokenValidated = true;
context.Skip();
context.SkipHandler();
return Task.FromResult(0);
},
OnUserInformationReceived = UserNotImpl,
@ -611,6 +824,69 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
Assert.True(tokenValidated);
}
[Fact]
public async Task OnTokenValidatedBackchannel_Reject_NoMoreEventsRun()
{
var messageReceived = false;
var codeReceived = false;
var tokenResponseReceived = false;
var tokenValidated = false;
var remoteFailure = false;
var server = CreateServer(new OpenIdConnectEvents()
{
OnMessageReceived = context =>
{
messageReceived = true;
return Task.FromResult(0);
},
OnAuthorizationCodeReceived = context =>
{
codeReceived = true;
return Task.FromResult(0);
},
OnTokenResponseReceived = context =>
{
tokenResponseReceived = true;
return Task.FromResult(0);
},
OnTokenValidated = context =>
{
tokenValidated = true;
context.Fail("Authentication was aborted from user code.");
return Task.FromResult(0);
},
OnRemoteFailure = context =>
{
remoteFailure = true;
return Task.FromResult(0);
},
OnUserInformationReceived = UserNotImpl,
OnAuthenticationFailed = FailedNotImpl,
OnTicketReceived = TicketNotImpl,
OnRedirectToIdentityProvider = RedirectNotImpl,
OnRedirectToIdentityProviderForSignOut = RedirectNotImpl,
OnRemoteSignOut = RemoteSignOutNotImpl,
},
context =>
{
return context.Response.WriteAsync(context.Request.Path);
});
var exception = await Assert.ThrowsAsync<Exception>(delegate
{
return PostAsync(server, "signin-oidc", "state=protected_state&code=my_code");
});
Assert.Equal("Authentication was aborted from user code.", exception.Message);
Assert.True(messageReceived);
Assert.True(codeReceived);
Assert.True(tokenResponseReceived);
Assert.True(tokenValidated);
Assert.True(remoteFailure);
}
[Fact]
public async Task OnTokenValidatedBackchannel_HandledWithoutTicket_NoMoreEventsRun()
{
@ -638,7 +914,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnTokenValidated = context =>
{
tokenValidated = true;
context.Ticket = null;
context.Principal = null;
context.HandleResponse();
context.Response.StatusCode = StatusCodes.Status202Accepted;
return Task.FromResult(0);
@ -692,8 +968,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnTokenValidated = context =>
{
tokenValidated = true;
// context.Ticket = null;
context.HandleResponse();
context.Success();
return Task.FromResult(0);
},
OnUserInformationReceived = UserNotImpl,
@ -757,7 +1032,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnUserInformationReceived = context =>
{
userInfoReceived = true;
context.Skip();
context.SkipHandler();
return Task.FromResult(0);
},
OnAuthenticationFailed = FailedNotImpl,
@ -784,6 +1059,75 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
Assert.True(userInfoReceived);
}
[Fact]
public async Task OnUserInformationReceived_Reject_NoMoreEventsRun()
{
var messageReceived = false;
var tokenValidated = false;
var codeReceived = false;
var tokenResponseReceived = false;
var userInfoReceived = false;
var remoteFailure = false;
var server = CreateServer(new OpenIdConnectEvents()
{
OnMessageReceived = context =>
{
messageReceived = true;
return Task.FromResult(0);
},
OnTokenValidated = context =>
{
tokenValidated = true;
return Task.FromResult(0);
},
OnAuthorizationCodeReceived = context =>
{
codeReceived = true;
return Task.FromResult(0);
},
OnTokenResponseReceived = context =>
{
tokenResponseReceived = true;
return Task.FromResult(0);
},
OnUserInformationReceived = context =>
{
userInfoReceived = true;
context.Fail("Authentication was aborted from user code.");
return Task.FromResult(0);
},
OnRemoteFailure = context =>
{
remoteFailure = true;
return Task.FromResult(0);
},
OnAuthenticationFailed = FailedNotImpl,
OnTicketReceived = TicketNotImpl,
OnRedirectToIdentityProvider = RedirectNotImpl,
OnRedirectToIdentityProviderForSignOut = RedirectNotImpl,
OnRemoteSignOut = RemoteSignOutNotImpl,
},
context =>
{
return context.Response.WriteAsync(context.Request.Path);
});
var exception = await Assert.ThrowsAsync<Exception>(delegate
{
return PostAsync(server, "signin-oidc", "id_token=my_id_token&state=protected_state&code=my_code");
});
Assert.Equal("Authentication was aborted from user code.", exception.Message);
Assert.True(messageReceived);
Assert.True(tokenValidated);
Assert.True(codeReceived);
Assert.True(tokenResponseReceived);
Assert.True(userInfoReceived);
Assert.True(remoteFailure);
}
[Fact]
public async Task OnUserInformationReceived_HandledWithoutTicket_NoMoreEventsRun()
{
@ -817,7 +1161,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnUserInformationReceived = context =>
{
userInfoReceived = true;
context.Ticket = null;
context.Principal = null;
context.HandleResponse();
context.Response.StatusCode = StatusCodes.Status202Accepted;
return Task.FromResult(0);
@ -878,7 +1222,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
{
userInfoReceived = true;
// context.Ticket = null;
context.HandleResponse();
context.Success();
return Task.FromResult(0);
},
OnAuthenticationFailed = FailedNotImpl,
@ -949,7 +1293,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
{
authFailed = true;
Assert.Equal("TestException", context.Exception.Message);
context.Skip();
context.SkipHandler();
return Task.FromResult(0);
},
OnRemoteFailure = FailureNotImpl,
@ -976,6 +1320,82 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
Assert.True(authFailed);
}
[Fact]
public async Task OnAuthenticationFailed_Reject_NoMoreEventsRun()
{
var messageReceived = false;
var tokenValidated = false;
var codeReceived = false;
var tokenResponseReceived = false;
var userInfoReceived = false;
var authFailed = false;
var remoteFailure = false;
var server = CreateServer(new OpenIdConnectEvents()
{
OnMessageReceived = context =>
{
messageReceived = true;
return Task.FromResult(0);
},
OnTokenValidated = context =>
{
tokenValidated = true;
return Task.FromResult(0);
},
OnAuthorizationCodeReceived = context =>
{
codeReceived = true;
return Task.FromResult(0);
},
OnTokenResponseReceived = context =>
{
tokenResponseReceived = true;
return Task.FromResult(0);
},
OnUserInformationReceived = context =>
{
userInfoReceived = true;
throw new NotImplementedException("TestException");
},
OnAuthenticationFailed = context =>
{
authFailed = true;
Assert.Equal("TestException", context.Exception.Message);
context.Fail("Authentication was aborted from user code.");
return Task.FromResult(0);
},
OnRemoteFailure = context =>
{
remoteFailure = true;
return Task.FromResult(0);
},
OnTicketReceived = TicketNotImpl,
OnRedirectToIdentityProvider = RedirectNotImpl,
OnRedirectToIdentityProviderForSignOut = RedirectNotImpl,
OnRemoteSignOut = RemoteSignOutNotImpl,
},
context =>
{
return context.Response.WriteAsync(context.Request.Path);
});
var exception = await Assert.ThrowsAsync<Exception>(delegate
{
return PostAsync(server, "signin-oidc", "id_token=my_id_token&state=protected_state&code=my_code");
});
Assert.Equal("Authentication was aborted from user code.", exception.Message);
Assert.True(messageReceived);
Assert.True(tokenValidated);
Assert.True(codeReceived);
Assert.True(tokenResponseReceived);
Assert.True(userInfoReceived);
Assert.True(authFailed);
Assert.True(remoteFailure);
}
[Fact]
public async Task OnAuthenticationFailed_HandledWithoutTicket_NoMoreEventsRun()
{
@ -1016,7 +1436,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
{
authFailed = true;
Assert.Equal("TestException", context.Exception.Message);
Assert.Null(context.Ticket);
Assert.Null(context.Principal);
context.HandleResponse();
context.Response.StatusCode = StatusCodes.Status202Accepted;
return Task.FromResult(0);
@ -1083,7 +1503,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
{
authFailed = true;
Assert.Equal("TestException", context.Exception.Message);
Assert.Null(context.Ticket);
Assert.Null(context.Principal);
var claims = new[]
{
@ -1092,11 +1512,8 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
new Claim(ClaimsIdentity.DefaultNameClaimType, "bob")
};
context.Ticket = new AuthenticationTicket(
new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name)),
new AuthenticationProperties(), context.Scheme.Name);
context.HandleResponse();
context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
return Task.FromResult(0);
},
OnRemoteFailure = FailureNotImpl,
@ -1174,7 +1591,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
{
remoteFailure = true;
Assert.Equal("TestException", context.Failure.Message);
context.Skip();
context.SkipHandler();
return Task.FromResult(0);
},
OnTicketReceived = TicketNotImpl,
@ -1314,7 +1731,7 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
OnTicketReceived = context =>
{
ticektReceived = true;
context.Skip();
context.SkipHandler();
return Task.FromResult(0);
},
@ -1408,8 +1825,9 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
var builder = new WebHostBuilder()
.ConfigureServices(services =>
{
services.AddCookieAuthentication();
services.AddOpenIdConnectAuthentication(o =>
services.AddAuthentication()
.AddCookie()
.AddOpenIdConnect(o =>
{
o.Events = events;
o.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

Просмотреть файл

@ -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.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
@ -11,10 +10,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Xunit;

Просмотреть файл

@ -112,10 +112,10 @@ namespace Microsoft.AspNetCore.Authentication.Test.OpenIdConnect
services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
});
services.AddCookieAuthentication();
services.AddOpenIdConnectAuthentication(options);
services.AddAuthentication()
.AddCookie()
.AddOpenIdConnect(options);
});
return new TestServer(builder);

Просмотреть файл

@ -134,7 +134,7 @@ namespace Microsoft.AspNetCore.Authentication
// return Task.FromResult(0);
// }
// public Task ChallengeAsync(ChallengeContext context)
// public Task ChallengeAsync(AuthenticationProperties properties)
// {
// throw new NotImplementedException();
// }
@ -144,12 +144,12 @@ namespace Microsoft.AspNetCore.Authentication
// throw new NotImplementedException();
// }
// public Task SignInAsync(SignInContext context)
// public Task SignInAsync(ClaimsPrincipal principal, AuthenticationProperties properties)
// {
// throw new NotImplementedException();
// }
// public Task SignOutAsync(SignOutContext context)
// public Task SignOutAsync(AuthenticationProperties properties)
// {
// throw new NotImplementedException();
// }

Просмотреть файл

@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
@ -13,7 +12,6 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Xunit;
namespace Microsoft.AspNetCore.Authentication.Twitter
@ -177,15 +175,15 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
var res = context.Response;
if (req.Path == new PathString("/signIn"))
{
await Assert.ThrowsAsync<NotSupportedException>(() => context.SignInAsync("Twitter", new ClaimsPrincipal()));
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync("Twitter", new ClaimsPrincipal()));
}
else if (req.Path == new PathString("/signOut"))
{
await Assert.ThrowsAsync<NotSupportedException>(() => context.SignOutAsync("Twitter"));
await Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync("Twitter"));
}
else if (req.Path == new PathString("/forbid"))
{
await Assert.ThrowsAsync<NotSupportedException>(() => context.ForbidAsync("Twitter"));
await Assert.ThrowsAsync<InvalidOperationException>(() => context.ForbidAsync("Twitter"));
}
else if (handler == null || !handler(context))
{
@ -195,13 +193,14 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
})
.ConfigureServices(services =>
{
services.AddCookieAuthentication("External", _ => { });
Action<TwitterOptions> wrapOptions = o =>
{
o.SignInScheme = "External";
options(o);
};
services.AddTwitterAuthentication(wrapOptions);
services.AddAuthentication()
.AddCookie("External", _ => { })
.AddTwitter(wrapOptions);
});
return new TestServer(builder);
}

Просмотреть файл

@ -312,7 +312,7 @@ namespace Microsoft.AspNetCore.CookiePolicy.Test
var builder = new WebHostBuilder()
.ConfigureServices(services =>
{
services.AddCookieAuthentication(o =>
services.AddAuthentication().AddCookie(o =>
{
o.CookieName = "TestCookie";
o.CookieHttpOnly = false;
@ -352,7 +352,7 @@ namespace Microsoft.AspNetCore.CookiePolicy.Test
var builder = new WebHostBuilder()
.ConfigureServices(services =>
{
services.AddCookieAuthentication(o =>
services.AddAuthentication().AddCookie(o =>
{
o.CookieName = "TestCookie";
o.CookieHttpOnly = false;

Просмотреть файл

@ -68,7 +68,7 @@ namespace Microsoft.Owin.Security.Interop
await context.Response.WriteAsync(result.Ticket.Principal.Identity.Name);
});
})
.ConfigureServices(services => services.AddCookieAuthentication(o => o.DataProtectionProvider = dataProtection));
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.DataProtectionProvider = dataProtection));
var newServer = new AspNetCore.TestHost.TestServer(builder);
var request = new HttpRequestMessage(HttpMethod.Get, "http://example.com/login");
@ -123,7 +123,7 @@ namespace Microsoft.Owin.Security.Interop
await context.Response.WriteAsync(result.Ticket.Principal.Identity.Name);
});
})
.ConfigureServices(services => services.AddCookieAuthentication(o => o.DataProtectionProvider = dataProtection));
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.DataProtectionProvider = dataProtection));
var newServer = new AspNetCore.TestHost.TestServer(builder);
var request = new HttpRequestMessage(HttpMethod.Get, "http://example.com/login");
@ -155,7 +155,7 @@ namespace Microsoft.Owin.Security.Interop
app.UseAuthentication();
app.Run(context => context.SignInAsync("Cookies", user));
})
.ConfigureServices(services => services.AddCookieAuthentication(o => o.DataProtectionProvider = dataProtection));
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.DataProtectionProvider = dataProtection));
var newServer = new AspNetCore.TestHost.TestServer(builder);
var cookies = await SendAndGetCookies(newServer, "http://example.com/login");
@ -202,7 +202,7 @@ namespace Microsoft.Owin.Security.Interop
app.UseAuthentication();
app.Run(context => context.SignInAsync("Cookies", user));
})
.ConfigureServices(services => services.AddCookieAuthentication(o => o.DataProtectionProvider = dataProtection));
.ConfigureServices(services => services.AddAuthentication().AddCookie(o => o.DataProtectionProvider = dataProtection));
var newServer = new AspNetCore.TestHost.TestServer(builder);
var cookies = await SendAndGetCookies(newServer, "http://example.com/login");