Slide 1

Slide 1 text

.NET Core, ASP.NET Core & MVC Security Overview Dominick Baier [email protected] http://leastprivilege.com @leastprivilege

Slide 2

Slide 2 text

2 @leastprivilege Me • Independent Consultant – Specializing in Identity & Access Control – Working with Software Development Teams (ISVs and in-house) • 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 slides: https://speakerdeck.com/leastprivilege

Slide 3

Slide 3 text

3 @leastprivilege The new .NET

Slide 4

Slide 4 text

4 @leastprivilege

Slide 5

Slide 5 text

5 @leastprivilege Platform specific Implementation where needed AES.Create() OpenSSL Windows CNG Apple Crypto .NET API Surface Platform Abstraction Layer

Slide 6

Slide 6 text

Modern Application Architecture Browser Native App Server App/Thing Web App Service Service Service

Slide 7

Slide 7 text

7 @leastprivilege Initial Design public interface IIdentity { bool IsAuthenticated { get; } string AuthenticationType { get; } string Name { get; } } public interface IPrincipal { IIdentity Identity { get; } bool IsInRole(string roleName); }

Slide 8

Slide 8 text

8 @leastprivilege Dealing with identity (old school) Plumbing code / Infrastructure / Runtime Application logic Thread.CurrentPrincipal set get TLS Application

Slide 9

Slide 9 text

9 @leastprivilege Updates to Identity over Time 2002 .NET 1.0 ASP.NET 1.0 2006 .NET 3.0 WCF (#fail) 2009 WIF 2012 .NET 4.5 2013 Katana 2.0 2014 Katana 3.0 2016 .NET Core ASP.NET Core Claims + Security Token Support = External Authentication

Slide 10

Slide 10 text

10 @leastprivilege ASP.NET Core Architecture • ASP.NET Core is the 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

Slide 11

Slide 11 text

11 @leastprivilege Security Architecture in ASP.NET Core • Everything is based on ClaimsPrincipal – no more custom IPrincipal • Authentication is implemented as middleware – cookies – external authentication • Other security related services – CORS, logging, encoding, anti-forgery • New data protection API • New authorization API

Slide 12

Slide 12 text

12 @leastprivilege Authentication in ASP.NET Core • Various middleware provide authentication features – Cookies for browser based authentication – Google, Facebook, and other social authentication – OpenId Connect for external authentication – JSON web token (JWT) for token-based authentication

Slide 13

Slide 13 text

13 @leastprivilege AuthenticationManager • Central API for coordinating authentication middleware – availabe via HttpContext public abstract class AuthenticationManager { public abstract IEnumerable GetAuthenticationSchemes(); public virtual Task SignInAsync(string authenticationScheme, ClaimsPrincipal principal); public virtual Task SignOutAsync(string authenticationScheme); public virtual Task AuthenticateAsync(string authenticationScheme); public virtual Task ChallengeAsync(string authenticationScheme); public virtual Task ForbidAsync(); // ... }

Slide 14

Slide 14 text

14 @leastprivilege Cookie Authentication Middleware • Forms / Session authentication replacement public void Configure(IApplicationBuilder app) { app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationScheme = "Cookies", AutomaticAuthenticate = true, AutomaticChallenge = true, LoginPath = new PathString("/Account/Login"), AccessDeniedPath = new PathString("/Account/AccessDenied") }); }

Slide 15

Slide 15 text

15 @leastprivilege Cookies: Logging in • SignInAsync issues cookie – Authentication scheme parameter indicates which middleware var claims = new Claim[] { new Claim("sub", "37734"), new Claim("name", "Dominick Baier") }; var ci = new ClaimsIdentity(claims, "password"); var cp = new ClaimsPrincipal(ci); await HttpContext.Authentication.SignInAsync("Cookies", cp);

Slide 16

Slide 16 text

16 @leastprivilege Cookies: Logging out • SignOutAsync removes cookie – Authentication scheme parameter indicates which middleware await HttpContext.Authentication.SignOutAsync("Cookies");

Slide 17

Slide 17 text

17 @leastprivilege Data Protection • Who thought this would be a good idea?? For giggles: "https://www.google.com/#q=

Slide 18

Slide 18 text

18 @leastprivilege Key Container Locations • On Azure Web Apps (no encryption) – %HOME%\ASP.NET\DataProtection-Keys • If user profile is loaded (encrypted) – %LOCALAPPDATA%\ASP.NET\DataProtection-Keys • IIS / no profile (encrypted) – Registry HKLM • In-Memory • Manual configuration 2015-05-02T08:20:38.6577127Z 2015-05-02T08:20:38.6424674Z 2015-07-31T08:20:38.6424674Z AQ...g==

