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

Announcing PolicyServer

Announcing PolicyServer

NDC London 2018

Avatar for Dominick Baier

Dominick Baier

January 17, 2018
Tweet

More Decks by Dominick Baier

Other Decks in Programming

Transcript

  1. Implementing Authorization for Applications & APIs Dominick Baier & Brock

    Allen https://identityserver.io [email protected] @leastprivilege / @brocklallen
  2. 2 @leastprivilege / @brocklallen Authorization is hard! • Many approaches

    – roles, permissions, resource-based, ACLs… (and permutations) – queries vs commands • No standard solution – often very application specific – blurry line between authorization and business rules – XACML good example of failed attempt to standardize
  3. 3 @leastprivilege / @brocklallen Modern Applications Browser Native App Server

    App "Thing" Web App Web API Web API Web API Identity Provider
  4. 5 @leastprivilege / @brocklallen Overloaded Security Token { "iss": "https://idsrv4",

    "exp": 1340819380, "aud": [ "api1", "api2"], "amr": [ "password" ], "auth_time": 12340819300 "sub": "182jmm199", "name": "Doug Ross", "role": [ "Approver", "Doctor" ], "permission": [ "DeleteData", "ManageCustomers", "ChangeTreatmentPlan" ] } authentication metadata identity authorization data roles
  5. 7 @leastprivilege / @brocklallen Permissions and Tokens • Separation of

    concerns – authentication vs authorization – identity system does not have intimate knowledge of application specific authorization rules • "do authorization as close as possible to the resource you are trying to protect" • Tokens can be re-used at several places – claims might have different meaning for each consumer – token & claim bloat • Permissions might change – only way to update the data would be to get a new token
  6. 9 @leastprivilege / @brocklallen Modern Applications Browser Native App Server

    App "Thing" Web App Web API Web API Web API Identity Provider Policy Provider
  7. 10 @leastprivilege / @brocklallen Patient API Oncology API Cardiac API

    Identity Provider Policy Provider authentication + token request get client specific permissions call APIs get API specific permissions Admin UI
  8. 11 @leastprivilege / @brocklallen Global roles (static / dynamic) Management

    API Client API App specific roles (static / dynamic) Roles to permission mappings resources & rules (future) Applications Admin UI Client Library What we prototyped… { "sub": "jd9j91199j1", "role": "Doctor", "contractor": "true" } Policy Provider
  9. 13 @leastprivilege / @brocklallen Some usage patterns • Provide a

    client library to call the policy provider – client library takes care of caching & refreshing • Augment the ClaimsPrincipal – e.g. using claims transformation in pipeline • Use a specialized authorization API – e.g. ASP.NET Core Authorization
  10. 14 @leastprivilege / @brocklallen Client Library public class TreatmentController :

    Controller { private readonly PolicyServerClient _client; public TreatmentController(PolicyServerClient client) { _client = client; } public async Task<IActionResult> Update(TreatmentUpdateModel model) { var policy = await _client.EvaluateAsync(User); // or var isDoctor = await _client.IsInRoleAsync(User, "Doctor"); // or var allowed = await _client.HasPermissionAsync(User, "PrescribeMedication"); } }
  11. 15 @leastprivilege / @brocklallen Augment the ClaimsPrincipal • Inject roles

    and permissions into current principal – backwards compat with existing libraries [Authorize(Roles = "Doctor")] public async Task<IActionResult> Update(TreatmentUpdateModel model) { var isDoctor = User.HasClaim("role", "Doctor"); var permissions = User.FindAll("permission"); }
  12. 16 @leastprivilege / @brocklallen ASP.NET Core Authorization • New authorization

    library from Microsoft – created for ASP.NET Core, but has been back-ported by the community* • Introduces a policy-based framework – decoupling authorization logic from business code – extensible – testable * https://github.com/DavidParks8/Owin-Authorization
  13. 17 @leastprivilege / @brocklallen ASP.NET Core Authorization Policies services.AddAuthorization(options =>

    { options.AddPolicy("PrescribeMedication", policy => { policy.RequireAuthenticatedUser(); policy.RequireClaim("permission", "PrescribeMedication"); }); }); [Authorize("PrescribeMedication")] public IActionResult Update() { // stuff } Startup Controller
  14. 18 @leastprivilege / @brocklallen Programmatically using policies public class TreatmentController

    : Controller { private readonly IAuthorizationService _authz; public TreatmentController(IAuthorizationService authz) { _authz = authz; } public async Task<IActionResult> Update() { var allowed = await _authz.AuthorizeAsync(User, "PrescribeMedication"); if (!allowed) return Challenge(); return View(); } }
  15. 19 @leastprivilege / @brocklallen …or from a View @using Microsoft.AspNetCore.Authorization

    @inject IAuthorizationService _authz @if (await _authz.AuthorizeAsync(User, "PrescribeMedication")) { <div> <a href="/treatment/update">Update</a> </div> }
  16. 20 @leastprivilege / @brocklallen ASP.NET Core Policy Provider • Extensibility

    point that allows creating policies on the fly – no need to create explicit "permission policies" anymore // this policy is not statically defined // but gets created dynamically // check for permission claim [Authorize("PrescribeMedication")] public IActionResult Update() { // stuff } Controller
  17. 21 @leastprivilege / @brocklallen Custom Requirements public class MedicationRequirement :

    IAuthorizationRequirement { public string MedicationName { get; set; } public int Amount { get; set; } }
  18. 22 @leastprivilege / @brocklallen Requirement Handler public class MedicationRequirementHandler :

    AuthorizationHandler<MedicationRequirement> { private readonly PolicyServerClient _client; public MedicationRequirementHandler(PolicyServerClient client) { _client = client; } protected override async Task HandleRequirementAsync( AuthorizationHandlerContext context, MedicationRequirement requirement) { var user = context.User; var allowed = false; if (await _client.HasPermissionAsync(user, "PrescribeMedication")) { if (requirement.Amount < 10) allowed = true; else allowed = await _client.IsInRoleAsync(user, "Doctor"); if (allowed || requirement.MedicationName == "placebo") { context.Succeed(requirement); } } } }
  19. 23 @leastprivilege / @brocklallen Using a custom Requirement public async

    Task<IActionResult> Prescribe(int amount) { var meds = new MedicationRequirement { MedicationName = "aspirin", Amount = amount }; var allowed = await _authz.AuthorizeAsync(User, meds); if (!allowed) return Challenge(); return View("Confirm"); }
  20. 24 @leastprivilege / @brocklallen Global ASP.NET Core authorization policy public

    void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() // add arbitrary complex policy .Build(); options.Filters.Add(new AuthorizeFilter(policy)); }); }
  21. 25 @leastprivilege / @brocklallen Conclusion • Different levels of authorization

    lend to different abstractions Application/API application access feature feature feature access application logic ? Access token/global policy Role/permission checks Custom business logic