& Access Control – Working with Software Development Teams (ISVs and in-house) – .NET Foundation Advisory Board – .NET Technical Steering Group Member • Creator and Maintainer of IdentityServer OSS Project – Certified OpenID Connect & OAuth 2.0 Implementation for ASP.NET – https://identityserver.io [email protected] http://leastprivilege.com https://speakerdeck.com/leastprivilege
HTTP runtime • MVC is Microsoft's primary application framework – combines web UI & API Console Application .NET (Core) ASP.NET Core Middleware Middleware User Agent MVC DI
based on ClaimsPrincipal – no more custom IPrincipal • Security related services available from DI container – authentication • cookies, external authentication, token-based authentication – authorization – data protection – CORS – encoding – anti-forgery • Middleware for security-related request processing
and authentication handlers in DI – middleware invokes handlers for request related processing – handlers can be also invoked manually • Handlers implement specific authentication methods – Cookies for browser based authentication – Google, Facebook, and other social authentication – OpenId Connect for external authentication – JSON web token (JWT) for token-based authentication
either using a named scheme, or default var claims = new Claim[] { new Claim("sub", "37734"), new Claim("name", "Brock Allen") }; var ci = new ClaimsIdentity(claims, "password", "name", "role"); var cp = new ClaimsPrincipal(ci); await HttpContext.SignInAsync(cp);
claims – register an instance of IClaimsTransformation in DI – gets called from the handler's AuthenticateAsync method public class ClaimsTransformer : IClaimsTransformation { public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal) { return await CreateApplicationPrincipalAsync(principal); } } services.AddTransient<IClaimsTransformation, ClaimsTransformer>();
middleware checks DefaultAuthenticate scheme Default authenticate handler calls AuthenticateAsync Cookie found? Populate HttpContext.User Request arrives at Controller [Authorize] ? Execute action method Get current user or call handler based on specified scheme AuthZ filter calls Challenge and redirects to LoginPath Is user authenticated? Account controller authenticates user and redirects back Is user authorized? AuthZ filter calls Forbid and redirects to AccessDeniedPath yes no yes no no yes no yes
a good idea?? For giggles: "https://www.google.com/#q=<machineKey filetype:config" <system.web> <!– copied from http://machinekeys.ru seemed legit --> <machineKey decryptionKey="656E7...617365206865726547A5" validationKey="07C1493415E4405F08...6EF8B1F" /> </system.web>
other secrets – IDataProtectionProvider in DI • Uses a key container file – stored outside of application directory* – uses a key ring with automatic rotation – keys should be protected • Needs to be synchronized between nodes in a farm * https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/default-settings
login – Control URL user returns to and state with AuthenticationProperties – MVC ChallengeResult works with action result architecture var props = new AuthenticationProperties { RedirectUri = "/Home/Secure" }; await HttpContext.ChallengeAsync("Google", props); // or if using MVC: return Challenge("Google", props);
performs local account registration logic – AuthenticateAsync triggers cookie middleware – Create local account or load existing account – Use primary cookie middleware to log user in (and remove temp cookie) var tempUser = (await HttpContext.AuthenticateAsync("Temp")).Principal; var userIdClaim = tempUser.FindFirst(ClaimTypes.NameIdentifier); var provider = userIdClaim.Issuer; var userId = userIdClaim.Value; // create local account if new, or load existing local account var user = new ClaimsPrincipal(...); await HttpContext.SignInAsync(user); await HttpContext.SignOutAsync("Temp");
Web App Web API Web API Web API OpenID Connect OAuth 2.0 OAuth 2.0 OAuth 2.0 OAuth 2.0 OAuth 2.0 OAuth 2.0 Security Token Service OpenID Connect OpenID Connect