Slide 19

Slide 19 text

19 @leastprivilege Claims Transformation • Per-request manipulation of principal & claims app.UseClaimsTransformation(context => { if (context.Principal.Identity.IsAuthenticated) { CreateApplicationPrincipal(context); } return Task.FromResult(context.Principal); });

Slide 20

Slide 20 text

20 @leastprivilege External Authentication • In the box – Google, Twitter, Facebook, Microsoft Account – OpenID Connect & JSON Web Tokens • New generic OAuth 2.0 middleware makes on-boarding other proprietary providers easier – LinkedIn, Slack, Spotify, WordPress, Yahoo, Github, Instragram, BattleNet, Dropbox, Paypal, Vimeo… https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers

Slide 21

Slide 21 text

21 @leastprivilege Social Identity Providers • Enabled with UseGoogleAuthentication, et al. – Rely upon cookie authentication middleware app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationScheme = "Cookies", AutomaticAuthenticate = true, }); app.UseGoogleAuthentication(new GoogleOptions { AuthenticationScheme = "Google", SignInScheme = "Cookies", ClientId = "998042782978...", ClientSecret = "HsnwJri_53zn7..." });

Slide 22

Slide 22 text

22 @leastprivilege Social Identity Providers • ChallengeAsync triggers redirect for login – Control URL user returns to with AuthenticationProperties – MVC ChallengeResult works with action result architecture var props = new AuthenticationProperties { RedirectUri = "/Home/Secure" }; await HttpContext.Authentication.ChallengeAsync("Google", props); // or if using MVC: return new ChallengeResult("Google", props);

Slide 23

Slide 23 text

23 @leastprivilege Mixing local and external Authentication • Typically need registration logic for users from social providers – Use additional cookie middleware for processing registration app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationScheme = "Temp", AutomaticAuthenticate = false, AutomaticChallenge = false }); app.UseGoogleAuthentication(new GoogleOptions { AuthenticationScheme = "Google", SignInScheme = "Temp", ClientId = "998042782978...", ClientSecret = "HsnwJri_53zn7..." });

Slide 24

Slide 24 text

24 @leastprivilege Mixing local and external Authentication • Redirect page 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.Authentication.AuthenticateAsync("Temp"); 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.Authentication.SignInAsync("Cookies", user); await HttpContext.Authentication.SignOutAsync("Temp");

Slide 25

Slide 25 text

25 @leastprivilege The way forward… Browser Native App Server App "Thing" Web App Web API Web API Web API Security Token Service Authentication, SSO, account linking, federation, social logins…

Slide 26

Slide 26 text

26 @leastprivilege Security Protocols Browser Native App Server App "Thing" 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

Slide 27

Slide 27 text

27 @leastprivilege http://openid.net/connect/

Slide 28

Slide 28 text

28 @leastprivilege Libraries & Implementations

Slide 29

Slide 29 text

29 @leastprivilege OpenID Connect Certification

Slide 30

Slide 30 text

30 @leastprivilege

Slide 31

Slide 31 text

31 @leastprivilege Authentication for Web Applications GET /authorize ?client_id=app1 &redirect_uri=https://app.com/cb &response_type=id_token &response_mode=form_post &nonce=j1y…a23 &scope=openid profile email

Slide 32

Slide 32 text

32 @leastprivilege Authentication

Slide 33

Slide 33 text

33 @leastprivilege Consent

Slide 34

Slide 34 text

34 @leastprivilege Response POST /callback set cookie

Slide 35

Slide 35 text

35 @leastprivilege Identity Token { "typ": "JWT", "alg": "RS256", "kid": "mj399j…" } { "iss": "https://idsrv3", "exp": 1340819380, "aud": "app1", "nonce": "j1y…a23", "sub": "182jmm199", "email": "[email protected]", "name": "Alice", "amr": [ "password" ], "auth_time": 12340819300 } Header Payload eyJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMD.4MTkzODAsDQogImh0dHA6Ly9leGFt Header Payload Signature

Slide 36

Slide 36 text

36 @leastprivilege OpenID Connect Middleware • Much improved – support for implicit, code and hybrid flow – support for userinfo endpoint & better token management app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions { AuthenticationScheme = "OIDC", SignInScheme = "Cookies", Authority = "https://demo.identityserver.io", ClientId = "mvc", ClientSecret = "secret" ResponseType = "code id_token", SaveTokens = true });

