From 3699bd719c136700c7ae16bc127adb971675aef6 Mon Sep 17 00:00:00 2001 From: dncsvr Date: Wed, 24 Apr 2024 20:56:01 +0300 Subject: [PATCH] add multi authentication documentation - minor edits --- .../MultiAuthenticationExtensions.cs | 27 ++-- authentication/README.md | 120 ++++++++++++++++++ 2 files changed, 134 insertions(+), 13 deletions(-) diff --git a/authentication/MultiAuthentication/MultiAuthenticationExtensions.cs b/authentication/MultiAuthentication/MultiAuthenticationExtensions.cs index f6cf6d1..fd3a714 100644 --- a/authentication/MultiAuthentication/MultiAuthenticationExtensions.cs +++ b/authentication/MultiAuthentication/MultiAuthenticationExtensions.cs @@ -29,20 +29,21 @@ public static void AddAuthenticationWithSchemeSelector(this IServiceCollection s }); - source.Configure("ApiKey", options => options.ForwardDefaultSelector = (context) => - { - if (context.Request.Headers.ContainsKey("X-ORGANIZATION-ID")) - { - return "OrganizationId"; - } - - if (context.Request.Headers.ContainsKey("Authorization")) + source.Configure("ApiKey", options => + options.ForwardDefaultSelector = context => { - return "BearerToken"; - } - - return "ApiKey"; - }); + if (context.Request.Headers.ContainsKey("X-ORGANIZATION-ID")) + { + return "OrganizationId"; + } + + if (context.Request.Headers.ContainsKey("Authorization")) + { + return "BearerToken"; + } + + return "ApiKey"; + }); source.AddOptions(); source.AddAuthorization(); diff --git a/authentication/README.md b/authentication/README.md index a6bc914..3383918 100644 --- a/authentication/README.md +++ b/authentication/README.md @@ -1,2 +1,122 @@ # Authentication +## Multi Authentication + +`MultiAuthentication` is a sample project to demonstrate how to use +`Authentication` and `Authorization` features implemented by `.net` to achive +a mechanism for providing authentication for single endpoint from multiple +schemes. + +### Using `Authorize` attribute with multiple scheme values + +First option is to set _AuthenticationSchemes_ value of `Authorize` attribute +and register multiple schemes with `AuthenticationBuilder`. + +```csharp +//Program.cs + +builder.Services. + .AddAuthentication() + .AddScheme("SchemeOne", options => { }) + .AddScheme("SchemeTwo", options => { }); +``` + +```csharp +//Action in controller + +[HttpGet] +[Authorize(AuthenticationSchemes = "ShemeOne,SchemeTwo")] +public void Action() +{ + ... +} +``` + +> [!NOTE] +> +> The a request is made to the endpoint, will be handled by all two named schemes +> and the result of each handler will be combined in final result. + +> [!NOTE] +> +> Authorize attribute with no specific scheme will forward request to default +> scheme. When multiple schemes are added, default authentication scheme cannot +> be determined, so default scheme should be set explicitly + +### Building `Policy` with multiple authentication schemes + +Another options is to set _Policy_ value of `Authorize` attribute and add an +`AuthorizationPolicy` with multiple schemes. + +```csharp +source.AddAuthorization(options => +{ + ... + + var policyBuilder = new AuthorizationPolicyBuilder( + "SchemeOne", + "SchemeTwo" + ).RequireAuthenticatedUser(); + + options.AddPolicy("PolicyWithMultiSchemes", policyBuilder.Build()); +}); +``` + +```csharp +//Action in controller + +[HttpGet] +[Authorize(Policy = "PolicyWithMultiSchemes")] +public void Action() +{ + ... +} +``` + +> [!NOTE] +> +> The a request is made to the endpoint, will be handled by all two named schemes +> and the result of each handler will be combined in final result. + +> [!NOTE] +> +> If the policy is not added as default policy, when `Authorize` attribute +> is used without a specific policy, an exception will be thrown which will +> state a default policy should be set. + +### Configuring `ForwardSelector` of `AuthenticationSchemeOptions` + +Third option which is sort of a work around is to set `ForwardSelector` +property of `AuthenticationSchemeOptions` for all handlers, and selector will +forward the request accordingly to each handlers. + +This option requiers a default scheme and handler to be set when configuring +authentication and options to be configured for default handler. + +```csharp +source.AddAuthentication(options => +{ + options.DefaultScheme = "Default"; + options.DefaultAuthenticateScheme = "Default"; + options.AddScheme("Default", "Default"); + //Add other schemes +}); + +source.Configure("Default", options => + options.ForwardDefaultSelector = context => + { + if (...) + { + return "SchemeOne"; + } + + if (...) + { + return "SchemeTwo"; + } + + return "Default"; + }); + +source.AddOptions(); +``` \ No newline at end of file