|
using Microsoft.AspNetCore.Authentication; |
|
using Microsoft.AspNetCore.Authentication.JwtBearer; |
|
using Microsoft.AspNetCore.Http; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Security.Claims; |
|
using System.Threading.Tasks; |
|
using Vonk.Core.Context; |
|
using Vonk.Core.Context.VonkContext; |
|
using Vonk.Core.Support; |
|
|
|
namespace Vonk.Authorization |
|
{ |
|
public class VonkAuthorizationMiddleware |
|
{ |
|
private readonly RequestDelegate _next; |
|
|
|
public VonkAuthorizationMiddleware(RequestDelegate next) |
|
{ |
|
_next = next; |
|
} |
|
|
|
public async Task Invoke(HttpContext httpContext) |
|
{ |
|
var vonkContext = httpContext.Vonk(); |
|
try |
|
{ |
|
var auth = await httpContext.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme); |
|
|
|
if (auth?.Principal?.Identity?.IsAuthenticated ?? false) |
|
{ |
|
var claims = auth.Principal.Claims ?? Enumerable.Empty<Claim>(); |
|
if (Authorized(vonkContext, claims)) |
|
{ |
|
await _next(httpContext); |
|
} |
|
else |
|
{ |
|
vonkContext.Response.HttpResult = StatusCodes.Status401Unauthorized; |
|
vonkContext.Response.AddIssue("You are not authorized for this request", VonkIssues.UNAUTHORIZED); |
|
} |
|
} |
|
} |
|
catch |
|
{ |
|
//handle authentication errors; |
|
} |
|
} |
|
|
|
private bool Authorized(IVonkContext context, IEnumerable<Claim> claims) |
|
{ |
|
//The claims contain roles, or roles can be derived from the claims. |
|
//Match them with the information in the request to allow or deny the request. |
|
//If for example the claims contain the operations you are allowed to invoke, you could do: |
|
switch (context.Request.Interaction) |
|
{ |
|
case VonkInteraction.instance_read: |
|
return claims.Any(claim => claim.Value == "read"); |
|
case Core.Context.VonkInteraction.instance_update: |
|
return claims.Any(claim => claim.Value == "update"); |
|
case Core.Context.VonkInteraction.instance_delete: |
|
return claims.Any(claim => claim.Value == "delete"); |
|
case Core.Context.VonkInteraction.type_create: |
|
return claims.Any(claim => claim.Value == "create"); |
|
case Core.Context.VonkInteraction.type_search: |
|
return claims.Any(claim => claim.Value == "search"); |
|
default: |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
} |
@cknaap What configuration would be required when receiving the following Exception?
and/or: