Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Securing Web Applications and APIs with ASP.NET Core 2.2 and 3.0

Securing Web Applications and APIs with ASP.NET Core 2.2 and 3.0

Dominick Baier

January 25, 2019
Tweet

More Decks by Dominick Baier

Other Decks in Programming

Transcript

  1. 2 @leastprivilege / @brocklallen Me • Independent Consultant – Specializing

    on Application Security Architectures – Working with Software Development Teams (ISVs and in-house) • Co-Creator of IdentityServer & IdentityModel OSS Project – Certified OpenID Connect & OAuth 2.0 Implementation for .NET – https://identityserver.io • Co-Creator of PolicyServer – Modern Authorization Solution – https://policyserver.io email [email protected] blog http://leastprivilege.com twitter @leastprivilege slides https://speakerdeck.com/leastprivilege
  2. Modern Application Architecture Browser Native App Server App/Thing Web App

    Service Service Service Identity Provider Authorization Policy Provider
  3. 6 @leastprivilege / @brocklallen Agenda • Hosting • Data Protection

    • Authentication • Authorization • Identity • IdentityServer integration https://github.com/leastprivilege/AspNetCoreSecuritySamples
  4. 8 @leastprivilege / @brocklallen Kestrel Security • HTTPS by default

    – static configuration or dynamic selection (SNI) – dotnet dev-certs tool for local development • Need to fine-tune transport parameters when doing edge hosting – Keep-Alive timeouts – Request Header limits – Request/Response buffer sizes – Request line size – Request header limits – Request header count limits – Request/Response body timeouts & data rates – Total client connections – Handshake timeous – …
  5. 9 @leastprivilege / @brocklallen ASP.NET Core Architecture • Host •

    Pipeline & middleware • Services Console Application .NET (Core) ASP.NET Core Middleware Middleware User Agent MVC DI
  6. 10 @leastprivilege / @brocklallen Data Protection • Remember this? <system.web>

    <!– copied from the 90ies --> <machineKey decryptionKey="656E7...617365206865726547A5" validationKey="07C1493415E4405F08...6EF8B1F" /> </system.web> For giggles: "https://www.google.com/#q=<machineKey filetype:config"
  7. 11 @leastprivilege / @brocklallen Data Protection in ASP.NET Core •

    Keys are stored outside of application directory – profile – registry – Azure web apps magic – Redis – manual • Automatic key management – 512 bit master key / AES-256 CBC / HMACSHA256 – rotated every 90 days – automatic application isolation • Key protection – DPAPI, X509, Azure KeyVault
  8. 13 @leastprivilege / @brocklallen Who uses Data Protection? • ASP.NET

    Core – protecting cookies – anti-forgery – protecting OpenID Connect/OAuth state – [TempData] • You – IDataProtectionProvider service – can be also used with non-ephemeral data • if key ring is properly stored / backed-up
  9. 14 @leastprivilege / @brocklallen Authentication in ASP.NET Core • Authenticating

    users/clients – local – Google, Facebook, and other proprietary providers* – OpenID Connect, WS-Federation & SAML** for standards-based external authentication – JSON web token (JWT) for token-based API authentication • Session Management – cookies * 40+ more https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers ** https://github.com/Sustainsys/Saml2
  10. 15 @leastprivilege / @brocklallen Setting up authentication public void ConfigureServices(IServiceCollection

    services) { services.AddAuthentication(defaultScheme: "cookies") .AddCookies(scheme: "cookies") .AddGoogle(scheme: "google") .AddOpenIdConnect(scheme: "idsrv"); } public void Configure(IApplicationBuilder app) { app.UseAuthentication(); }
  11. 16 @leastprivilege / @brocklallen Interacting with the authentication system public

    interface IAuthenticationService { // authenticate the specified scheme. Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme); // session management Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties); Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties); // signal that authentication is required Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties); // signal that access is denied Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties); }
  12. 17 @leastprivilege / @brocklallen Interacting with the authentication system (2)

    • Convenience extension methods public static class AuthenticationHttpContextExtensions { public static Task SignInAsync(this HttpContext context, ClaimsPrincipal principal) { } public static Task SignInAsync(this HttpContext context, string scheme, ClaimsPrincipal principal) { } public static Task SignOutAsync(this HttpContext context) { } public static Task SignOutAsync(this HttpContext context, string scheme) { } public static Task ChallengeAsync(this HttpContext context) { } public static Task ChallengeAsync(this HttpContext context, string scheme) { } public static Task ForbidAsync(this HttpContext context) { } public static Task ForbidAsync(this HttpContext context, string scheme) { } public static Task<AuthenticateResult> AuthenticateAsync(this HttpContext context) { } public static Task<AuthenticateResult> AuthenticateAsync(this HttpContext context, string scheme) { } }
  13. 18 @leastprivilege / @brocklallen Session Management (1) public void ConfigureServices(IServiceCollection

    services) { services.AddAuthentication(defaultScheme: "Cookies") .AddCookie("Cookies", options => { options.LoginPath = "/account/login"; options.AccessDeniedPath = "/account/denied"; options.Cookie.Name = "myapp"; options.Cookie.Expiration = TimeSpan.FromHours(8); options.SlidingExpiration = false; options.Cookie.SameSite = SameSiteMode.Lax; }); }
  14. 19 @leastprivilege / @brocklallen Session Management (2) • Cookie contains

    – claims – metadata var claims = new List<Claim> { new Claim("sub", "123"), new Claim("name", "Bob") }; var ci = new ClaimsIdentity(claims, "password", "name", "role"); var props = new AuthenticationProperties { Items = { { "token", "abc" } } }; await HttpContext.SignInAsync(new ClaimsPrincipal(ci), props); await HttpContext.SignOutAsync();
  15. 20 @leastprivilege / @brocklallen Advanced Features • The cookie handler

    has an eventing model – additional validation on incoming cookie – redirect/sign-in/sign-out interception – sign-out cleanup • Session storage mechanism can be replaced – e.g. server-side (Redis, Cosmos DB..) – keeps cookies small – allows for server-side revocation https://leastprivilege.com/2019/01/14/automatic-oauth-2-0-token-management-in-asp-net-core/
  16. 21 @leastprivilege / @brocklallen External Authentication • Special type of

    authentication handler – RemoteAuthenticationHandler – ChallengeAsync sends authentication/token request – SignOutAsync sends sign-out request – provides callback endpoints to process protocol responses Challenge(scheme) Handler's ChallengeAsync method gets invoked Redirect to external provider External provider Authentication middleware asks handlers who wants to process request callback Handlers does the protocol post- processing Call sign-in handler (sets cookie containing external identity) Redirect to final URL
  17. 22 @leastprivilege / @brocklallen Example: Sign-in & Token Request w/

    OpenID Connect services.AddAuthentication(options => { options.DefaultScheme = "cookies"; options.DefaultChallengeScheme = "oidc"; }) .AddCookie("cookies") .AddOpenIdConnect("oidc", options => { options.Authority = "https://demo.identityserver.io"; options.ClientId = "server.hybrid"; options.ClientSecret = "secret"; options.ResponseType = "code id_token"; options.Scope.Clear(); options.Scope.Add("openid"); options.Scope.Add("api"); });
  18. 23 @leastprivilege / @brocklallen API Authentication • Built-in support for

    JWT bearer tokens – see https://github.com/IdentityModel/IdentityModel.AspNetCore.OAuth2Introspection for RFC 7662 support public void ConfigureServices(IServiceCollection services) { services.AddAuthentication("jwt") .AddJwtBearer("jwt", options => { options.Authority = "https://demo.identityserver.com"; options.Audience = "api" }); }
  19. 24 @leastprivilege / @brocklallen Authorization • Policy-based authorization – based

    on properties of the caller/user • Resource-based authorization – takes the resource that is being manipulated into account as well • Authorization is a service – DI based – extensible – testable • Will be also available as middleware in 3.0 https://github.com/blowdart/AspNetAuthorizationWorkshop
  20. 25 @leastprivilege / @brocklallen Example Authorization Policy 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
  21. 26 @leastprivilege / @brocklallen Programmatically using policies public class CustomerController

    : Controller { private readonly IAuthorizationService _authz; public CustomerController(IAuthorizationService authz) { _authz = authz; } public async Task<IActionResult> Manage() { var result = await _authz.AuthorizeAsync(User, "ManageCustomers"); if (result.Succeeded) return View(); return Forbid(); } }
  22. 27 @leastprivilege / @brocklallen Custom Authorization Handler public class JobLevelRequirementHandler

    : AuthorizationHandler<JobLevelRequirement> { 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); } } }
  23. 28 @leastprivilege / @brocklallen Resource-based Authorization Subject Object Operation -

    client ID - subject ID - scopes - more claims + DI - read - write - send via email - ... - ID - owner - more properties + DI
  24. 29 @leastprivilege / @brocklallen Example: Document resource public class DocumentAuthorizationHandler

    : AuthorizationHandler<OperationAuthorizationRequirement, Document> { public override Task HandleRequirementAsync( AuthorizationHandlerContext context, OperationAuthorizationRequirement operation, Document resource) { // authz logic } }
  25. 30 @leastprivilege / @brocklallen Invoking the authorization handler public class

    DocumentController : Controller { private readonly IAuthorizationService _authz; public DocumentController(IAuthorizationService authz) { _authz = authz; } public async Task<IActionResult> Update(Document doc) { if ((await _authz.AuthorizeAsync(User, doc, Operations.Update)).Failure) { return Forbid(); } // do stuff } }
  26. 31 @leastprivilege / @brocklallen ASP.NET Identity • Library for managing

    identity data for users – manages credentials (e.g. passwords, complexity) – lockout for brute force prevention – mapping external authentication • Stores this data in database – can be used to maintain additional user attributes/claims • Provides primitives for email confirmation, password reset, and MFA workflows • Abstraction on cookie authentication handler – sign-in/sign-out
  27. 32 @leastprivilege / @brocklallen The missing link • ASP.NET Identity

    templates are geared towards local authentication • IdentityServer adds OpenID Connect & OAuth 2.0 for remote authentication • ASP.NET Core 2.2 + ships with an IdentityServer integration library – "zero config" IdentityServer using ASP.NET Identity & local APIs – Web API and SPA template • Will be expanded to more advanced scenarios in 3.0 – separating IdentityServer from APIs – dynamic client registration