Slide 37

Slide 37 text

37 @leastprivilege Web API Authentication • Middleware for JWT access tokens built-in – cookies not recommended app.UseJwtBearerAuthentication(new JwtBearerOptions { Authority = "https://localhost:44300", Audience = "my.api", options.AutomaticAuthenticate = true; });

Slide 38

Slide 38 text

38 @leastprivilege Issuing Tokens • No built-in token issuance middleware anymore – "Azure B2C Emulator" soon • IdentityServer is a full featured & certified token service – OpenID Connect and OAuth 2.0 (+ related specifications) http://github.com/identityserver

Slide 39

Slide 39 text

39 @leastprivilege Authorization • Complete re-write – support for unauthorized vs forbidden – better separation of business code and authorization logic – re-usable policies – resource/action based authorization – DI enabled

Slide 40

Slide 40 text

40 @leastprivilege [Authorize] • Similar syntax – roles still supported* [Authorize] public class HomeController : Controller { [AllowAnonymous] public IActionResult Index() { return View(); } [Authorize(Roles = "Sales")] public IActionResult About() { return View(User); } } * …and who thought that would be a good idea?

Slide 41

Slide 41 text

41 @leastprivilege Authorization policies services.AddAuthorization(options => { options.AddPolicy("ManageCustomers", policy => { policy.RequireAuthenticatedUser(); policy.RequireClaim("department", "sales"); policy.RequireClaim("status", "senior"); }); }; [Authorize("ManageCustomers")] public IActionResult Manage() { // stuff } Startup Controller

Slide 42

Slide 42 text

42 @leastprivilege Programmatically using policies public class CustomerController : Controller { private readonly IAuthorizationService _authz; public CustomerController(IAuthorizationService authz) { _authz = authz; } public async Task Manage() { var allowed = await _authz.AuthorizeAsync(User, "ManageCustomers"); if (!allowed) return Challenge(); return View(); } }

Slide 43

Slide 43 text

43 @leastprivilege …or from a View @using Microsoft.AspNetCore.Authorization @inject IAuthorizationService _authz @if (await _authz.AuthorizeAsync(User, "ManageCustomers")) { }

Slide 44

Slide 44 text

44 @leastprivilege Custom Requirements public class JobLevelRequirement : IAuthorizationRequirement { public JobLevel Level { get; } public JobLevelRequirement(JobLevel level) { Level = level; } } public static class StatusPolicyBuilderExtensions { public static AuthorizationPolicyBuilder RequireJobLevel( this AuthorizationPolicyBuilder builder, JobLevel level) { builder.AddRequirements(new JobLevelRequirement(level)); return builder; } }

Slide 45

Slide 45 text

45 @leastprivilege Handling Requirements public class JobLevelRequirementHandler : AuthorizationHandler { private readonly IOrganizationService _service; public JobLevelRequirementHandler(IOrganizationService service) { _service = service; } protected override void Handle( AuthorizationContext context, JobLevelRequirement requirement) { var currentLevel = _service.GetJobLevel(context.User); if (currentLevel == requirement.Level) { context.Succeed(requirement); } } }

Slide 46

Slide 46 text

46 @leastprivilege Resource-based Authorization Subject Object Operation - client ID - subject ID - scopes - more claims + DI - read - write - send via email - ... - ID - owner - more properties + DI

Slide 47

Slide 47 text

47 @leastprivilege Example: Document resource public class DocumentAuthorizationHandler : AuthorizationHandler { public override Task HandleRequirementAsync( AuthorizationHandlerContext context, OperationAuthorizationRequirement operation, Document resource) { // authorization logic } } services.AddTransient(); Add handler in DI:

Slide 48

Slide 48 text

48 @leastprivilege Invoking the authorization handler public class DocumentController : Controller { private readonly IAuthorizationService _authz; public DocumentController(IAuthorizationService authz) { _authz = authz; } public async Task Update(Document doc) { if (!await _authz.AuthorizeAsync(User, doc, Operations.Update)) { // forbidden return Challenge(); } // do stuff } }

Slide 49

Slide 49 text

49 @leastprivilege Resources • https://github.com/leastprivilege/ – AspNetCoreSecuritySamples • https://github.com/dotnet – corefx – coreclr • https://github.com/aspnet – home – security – announcements • http://docs.asp.net

Slide 50

Slide 50 text

50 @leastprivilege thank you!