From 59f8a859b2fa9ef1b989529b4a21dbb12818154e Mon Sep 17 00:00:00 2001 From: James Randall Date: Sun, 12 May 2019 11:51:02 +0100 Subject: [PATCH] Added support for custom claims binders --- .../Builders/IAuthorizationBuilder.cs | 9 +++++++++ .../FunctionMonkey.Abstractions.csproj | 6 +++--- .../ICommandClaimsBinder.cs | 7 +++++++ .../FunctionMonkey.Commanding.Abstractions.csproj | 6 +++--- ...onMonkey.Commanding.Cosmos.Abstractions.csproj | 6 +++--- .../FunctionMonkey.Compiler.csproj | 6 +++--- .../FunctionMonkey.Compiler.nuspec | 2 +- .../Templates/http.csharp.handlebars | 10 +++++++++- .../signalrcommandnegotiate.csharp.handlebars | 10 +++++++++- .../FunctionMonkey.FluentValidation.csproj | 6 +++--- .../FunctionMonkey.SignalR.csproj | 2 +- .../FunctionMonkey.Testing.csproj | 6 +++--- .../Mocks/CommandClaimsBinderMock.cs | 6 ++++++ .../Builders/AuthorizationBuilder.cs | 8 ++++++++ Source/FunctionMonkey/FunctionMonkey.csproj | 6 +++--- .../Infrastructure/CommandClaimsBinder.cs | 12 ++++++++++++ Source/FunctionMonkey/RuntimeInstance.cs | 15 +++++++++++---- 17 files changed, 94 insertions(+), 29 deletions(-) diff --git a/Source/FunctionMonkey.Abstractions/Builders/IAuthorizationBuilder.cs b/Source/FunctionMonkey.Abstractions/Builders/IAuthorizationBuilder.cs index bdaf2b6b..50a56b9c 100644 --- a/Source/FunctionMonkey.Abstractions/Builders/IAuthorizationBuilder.cs +++ b/Source/FunctionMonkey.Abstractions/Builders/IAuthorizationBuilder.cs @@ -39,6 +39,15 @@ public interface IAuthorizationBuilder /// The builder for use in a Fluent API IAuthorizationBuilder TokenValidator(string header=null) where TTokenValidator : ITokenValidator; + /// + /// Allows a custom claims binder to be registered. This can only occur globally and must take responsibility + /// for all claims mapping. + /// + /// The type of the claims binder + /// The builder for use in a Fluent API + IAuthorizationBuilder CustomClaimsBinder() + where TCustomClaimsBinder : ICommandClaimsBinder; + /// /// Allows the default authorization mode for HTTP functions to be set. Defaults to Function Code if this method is not used. /// diff --git a/Source/FunctionMonkey.Abstractions/FunctionMonkey.Abstractions.csproj b/Source/FunctionMonkey.Abstractions/FunctionMonkey.Abstractions.csproj index fa343849..64ccd4f4 100644 --- a/Source/FunctionMonkey.Abstractions/FunctionMonkey.Abstractions.csproj +++ b/Source/FunctionMonkey.Abstractions/FunctionMonkey.Abstractions.csproj @@ -2,13 +2,13 @@ netstandard2.0 - 2.1.0 + 2.2.0 James Randall https://raw.githubusercontent.com/JamesRandall/AzureFromTheTrenches.Commanding/master/LICENSE https://commanding.azurefromthetrenches.com/ https://github.com/JamesRandall/FunctionMonkey.git - 2.1.0.0 - 2.1.0.0 + 2.2.0.0 + 2.2.0.0 diff --git a/Source/FunctionMonkey.Abstractions/ICommandClaimsBinder.cs b/Source/FunctionMonkey.Abstractions/ICommandClaimsBinder.cs index 539baa48..374fd56b 100644 --- a/Source/FunctionMonkey.Abstractions/ICommandClaimsBinder.cs +++ b/Source/FunctionMonkey.Abstractions/ICommandClaimsBinder.cs @@ -1,4 +1,5 @@ using System.Security.Claims; +using System.Threading.Tasks; using AzureFromTheTrenches.Commanding.Abstractions; namespace FunctionMonkey.Abstractions @@ -13,5 +14,11 @@ public interface ICommandClaimsBinder /// Binds the claims in the principal onto properties of the command /// bool Bind(ClaimsPrincipal principal, ICommand command); + + /// + /// Binds the claims in the principal onto properties of the command. If this returns null then + /// the non-async binder will be called. + /// + Task BindAsync(ClaimsPrincipal principal, ICommand command); } } diff --git a/Source/FunctionMonkey.Commanding.Abstractions/FunctionMonkey.Commanding.Abstractions.csproj b/Source/FunctionMonkey.Commanding.Abstractions/FunctionMonkey.Commanding.Abstractions.csproj index a0fd06c6..456c67d9 100644 --- a/Source/FunctionMonkey.Commanding.Abstractions/FunctionMonkey.Commanding.Abstractions.csproj +++ b/Source/FunctionMonkey.Commanding.Abstractions/FunctionMonkey.Commanding.Abstractions.csproj @@ -2,14 +2,14 @@ netstandard2.0 - 2.1.0 + 2.2.0 James Randall James Randall https://raw.githubusercontent.com/JamesRandall/AzureFromTheTrenches.Commanding/master/LICENSE https://functionmonkey.azurefromthetrenches.com/ https://github.com/JamesRandall/FunctionMonkey.git - 2.1.0.0 - 2.1.0.0 + 2.2.0.0 + 2.2.0.0 diff --git a/Source/FunctionMonkey.Commanding.Cosmos.Abstractions/FunctionMonkey.Commanding.Cosmos.Abstractions.csproj b/Source/FunctionMonkey.Commanding.Cosmos.Abstractions/FunctionMonkey.Commanding.Cosmos.Abstractions.csproj index f828c983..b700c650 100644 --- a/Source/FunctionMonkey.Commanding.Cosmos.Abstractions/FunctionMonkey.Commanding.Cosmos.Abstractions.csproj +++ b/Source/FunctionMonkey.Commanding.Cosmos.Abstractions/FunctionMonkey.Commanding.Cosmos.Abstractions.csproj @@ -2,9 +2,9 @@ netstandard2.0 - 2.1.0 - 2.1.0.0 - 2.1.0.0 + 2.2.0 + 2.2.0.0 + 2.2.0.0 James Randall James Randall https://raw.githubusercontent.com/JamesRandall/AzureFromTheTrenches.Commanding/master/LICENSE diff --git a/Source/FunctionMonkey.Compiler/FunctionMonkey.Compiler.csproj b/Source/FunctionMonkey.Compiler/FunctionMonkey.Compiler.csproj index fd590731..f5a6182c 100644 --- a/Source/FunctionMonkey.Compiler/FunctionMonkey.Compiler.csproj +++ b/Source/FunctionMonkey.Compiler/FunctionMonkey.Compiler.csproj @@ -3,7 +3,7 @@ Exe netcoreapp2.1 - 2.1.1 + 2.2.0 FunctionMonkey.Compiler FunctionMonkey.Compiler @@ -385,8 +385,8 @@ $(MSBuildProjectDirectory)/bin/$(Configuration)/publish/ $(IntermediatePackDir)$(TargetFramework)/ publishDir=$([MSBuild]::NormalizeDirectory($(IntermediatePackDir))) - 2.1.1.0 - 2.1.1.0 + 2.2.0.0 + 2.2.1.0 diff --git a/Source/FunctionMonkey.Compiler/FunctionMonkey.Compiler.nuspec b/Source/FunctionMonkey.Compiler/FunctionMonkey.Compiler.nuspec index 1af39a45..e18a0a38 100644 --- a/Source/FunctionMonkey.Compiler/FunctionMonkey.Compiler.nuspec +++ b/Source/FunctionMonkey.Compiler/FunctionMonkey.Compiler.nuspec @@ -2,7 +2,7 @@ FunctionMonkey.Compiler - 2.1.1 + 2.2.0 James Randall Generates Azure Functions from command registrations https://raw.githubusercontent.com/JamesRandall/AzureFromTheTrenches.Commanding/master/LICENSE diff --git a/Source/FunctionMonkey.Compiler/Templates/http.csharp.handlebars b/Source/FunctionMonkey.Compiler/Templates/http.csharp.handlebars index ae07bec8..28da64fd 100644 --- a/Source/FunctionMonkey.Compiler/Templates/http.csharp.handlebars +++ b/Source/FunctionMonkey.Compiler/Templates/http.csharp.handlebars @@ -222,7 +222,15 @@ namespace {{Namespace}} {{#if ValidatesToken}} var claimsBinder = (FunctionMonkey.Abstractions.ICommandClaimsBinder) FunctionMonkey.Runtime.ServiceProvider.GetService(typeof(FunctionMonkey.Abstractions.ICommandClaimsBinder)); - claimsBinder.Bind(principal, command); + var claimsBinderTask = claimsBinder.BindAsync(principal, command); + if (claimsBinderTask == null) + { + claimsBinder.Bind(principal, command); + } + else + { + await claimsBinderTask; + } {{/if}} {{#if HasHttpResponseHandler}} diff --git a/Source/FunctionMonkey.Compiler/Templates/signalrcommandnegotiate.csharp.handlebars b/Source/FunctionMonkey.Compiler/Templates/signalrcommandnegotiate.csharp.handlebars index f5b3d4ae..b481049e 100644 --- a/Source/FunctionMonkey.Compiler/Templates/signalrcommandnegotiate.csharp.handlebars +++ b/Source/FunctionMonkey.Compiler/Templates/signalrcommandnegotiate.csharp.handlebars @@ -220,7 +220,15 @@ namespace {{Namespace}} {{#if ValidatesToken}} var claimsBinder = (FunctionMonkey.Abstractions.ICommandClaimsBinder) FunctionMonkey.Runtime.ServiceProvider.GetService(typeof(FunctionMonkey.Abstractions.ICommandClaimsBinder)); - claimsBinder.Bind(principal, command); + var claimsBinderTask = claimsBinder.BindAsync(principal, command); + if (claimsBinderTask == null) + { + claimsBinder.Bind(principal, command); + } + else + { + await claimsBinderTask; + } {{/if}} {{#if HasHttpResponseHandler}} diff --git a/Source/FunctionMonkey.FluentValidation/FunctionMonkey.FluentValidation.csproj b/Source/FunctionMonkey.FluentValidation/FunctionMonkey.FluentValidation.csproj index 08e30ede..fb0f9d2d 100644 --- a/Source/FunctionMonkey.FluentValidation/FunctionMonkey.FluentValidation.csproj +++ b/Source/FunctionMonkey.FluentValidation/FunctionMonkey.FluentValidation.csproj @@ -2,14 +2,14 @@ netstandard2.0 - 2.1.0 + 2.2.0 James Randall James Randall https://raw.githubusercontent.com/JamesRandall/AzureFromTheTrenches.Commanding/master/LICENSE https://commanding.azurefromthetrenches.com/ https://github.com/JamesRandall/FunctionMonkey.git - 2.1.0.0 - 2.1.0.0 + 2.2.0.0 + 2.2.0.0 diff --git a/Source/FunctionMonkey.SignalR/FunctionMonkey.SignalR.csproj b/Source/FunctionMonkey.SignalR/FunctionMonkey.SignalR.csproj index 10ffdbf0..d61b7163 100644 --- a/Source/FunctionMonkey.SignalR/FunctionMonkey.SignalR.csproj +++ b/Source/FunctionMonkey.SignalR/FunctionMonkey.SignalR.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 2.1.0 + 2.2.0 diff --git a/Source/FunctionMonkey.Testing/FunctionMonkey.Testing.csproj b/Source/FunctionMonkey.Testing/FunctionMonkey.Testing.csproj index 567f711c..c56ece1e 100644 --- a/Source/FunctionMonkey.Testing/FunctionMonkey.Testing.csproj +++ b/Source/FunctionMonkey.Testing/FunctionMonkey.Testing.csproj @@ -2,7 +2,7 @@ netcoreapp2.2 - 2.1.2 + 2.2.0 James Randall James Randall @@ -10,8 +10,8 @@ https://github.com/JamesRandall/FunctionMonkey.git https://functionmonkey.azurefromthetrenches.com/ true - 2.1.2.0 - 2.1.2.0 + 2.2.0.0 + 2.2.0.0 diff --git a/Source/FunctionMonkey.Testing/Mocks/CommandClaimsBinderMock.cs b/Source/FunctionMonkey.Testing/Mocks/CommandClaimsBinderMock.cs index 61d3e508..15f4c3c5 100644 --- a/Source/FunctionMonkey.Testing/Mocks/CommandClaimsBinderMock.cs +++ b/Source/FunctionMonkey.Testing/Mocks/CommandClaimsBinderMock.cs @@ -1,4 +1,5 @@ using System.Security.Claims; +using System.Threading.Tasks; using AzureFromTheTrenches.Commanding.Abstractions; using FunctionMonkey.Abstractions; @@ -10,5 +11,10 @@ public bool Bind(ClaimsPrincipal principal, ICommand command) { return false; } + + public Task BindAsync(ClaimsPrincipal principal, ICommand command) + { + return null; + } } } diff --git a/Source/FunctionMonkey/Builders/AuthorizationBuilder.cs b/Source/FunctionMonkey/Builders/AuthorizationBuilder.cs index 0be1e6d2..24a1850e 100644 --- a/Source/FunctionMonkey/Builders/AuthorizationBuilder.cs +++ b/Source/FunctionMonkey/Builders/AuthorizationBuilder.cs @@ -14,6 +14,8 @@ internal class AuthorizationBuilder : IAuthorizationBuilder public string AuthorizationHeader { get; set; } public Type DefaultClaimsPrincipalAuthorizationType { get; set; } + + public Type CustomClaimsBinderType { get; set; } public AuthorizationTypeEnum AuthorizationDefaultValue { get; set; } = AuthorizationTypeEnum.Function; @@ -24,6 +26,12 @@ public IAuthorizationBuilder TokenValidator(string header=null) return this; } + public IAuthorizationBuilder CustomClaimsBinder() where TCustomClaimsBinder : ICommandClaimsBinder + { + CustomClaimsBinderType = typeof(TCustomClaimsBinder); + return this; + } + public IAuthorizationBuilder AuthorizationDefault(AuthorizationTypeEnum authorizationDefault) { AuthorizationDefaultValue = authorizationDefault; diff --git a/Source/FunctionMonkey/FunctionMonkey.csproj b/Source/FunctionMonkey/FunctionMonkey.csproj index 054694f7..49ec55fa 100644 --- a/Source/FunctionMonkey/FunctionMonkey.csproj +++ b/Source/FunctionMonkey/FunctionMonkey.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 2.1.1 + 2.2.0 false James Randall @@ -10,8 +10,8 @@ https://functionmonkey.azurefromthetrenches.com/ https://github.com/JamesRandall/FunctionMonkey.git true - 2.1.1.0 - 2.1.1.0 + 2.2.0.0 + 2.2.0.0 diff --git a/Source/FunctionMonkey/Infrastructure/CommandClaimsBinder.cs b/Source/FunctionMonkey/Infrastructure/CommandClaimsBinder.cs index eaa602c1..256bef19 100644 --- a/Source/FunctionMonkey/Infrastructure/CommandClaimsBinder.cs +++ b/Source/FunctionMonkey/Infrastructure/CommandClaimsBinder.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Security.Claims; +using System.Threading.Tasks; using AzureFromTheTrenches.Commanding.Abstractions; using FunctionMonkey.Abstractions; @@ -25,5 +26,16 @@ public bool Bind(ClaimsPrincipal principal, ICommand command) return false; } + + public Task BindAsync(ClaimsPrincipal principal, ICommand command) + { + if (_mappers.TryGetValue(command.GetType(), out var binder)) + { + binder(command, principal); + return Task.FromResult(true); + } + + return Task.FromResult(false); + } } } diff --git a/Source/FunctionMonkey/RuntimeInstance.cs b/Source/FunctionMonkey/RuntimeInstance.cs index e5cacf29..69a99db0 100644 --- a/Source/FunctionMonkey/RuntimeInstance.cs +++ b/Source/FunctionMonkey/RuntimeInstance.cs @@ -160,10 +160,17 @@ private void SetupAuthorization(FunctionHostBuilder builder, FunctionBuilder fun // don't register the token validator type here - that gets passed down to the HTTP function // definitions to allow for function overrides and so is registered as part of HTTP dependencies - - ICommandClaimsBinder commandClaimsBinder = authorizationBuilder.ClaimsMappingBuilder.Build( - functionBuilder.GetHttpFunctionDefinitions().Select(x => x.CommandType).ToArray()); - ServiceCollection.AddSingleton(commandClaimsBinder); + if (authorizationBuilder.CustomClaimsBinderType == null) + { + ICommandClaimsBinder commandClaimsBinder = authorizationBuilder.ClaimsMappingBuilder.Build( + functionBuilder.GetHttpFunctionDefinitions().Select(x => x.CommandType).ToArray()); + ServiceCollection.AddSingleton(commandClaimsBinder); + } + else + { + ServiceCollection.AddTransient(typeof(ICommandClaimsBinder), + authorizationBuilder.CustomClaimsBinderType); + } } private IFunctionAppConfiguration LocateConfiguration(Assembly functionAppConfigurationAssembly)