-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathAuthorizationFunctionMiddleware.cs
More file actions
90 lines (77 loc) · 4.04 KB
/
AuthorizationFunctionMiddleware.cs
File metadata and controls
90 lines (77 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
using System;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Azure.Functions.Worker.Middleware;
using Microsoft.Extensions.Primitives;
namespace AzureFunctions.Extensions.OpenIDConnect.Isolated
{
public class AuthorizationFunctionMiddleware : IFunctionsWorkerMiddleware
{
private readonly IAuthenticationService _authenticationService;
private readonly IRouteGuardian _routeGuardian;
private readonly IAuthorizationService _authorizationService;
private readonly IAuthorizationRequirementsRetriever _requirementsRetriever;
private readonly IHttpFunctionContextAccessorFactory _httpFunctionContextAccessorFactory;
public AuthorizationFunctionMiddleware(IAuthenticationService authenticationService,
IRouteGuardian routeGuardian, IAuthorizationService authorizationService,
IAuthorizationRequirementsRetriever requirementsRetriever,
IHttpFunctionContextAccessorFactory httpFunctionContextAccessorFactory)
{
_authenticationService = authenticationService;
_routeGuardian = routeGuardian;
_authorizationService = authorizationService;
_requirementsRetriever = requirementsRetriever;
_httpFunctionContextAccessorFactory = httpFunctionContextAccessorFactory;
}
public async Task Invoke(FunctionContext executingContext, FunctionExecutionDelegate next)
{
if (_routeGuardian.IsProtectedRoute(executingContext.FunctionDefinition.Name))
{
var functionContextAccessor = _httpFunctionContextAccessorFactory.Create(executingContext);
var requestData = await functionContextAccessor.GetHttpRequestDataAsync();
var headers = new HeaderDictionary(requestData.Headers.ToDictionary(x => x.Key, x => new StringValues(x.Value.ToArray())));
// Authenticate the user
var authenticationResult = await _authenticationService.AuthenticateAsync(headers);
if (authenticationResult.Failed)
{
Unauthorized(functionContextAccessor, requestData);
return;
}
executingContext.Items.Add(HttpRequestDataExtensions.UserKey, authenticationResult.User);
var attribute = _routeGuardian.GetAuthorizationConfiguration(executingContext.FunctionDefinition.Name);
var requirements = _requirementsRetriever.ForAttribute(attribute);
if (requirements != null)
{
var authorizationResult = await _authorizationService.AuthorizeAsync(authenticationResult.User, executingContext, requirements);
if (!authorizationResult.Succeeded)
{
Forbidden(functionContextAccessor, requestData, authorizationResult.Failure);
return;
}
}
}
await next(executingContext);
}
private static void Unauthorized(IHttpFunctionContextAccessor executingContext,
HttpRequestData httpRequestData)
{
var response = HttpResponseData.CreateResponse(httpRequestData);
response.StatusCode = HttpStatusCode.Unauthorized;
executingContext.SetInvocationResult(response);
}
private static void Forbidden(IHttpFunctionContextAccessor executingContext,
HttpRequestData httpRequestData, AuthorizationFailure failure)
{
var response = HttpResponseData.CreateResponse(httpRequestData);
response.StatusCode = HttpStatusCode.Forbidden;
response.Body.Write(Encoding.UTF8.GetBytes(String.Join(',', failure.FailedRequirements.Select(x => x.ToString()))));
executingContext.SetInvocationResult(response);
}
}
}