Closed HaoK closed 7 years ago
I'm drafting the announcement here, when we are all happy, I'll open the real announcements issue
cc @Rick-Anderson @Tratcher @blowdart
Katana => Microsoft.Owin.
In 1.0 didn't UseIdentity() need to be before Facebook?
Your layout for the 2.0 sample needs work.
Is this what the fwlink will point to in the short term?
[Authorize] also relies on DefaultAuthenticateScheme.
Missing a new line on DefaultForbidScheme.
Doesn't DefaultSignOutScheme fall back to SignInScheme? Same for Forbid?
HttpContext.Authentication.GetAuthenticateInfoAsync(scheme)
was used to obtain Auth tokens to use with external services, like Fitbit or GitHub.
How is this accomplished in 2.0?
Example: AspNetCore - Get current access token
Also: The warning message when using HttpContext.Authentication is incorrect
Warning CS0618 'HttpContext.Authentication' is obsolete: 'This is obsolete and will be removed in a future version. The recommended alternative is to use Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions. See https://go.microsoft.com/fwlink/?linkid=845470.
The link just takes you to the aspnet core starting page, and I cannot find Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions anywhere.
@tylerd try var result = await HttpContext.GetTokenAsync(scheme, "access_token");
updated with feedback, not sure what layout issue @Tratcher feel free to fix it directly.
Added a placeholder to go over AuthZ changes as well, Authorize deserves a section even tho it hasn't changed that much.
Updated the indenting
Added a major section on Authorization/Authorize/ChallengeBehavior
It looks good, but you should maybe insist on the fact the old stack was not just obsoleted but is now completely unusable. It would be also great to mention that older middleware written for 1.0 will not work and that moving to a 2.0.0-compatible version is mandatory.
To use a more advanced scoped claims transform that uses DbContext's, they would just need to add their own IClaimsTransformation before any AddAuthentication calls.
What, did you really rename IClaimsTransformer
to IClaimsTransformation
? What was the reasoning behind this change?
@Tratcher can you write the section on host changes for HttpSys/IISIntegration in a comment and I'll merge it?
@PinpointTownes they don't look the same for one, and I prefer the new name, https://github.com/aspnet/Security/blob/rel/1.1.2/src/Microsoft.AspNetCore.Authentication/IClaimsTransformer.cs vs https://github.com/aspnet/HttpAbstractions/blob/dev/src/Microsoft.AspNetCore.Authentication.Abstractions/IClaimsTransformation.cs
Buh, the new name is ugly :trollface:
Note that getting rid of ClaimsTransformationContext
will prevent one from accessing the HTTP context... at least, without having to use IHttpContextAccessor
. Maybe you could add a short line mentioned that as a workaround?
Other things you should treat:
AuthenticationProperties
and its friends have moved to a different namespace. This change will affect folks who use it in their controllers and don't necessarily use the extensions.
Authentication middleware selection via branching is no longer possible (because there's now only one middleware). You should maybe suggest a workaround.
@PinpointTownes well, its just a normal service now which can consume whatever it wants from DI, unlike before, but sure I'll call that out in the claims xform section.
Added some text about mixing 1.0 and 2.0 together in the initial section, but this probably needs a longer dedicated section in the known breaking changes when I get to it.
re Properties and things moving around, that will go into this placeholder section: Overview of Auth core/scheme provider/request handler section.
This announcment is probably going to be really really long (too long I think). Hopefully @Rick-Anderson will turn this into real docs :)
ChallengeBehavior.Automatic description is backwards, it forbids if you already have a ticket.
Not much to say for the hosts. The biggest visible differences are that they were each consolidated to a single "Windows" scheme, and that IISIntegration now conditionally registers the handler only if windows auth is enabled in IIS (if you have the latest version of ANCM, otherwise it's always registered as before).
Cool thanks, added the host section
Added "New Microsoft.AspNet.Authentication.Core/Abstractions" section
Needs a sample showing this common scenario:
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
@danroth27 didn't you say that you were able to just always challenge cookie? Or is your scenario different?
Its also there in the example already: AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
but I'll call more attention to this in the section I'm writing now which will go over the AuthenticationMiddleware in more detail
Dan's scenario is different, he has a login page. For OAuth/OIDC apps without a login page then you need to specify the default challenge too.
Updated doc with Security/Authenticationhandler overviews along with a short overview of the context/events methods.
Bah github fail, lost the update, was in preview, and commenting nukes the edits :(
Ok updated again, fun fact: so turns out you can recover form posts that were lost after a submit by taking a process dump of a chrome tab... good trick if you ever lose a HUGE post :)
Removed dedicated cookie interop section, since the initial paragraph covered it.
Looks good to convert to announcments @Tratcher?
@danroth27 this look reasonable to you for the announcement?
:shipit:
@HaoK @Tratcher I'll need a couple edits to this issue to help me finish the migration doc:
Sir, what happened to this peace of code?
services.Configure<IdentityOptions>(option => { config.Cookies... }
You need to configure the cookies by their name instead, you can use https://github.com/aspnet/Identity/blob/dev/src/Microsoft.AspNetCore.Identity/IdentityServiceCollectionExtensions.cs#L39
services.ConfigureApplicationCookie()
@HaoK , @Tratcher:
After successful done a AzureAdAuthentication. I want query more Office 365 API with id_token and want to get more access tokens via and query SharePoint Online:
What I this best way to make this querys and how I can ID_Token:
This return NULL and the old way not work anymore with 2.0 var identityToken = await HttpContext.GetTokenAsync("id_token");
OLD Query for idToken get the saved identity token var identityToken = await HttpContext.Authentication .GetTokenAsync(OpenIdConnectParameterNames.IdToken);
Authentication Options with id_token public void PostConfigure(string name, OpenIdConnectOptions options) { options.ClientId = _azureOptions.ClientId; options.ClientSecret = _azureOptions.ClientSecret; options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}"; options.UseTokenLifetime = true; options.CallbackPath = _azureOptions.CallbackPath; options.RequireHttpsMetadata = false; options.GetClaimsFromUserInfoEndpoint = true; options.ResponseType = "code id_token"; }
Is there any examples where you don't use cookies within the AddAuthentication method? I was hoping to convert this to the new services.AddAuthentication(...)
method:
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
Audience = "an.app-url.com",
Authority = "identity.example.com",
AutomaticAuthenticate = true
});
@chris31389 something like that?
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Authority = "http://localhost:30940/";
options.Audience = "resource-server";
options.RequireHttpsMetadata = false;
});
}
public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
// ...
}
}
@PinpointTownes Awesome, thank you 🏆
Please help using AspnetCore 2.0 ( released today ) VS2017 15.3 in ConfigureServices I have:
services.AddAuthentication(o => {
o.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = new PathString("/Account/Login");
options.LogoutPath = new PathString("/Account/Logout");
});
In Configure I have app.UseAuthentication();
I have a seperate project which produces a result with the claims principal filled with claims like :
var claims = new List<Claim>
{
new Claim(ClaimType.UserId.ToString(), user.UserId.ToString(), ClaimValueTypes.Integer),
new Claim(ClaimType.OrganisationId.ToString(), user.OrganisationId.ToString(), ClaimValueTypes.Integer),
new Claim(ClaimType.CultureInfoSetting.ToString(), user.CultureCode, ClaimValueTypes.String),
new Claim(ClaimType.SysRoleLevel.ToString(), user.SysRoleLevel.ToString(), ClaimValueTypes.Integer),
new Claim(ClaimType.Theme.ToString(), user.Theme, ClaimValueTypes.String)
};
var identity = new ClaimsIdentity(claims, "Cookies");
var p = new ClaimsPrincipal(identity);
result.ClaimsPrincipal = p;
And in my AccountController LogIn action to SignIn : await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, signin.ClaimsPrincipal, new AuthenticationProperties { IsPersistent = true });
However the HttpContext.User is not set, is not authenticated and my code bounces me back to the Login page as i have the Authorize attribute in Home/Index .
What am I doing wrong ???
Double check that your sign in call is getting hit in the debugger, if so, make sure you see the cookie being sent (via F12 in your brower), if all of that looks fine, look at your logs and see if you see any Cookie Authentication errors that talk about failed to decrypt cookie or the like. Make sure your UseAuthentication is before UseMvc
Thanks HaoK, but the problem seems to be the following ( cause when I removed it, now authentication works )
In ConfigureServices I had localisation =>
services.Configure
In Configure =>
var locOptions = app.ApplicationServices.GetService<IOptions
And in my AccountController after the Signin prior to the redirect to Home/Index => Response.Cookies.Append( CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(result.CultureCode, result.CultureCode)), new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) } ); When I remove this, authentication works..
I'd just use F12 to look at the delta in what cookies its sending with/without that change, that should give you a hint with whats going on
In the Claims Transformation sample, there is the comment:
// Can consume services from DI as needed, including scoped DbContexts
Is it really safe to use a scoped service in a singleton service?
In my opinon, we have to use a ServiceProvider (for example http://morgwai.pl/articles/aspdi.html)
Is it really safe to use a scoped service in a singleton service?
No, this actually throws by default in 2.0.
Works almost nicely.
But when i try to chagange login path like this:
services
.AddAuthentication(o =>
{
o.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(o =>
{
o.LoginPath = "/login";
o.LogoutPath = "/logout";
});
and in Configure method i use
app.UseAuthentication();
it will still redirect me to /account/login
What am i doing wrong?
This can be simplified to:
services
.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(o =>
{
o.LoginPath = "/login";
o.LogoutPath = "/logout";
});
It should also work. Not sure why it's not using the specified options. What other code do you have in the application
my bad.
It seems that problem was that i was using Castle.Windsor.MsDependencyInjection. Not sure why though...
Something people have been confused about is actually using custom cookie based auth. This helped me: https://stackoverflow.com/questions/43961571/asp-net-core-2-0-preview-1-how-to-set-up-cookie-authentication-with-custom-logi
Hi, My cookie authentication without identity works on the dev server but not debugging against localhost in Chrome. I see the cookie getting created but keep getting re-directed back to the login page. Code below, did I miss something?
A walk through in core 2 would be a great help - https://docs.microsoft.com/en-us/aspnet/core/security/authentication/cookie?tabs=aspnetcore1x - could do with a troubleshooting example.
Thanks.
ConfigureServices
// Set up cookie based authorisation
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = new PathString("/Account/Login/");
options.LogoutPath = new PathString("/Account/Logoff/");
options.AccessDeniedPath = new PathString("/Account/AccessDenied/");
});
// Add framework services.
services.AddMvc();
Configure
app.UseAuthentication();
AccountController
[HttpGet]
public async Task<IActionResult> Login(string returnUrl = null)
{
// Clear the existing external cookie to ensure a clean login process
//await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
ViewData["ReturnUrl"] = returnUrl;
return View();
}
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel loginViewModel, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
// https://andrewlock.net/introduction-to-authentication-with-asp-net-core/
// https://code.msdn.microsoft.com/ASPNET-Core-MVC-Authenticat-39b4b103
// https://stackoverflow.com/questions/20254796/why-is-my-claimsidentity-isauthenticated-always-false-for-web-api-authorize-fil/30430228#30430228
// https://msdn.microsoft.com/en-us/library/system.security.claims.authenticationtypes(v=vs.110).aspx
// https://docs.microsoft.com/en-us/aspnet/core/security/authorization/claims
var claimsIdentity = new ClaimsIdentity(null, CookieAuthenticationDefaults.AuthenticationScheme);
ClaimsPrincipal principal = new ClaimsPrincipal(claimsIdentity);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
var isAuthenticated = principal.Identity.IsAuthenticated;
//return LocalRedirect(returnUrl);
if (returnUrl != null)
{
return Redirect(returnUrl);
}
else
{
return Redirect("~/Administrator/Menu");
}
}
return View();
}
Hi, I'm trying to adapt a custom implementation of Identity framework from pre .NET Core where have our own user manager, role manager and sign in manager. We do this because we have our own internal account store, and use SAML authentication. I need to redirect the user to our SAML authentication service. I have the following in my ConfigureServices() prior to AddMvc:
services.AddIdentity<ApplicationUser, TNCRole<IdentityRole>>()
.AddUserManager<ApplicationUserManager>()
.AddRoleManager<ApplicationRoleManager>()
.AddSignInManager<ApplicationSignInManager>();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.Name = IdentityConfig.CookieName;
options.Cookie.Domain = cookieDomain;
options.ExpireTimeSpan = TimeSpan.FromMinutes(sessionDurationMinutes);
options.SlidingExpiration = true;
options.Events = new CookieAuthenticationEvents()
{
OnValidatePrincipal = context =>
{
SecurityStampValidator.ValidatePrincipalAsync(context);
return Task.FromResult(0);
},
// This is needed because the LoginPath option only supports relative URL's.
OnRedirectToLogin = ctx =>
{
ctx.RedirectUri = _signInRedirectUri;
ctx.Response.Redirect(ctx.RedirectUri);
return Task.CompletedTask;
}
};
});
With all this in place, the redirect to the external authentication service never happens. Instead it tries to redirect to ~/Account/Login. If I take out the first statement (services.AddIdentity), the redirect to our SAML service happens properly, but then I'm not registering our custom user manager, role manager and sign in manager. Can you please help me understand what I need to do to wire this up properly?
I'm trying to convert my old authentication to .NET 2.0. I had the following code:
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
IncludeErrorDetails = true,
Authority = "https://securetoken.google.com/xxxxx",
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "https://securetoken.google.com/xxxxxx",
ValidateAudience = true,
ValidAudience = "xxxx",
ValidateLifetime = true,
},
});
My new code is the following:
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationServices();
services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(DatabaseContext.ConnectionString));
services.AddCors();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.IncludeErrorDetails = true;
options.Authority = "https://securetoken.google.com/project-id";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "https://securetoken.google.com/project-id",
ValidateAudience = true,
ValidAudience = "project-id",
ValidateLifetime = true,
};
});
services.AddMvc().AddJsonOptions(options => { options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); });
services.AddAuthorization(options =>
{
options.AddPolicy(Policies.CorporativeKeysManager, policy => policy.RequireRole(Roles.CorporativeKeysManager));
options.AddPolicy(Policies.CorporativeNewsManager, policy => policy.RequireRole(Roles.CorporativeNewsManager));
options.AddPolicy(Policies.CorporativeAdmin, policy => policy.RequireRole(Roles.CorporativeNewsManager, Roles.CorporativeKeysManager));
});
services.AddEntityFrameworkSqlServer();
services.AddIdentity<ApplicationUser, IdentityRole>(config => { config.User.RequireUniqueEmail = true; config.Password.RequireNonAlphanumeric = false; })
.AddEntityFrameworkStores<DatabaseContext>()
.AddDefaultTokenProviders();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(c => c.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
app.UseStaticFiles();
}
But in 2.0 I'm getting a 404 response. If I remove the [Authorize]
attribute from my endpoint, it works. My output window shows this:
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:62423/api/users/info
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: (null).
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Identity.Application was challenged.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action SORTE.API.ContentManager.Controllers.UsersController.Info (SORTE.API.ContentManager) in 24.0837ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 35.2446ms 302
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:62423/Account/Login?ReturnUrl=%2Fapi%2Fusers%2Finfo
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 5.8149ms 404
From the log errors, it seems that it's trying to redirect me to /Account/Login
, but I don't have such endpoint, my project is Web API.
Am I missing some configuration?
Note: this issue is closed, you should use https://github.com/aspnet/Security/issues/1338
Summary:
The old 1.0 Authentication stack no longer will work, and is obsolete in 2.0. All authentication related functionality must be migrated to the 2.0 stack, any interop between old and new must be side by side apps, as opposed to mixing 1.0 auth code with 2.0 auth code in the same app. Cookie authentication will interop, so 1.0 Cookies and 2.0 Cookies will be valid in both apps if configured properly. The main motivation was to move to a more flexible service based
IAuthenticationService
and away from the old middleware/IAuthenticationManager
design that came over from Microsoft.Owin.IAuthenticationManager
(akahttpContext.Authentication
) is now obsoleteThis was the main entry point into the old auth system. This has now been replaced with a new set of
HttpContext
extensions that live in theMicrosoft.AspNetCore.Authentication
namespace and remain very similar:Configure():
UseXyzAuthentication
has been replaced by ConfigureService(): AddXyz()In Auth 1.0, every auth scheme had its own middleware, and startup looked something like this:
In Auth 2.0, there is now only a single Authentication middleware, and each authentication scheme is registered during
ConfigureServices
, andUseIdentity()
is no longer required (since it was just calling UseCookie 4 times underneath the covers)New
Microsoft.AspNetCore.Authentication.Core/Abstractions
All of the old Authentication namespaces in HttpAbstractions have been deprecated. The new Auth 2.0 stack lives in two new packages inside the HttpAbstractions repo:
Microsoft.AspNetCore.Authentication.Core/Abstractions
.Brief overview:
IAuthenticationService
: used by theHttpContext
extension methods to expose the 5 main operationsAuthenticate/Challenge/Forbid/SignIn/SignOut
IAuthenticationHandler
: Defines the required operations for all handlers: Authenticate/Challenge/ForbidIAuthenticationSignIn/OutHandler
: Implemented to add the SignIn/SignOut methods respectivelyIAuthenticationRequestHandler
: Implemented by handlers that need to participate in request handler, i.e. remote authentication schemes like OAuth/OIDC that need to process 3rd party auth responses.AuthenticationScheme
: represents a logical named authentication scheme to target for any givenIAuthenticationService
method, it binds the scheme name (and optional display name) to anIAuthenticationHandler
which implements the scheme specific logic.IAuthenticationSchemeProvider
: responsible for managing which schemes are supported, and what the defaults are for each operation (the default implementation just reads from theAuthenticationOptions
)IAuthenticationHandlerProvider
: responsible for returning the correct handler instance for a given scheme and request.IAuthenticationFeature
: used to capture the original request path/pathbase so redirects can be computed property after anapp.Map()
Types that are mostly unchanged, just with new homes:
AuthenticationProperties
: metadata for authentication operations.AuthenticationTicket
: used to store a claims principal (user) + authentication propertiesAuthenticateResult
: return value forAuthenticateAsync
, contains either a ticket, or a failureSecurity repo:
Microsoft.AspNetCore.Authentication
/ AuthenticationHandler changesAll of the core abstractions and services for authentication live in HttpAbstracions, but there's an additional layer of base classes/functionality targeted towards implementation of AuthenticationHandlers. This is also where the AuthenticationMiddleware lives. The handlers themselves for the various implementations aren't drastically different, but there were a fair amount of changes
Microsoft.AspNetCore.Authentication
Overview:
AuthenticationMiddleware
:UseAuthentication()
adds this middleware which does two things. By default It will automatically Authenticate usingAuthenticationOptions.DefaultAuthenticateScheme
to sethttpContext.User
if specified. It also will giveIAuthenticationRequestHandler's
a chance to handle the request.AuthenticationSchemeOptions
: Base class for options used with theAuthenticationHandler
base class, it defines two common properties in Events and ClaimsIssuer, as well as a virtualValidate()
method that will be called on every request by the handler.AuthenticationHandler<TOptions>
: Abstract base class for handlers who must implementHandleAuthenticateAsync
. The rest ofIAuthenticationHandler
is implemented with some reasonable defaults, Challenge(401)/Forbid(403), and logic to handle per request initialization usingIOptionsMonitor<TOptions>.Get(authenticationScheme.Name)
to resolve the handler's options.RemoteAuthenticationHandler<TOptions>
: Adds the abstractHandleRemoteAuthenticateAsync
and implementsHandleAuthenticateAsync
to call this method. This is meant to be used for 3rd party authentication, i.e. OAuth/OIDC. It adds an additional constraint to TOptions that requires them to beRemoteAuthenticationOptions
which adds a bunch of settings like CallbackPath, CorrelationCookie, Backchannel which are needed to talk to a remote authentication provider.AuthenticationBuilder
: is a new class which is used to group all of the AddXyz() authentication methods. This is returned byservices.AddAuthentication()
and is where specific authentication methods are expected to add themselves as extension methods, i.e. AddCookie(), AddGoogle(), AddFacebook().Event changes overview
At a high level, there 3 main kinds of events:
BaseContext
events which are the simplest and just expose properties with no real control flow.ResultContext
events which revolve around producingAuthenticateResult
s which expose:Success()
: used to indicate that authentication was successful and to use the Principal/Properties in the event to construct the result.NoResult()
: used to indicate no authentication result is to be returned.Fail()
: used to return a failure.HandleRequestContext
events are used in the IAuthenticationRequestHandler/HandleRemoteAuthenticate methods and adds two more methods:HandleResponse()
: used to indicate that the response was generated and the AuthenticationMiddleware should not invoke the rest of the middlewares in the pipeline after it.SkipHandler()
used to indicate that this handler is done with the request, but subsequent handlers will be called, as well as any other middleware in the pipeline if none of those handlers handle the request.AutomaticAuthentication/Challenge
have been replaced byDefault[Authenticate/Challenge]Scheme
AutomaticAuthentication/Challenge
were intended to only be set on one authentication scheme, but there was no good way to enforce this in 1.0. These have been removed as flags on the individual AuthenticationOptions, and have been moved into the base AuthenticationOptions which can be configured in the call toAddAuthentication(authenticationOptions => authenticationOptions.DefaultScheme = "Cookies")
.There are now overloads that use the default schemes for each method in
IAuthenticationService
DefaultScheme
: if specified, all the other defaults will fallback to this valueDefaultAuthenticateScheme
: if specified,AuthenticateAsync()
will use this scheme, and also theAuthenticationMiddleware
added byUseAuthentication()
will use this scheme to setcontext.User
automatically. (Corresponds to AutomaticAuthentication)DefaultChallengeScheme
if specified,ChallengeAsync()
will use this scheme,[Authorize]
with policies that don't specify schemes will also use thisDefaultSignInScheme
is used bySignInAsync()
and also by all of the remote auth schemes like Google/Facebook/OIDC/OAuth, typically this would be set to a cookie.DefaultSignOutScheme
is used bySignOutAsync()
falls back toDefaultSignInScheme
DefaultForbidScheme
is used byForbidAsync()
, falls back toDefaultChallengeScheme
"Windows" Authentication(HttpSys/IISIntegration)
The host behavior hasn't changed too much, but now they each register a single "Windows" authentication scheme. Also IISIntegration now conditionally registers the handler only if windows auth is enabled in IIS (if you have the latest version of ANCM, otherwise it's always registered as before).
Authorization changes
IAuthorizationService.AuthorizeAsync
now returnsAuthorizationResult
instead of boolIn order to enable scenarios around authorization failures,
IAuthorizationService
now returns a result object which allows access to the reasons whyAuthorizeAsync
failed (eithercontext.Fail()
, or a list of failed requirements)Removal of
ChallengeBehavior
=> newPolicyEvaluator
In Auth 1.0, there was a
ChallengeBehavior
enum that was used to specify either Automatic/Unauthorized/Forbid behaviors to signal to the auth middleware what behavior the caller wanted. Automatic was the default and would go down the Forbid(403) code path if the middleware already had an authentication ticket, otherwise would result in Unauthorized(401).In Auth 2.0, this behavior has been moved into a new Authorization.Policy package, which introduces the
IPolicyEvaluator
which uses bothIAuthenticationService
(when requested via policy.AuthenticationSchemes), andIAuthorizationService
to decide whether to return a tri statePolicyAuthorizationResult
(Succeeded/Challenged/Forbidden).Overview of
[Authorize]
The
[Authorize]
attribute hasn't changed much, but the there were some implementation details that have changed significantly in MVC'sAuthorizeFilter
, and here's an overview of how things work: AuthorizeFilter source[Authorize]
attributes on the controller/method/globally.IPolicyEvaluator.AuthenticateAsync(policy, httpContext)
is called, by default, if the has specified anypolicy.AuthenticationSchemes
,AuthenticateAsync
will be called on each scheme, and each resultingClaimsPrincipal
will be merged together into a single ClaimsPrincipal set on context.User. If no schemes were specified, the evaluator will attempt to use context.User if it contains an authenticated user. This is usually the normal code path, asDefaultScheme/DefaultAuthenticateScheme
will be set to the main application cookie, and theAuthenticationMiddleware
will have already set context.User using this scheme'sAuthenticateAsync()
Authenticate logicAllowAnoynmous
was specified, authorization is skipped, and the filter logic short circuits and is done.IPolicyEvaluator.AuthenticateAsync(policy, authenticationResult, httpContext)
is called with the result from step 2. This just basically turns into a call toIAuthorizationService.AuthorizeAsync
, and the result is used to determine the appropriateChallenge/ForbidResult
if needed.Claims Transformation
Simpler, new
IClaimsTransformation
service with a single method:Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
We call this on any successful
AuthenticateAsync
call.Known issues/breaking changes: