diff --git a/src/isolated/FunctionsAuthenticationMiddleware.cs b/src/isolated/FunctionsAuthenticationMiddleware.cs
new file mode 100644
index 0000000..b472276
--- /dev/null
+++ b/src/isolated/FunctionsAuthenticationMiddleware.cs
@@ -0,0 +1,86 @@
+//
+// Copyright (c) DarkLoop. All rights reserved.
+//
+
+using DarkLoop.Azure.Functions.Authorization.Internal;
+using DarkLoop.Azure.Functions.Authorization.Properties;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Http.Features.Authentication;
+using Microsoft.Azure.Functions.Worker;
+using Microsoft.Azure.Functions.Worker.Middleware;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace DarkLoop.Azure.Functions.Authorization;
+
+internal sealed class FunctionsAuthenticationMiddleware : IFunctionsWorkerMiddleware
+{
+ private readonly ILogger _logger;
+ private readonly IAuthenticationHandlerProvider _authenticationHandlerProvider;
+ private readonly IAuthenticationSchemeProvider _authenticationSchemeProvider;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// authentication handler provider.
+ /// authentication scheme provider.
+ /// A logger object for diagnostics.
+ public FunctionsAuthenticationMiddleware(
+ IAuthenticationHandlerProvider authenticationHandlerProvider,
+ IAuthenticationSchemeProvider authenticationSchemeProvider,
+ ILogger logger)
+ {
+ Check.NotNull(authenticationHandlerProvider, nameof(authenticationHandlerProvider));
+ Check.NotNull(authenticationSchemeProvider, nameof(authenticationSchemeProvider));
+ Check.NotNull(logger, nameof(logger));
+
+ _authenticationHandlerProvider = authenticationHandlerProvider;
+ _authenticationSchemeProvider = authenticationSchemeProvider;
+ _logger = logger;
+ }
+
+ ///
+ public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
+ {
+ var httpContext = context.GetHttpContext() ?? throw new NotSupportedException(IsolatedMessages.NotSupportedIsolatedMode);
+
+ foreach (var scheme in await _authenticationSchemeProvider.GetRequestHandlerSchemesAsync())
+ {
+ var handler = await _authenticationHandlerProvider.GetHandlerAsync(httpContext, scheme.Name) as IAuthenticationRequestHandler;
+ if (handler != null && await handler.HandleRequestAsync())
+ {
+ return;
+ }
+ }
+
+ var defaultAuthenticate = await _authenticationSchemeProvider.GetDefaultAuthenticateSchemeAsync();
+ if (defaultAuthenticate != null)
+ {
+ var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name);
+ if (result?.Principal != null)
+ {
+ httpContext.User = result.Principal;
+ }
+ if (result?.Succeeded ?? false)
+ {
+ var authFeatures = httpContext.Features.SetAuthenticationFeatures(result);
+ context.Features.Set(authFeatures);
+ context.Features.Set(authFeatures);
+ }
+ else
+ {
+ var allSchemes = (await _authenticationSchemeProvider.GetAllSchemesAsync()).ToList();
+ _logger.LogDebug(
+ IsolatedMessages.AuthenticationFailed,
+ allSchemes.Count > 0
+ ? " for " + string.Join(", ", allSchemes)
+ : string.Empty);
+ }
+ }
+
+ await next(context);
+ }
+
+}
\ No newline at end of file
diff --git a/src/isolated/FunctionsAuthorizationMiddleware.cs b/src/isolated/FunctionsAuthorizationMiddleware.cs
index 7490e79..97798ce 100644
--- a/src/isolated/FunctionsAuthorizationMiddleware.cs
+++ b/src/isolated/FunctionsAuthorizationMiddleware.cs
@@ -2,31 +2,33 @@
// Copyright (c) DarkLoop. All rights reserved.
//
-using System;
-using System.Threading.Tasks;
using DarkLoop.Azure.Functions.Authorization.Internal;
using DarkLoop.Azure.Functions.Authorization.Properties;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Policy;
using Microsoft.AspNetCore.Http.Extensions;
-using Microsoft.AspNetCore.Http.Features.Authentication;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Middleware;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
+using System;
+using System.Threading.Tasks;
namespace DarkLoop.Azure.Functions.Authorization
{
///
internal sealed class FunctionsAuthorizationMiddleware : IFunctionsWorkerMiddleware
{
+
private readonly IFunctionsAuthorizationProvider _authorizationProvider;
private readonly IFunctionsAuthorizationResultHandler _authorizationResultHandler;
- private readonly IAuthorizationPolicyProvider _policyProvider;
- private readonly IPolicyEvaluator _policyEvaluator;
private readonly IOptionsMonitor _configOptions;
private readonly ILogger _logger;
+ private readonly IPolicyEvaluator _policyEvaluator;
+ private readonly IAuthorizationPolicyProvider _policyProvider;
+
+
///
/// Initializes a new instance of the class.
@@ -38,12 +40,12 @@ internal sealed class FunctionsAuthorizationMiddleware : IFunctionsWorkerMiddlew
/// Functions authorization configure options.
/// A logger object for diagnostics.
public FunctionsAuthorizationMiddleware(
- IFunctionsAuthorizationProvider authorizationProvider,
- IFunctionsAuthorizationResultHandler authorizationHandler,
- IAuthorizationPolicyProvider policyProvider,
- IPolicyEvaluator policyEvaluator,
- IOptionsMonitor configOptions,
- ILogger logger)
+ IFunctionsAuthorizationProvider authorizationProvider,
+ IFunctionsAuthorizationResultHandler authorizationHandler,
+ IAuthorizationPolicyProvider policyProvider,
+ IPolicyEvaluator policyEvaluator,
+ IOptionsMonitor configOptions,
+ ILogger logger)
{
Check.NotNull(authorizationProvider, nameof(authorizationProvider));
Check.NotNull(authorizationHandler, nameof(authorizationHandler));
@@ -60,6 +62,8 @@ public FunctionsAuthorizationMiddleware(
_logger = logger;
}
+
+
///
public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
{
@@ -83,28 +87,10 @@ public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next
return;
}
- var authenticateResult = await _policyEvaluator.AuthenticateAsync(filter.Policy, httpContext);
-
- var authenticateFeature = httpContext.Features.SetAuthenticationFeatures(authenticateResult);
+ var authenticateFeature = context.Features.Get();
- // We also make the features available in the FunctionContext
- context.Features.Set(authenticateFeature);
- context.Features.Set(authenticateFeature);
-
- if (filter.AllowAnonymous)
- {
- await next(context);
- return;
- }
-
- if (authenticateResult is not null && !authenticateResult.Succeeded)
- {
- _logger.LogDebug(
- IsolatedMessages.AuthenticationFailed,
- filter.Policy.AuthenticationSchemes.Count > 0
- ? " for " + string.Join(", ", filter.Policy.AuthenticationSchemes)
- : string.Empty);
- }
+ var authenticateResult = authenticateFeature?.AuthenticateResult ??
+ await _policyEvaluator.AuthenticateAsync(filter.Policy, httpContext);
var authorizeResult = await _policyEvaluator.AuthorizeAsync(filter.Policy, authenticateResult!, httpContext, httpContext);
var authContext = new FunctionAuthorizationContext(
@@ -112,5 +98,6 @@ public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next
await _authorizationResultHandler.HandleResultAsync(authContext, httpContext, async (ctx) => await next(ctx));
}
+
}
-}
+}
\ No newline at end of file
diff --git a/src/isolated/FunctionsAuthorizationWorkerAppBuilderExtensions.cs b/src/isolated/FunctionsAuthorizationWorkerAppBuilderExtensions.cs
index ec20163..b2ae536 100644
--- a/src/isolated/FunctionsAuthorizationWorkerAppBuilderExtensions.cs
+++ b/src/isolated/FunctionsAuthorizationWorkerAppBuilderExtensions.cs
@@ -3,6 +3,7 @@
//
using DarkLoop.Azure.Functions.Authorization;
+using DarkLoop.Azure.Functions.Authorization.Extensions;
using DarkLoop.Azure.Functions.Authorization.Features;
using Microsoft.Extensions.Hosting;
@@ -13,13 +14,45 @@ namespace Microsoft.Azure.Functions.Worker
///
public static class FunctionsAuthorizationWorkerAppBuilderExtensions
{
+
+ ///
+ /// Adds both DarkLoop's Functions authentication and authorization middleware to the application pipeline.
+ ///
+ /// The current builder.
+ public static IFunctionsWorkerApplicationBuilder UseFunctionsAuth(this IFunctionsWorkerApplicationBuilder builder)
+ {
+ builder.UseWhen(context =>
+ context.IsHttpTrigger() &&
+ context.Features.Get() is not null);
+
+ builder.UseWhen(context =>
+ context.IsHttpTrigger() &&
+ context.Features.Get() is not null);
+
+ return builder;
+ }
+
+ ///
+ /// Adds DarkLoop's Functions authentication middleware to the application pipeline.
+ /// if the function is an HTTP trigger and the is available.
+ ///
+ /// The current builder.
+ public static IFunctionsWorkerApplicationBuilder UseFunctionsAuthentication(this IFunctionsWorkerApplicationBuilder builder)
+ {
+ return builder.UseWhen(context =>
+ context.IsHttpTrigger() &&
+ context.Features.Get() is not null);
+ }
+
///
/// Adds DarkLoop's Functions authorization middleware to the application pipeline.
+ /// if the function is an HTTP trigger and the is available.
///
/// The current builder.
public static IFunctionsWorkerApplicationBuilder UseFunctionsAuthorization(this IFunctionsWorkerApplicationBuilder builder)
{
return builder.UseWhen(context =>
+ context.IsHttpTrigger() &&
context.Features.Get() is not null);
}
}