From 5b9479b99954fc717083b3c3ceca3b9274f17a3e Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Sun, 5 Apr 2020 22:55:56 +0300 Subject: [PATCH] custom signin manager documentation update --- docs/en/How-To/Customize-SignIn-Manager.md | 93 ++++++++++++---------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/docs/en/How-To/Customize-SignIn-Manager.md b/docs/en/How-To/Customize-SignIn-Manager.md index 8c9733a6af..f8108c1910 100644 --- a/docs/en/How-To/Customize-SignIn-Manager.md +++ b/docs/en/How-To/Customize-SignIn-Manager.md @@ -1,84 +1,97 @@ -# Customize the SignInManager +# How to Customize the SignIn Manager for ABP Applications -## Introduction +After creating a new application using the [application startup template](../Startup-Templates/Application.md), you may want extend or change the default behavior of the SignIn Manager for your authentication and registration flow needs. ABP [Account Module](../Modules/Account) uses default [Microsoft Identity SignIn Manager](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs). To write your Custom SignIn Manager, you need to extend this class and register to the DI container. -ABP Framework uses Microsoft Identity underneath hence supports customization as much as Microsoft Identity does. +This document explains how to customize the SignIn Manager for your own application. -## Sample Code +## Create a CustomSignInManager -https://github.com/abpframework/abp-samples/blob/master/aspnet-core/BookStore-AzureAD/src/Acme.BookStore.Web/CustomSignInManager.cs +Create a new class inheriting the [SignInMager](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/SignInManager.cs) of Microsoft Identity package. -## Creating CustomSignInManager - -To create your own custom SignIn Manager, you need to inherit `SignInManager`. - -````xml -public class CustomSignInManager : SignInManager +````csharp +public class CustomSignInManager : Microsoft.AspNetCore.Identity.SignInManager { - public CustomSigninManager( - UserManager userManager, - IHttpContextAccessor contextAccessor, - IUserClaimsPrincipalFactory claimsFactory, - IOptions optionsAccessor, - ILogger> logger, - IAuthenticationSchemeProvider schemes, - IUserConfirmation confirmation) - : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation) - { - } + public CustomSignInManager( + Microsoft.AspNetCore.Identity.UserManager userManager, + Microsoft.AspNetCore.Http.IHttpContextAccessor contextAccessor, + Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory claimsFactory, + Microsoft.Extensions.Options.IOptions optionsAccessor, + Microsoft.Extensions.Logging.ILogger> logger, + Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider schemes, + Microsoft.AspNetCore.Identity.IUserConfirmation confirmation) + : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation) + { + } } ```` +> It is important to use **Volo.Abp.Identity.IdentityUser** type for SignInManager to inherit, not the AppUser of your application. + +Afterwards you can override any of the SignIn Manager methods you need and add new methods and properties needed for your authentication or registration flow. +## Overriding the GetExternalLoginInfoAsync Method -## Overriding Methods +In this case we'll be overriding the `GetExternalLoginInfoAsync` method which is invoked when a third party authentication is implemented. -Afterwards you can override a method like `GetExternalLoginInfoAsync`: +A good way to override a method is copying its [source code](https://github.com/dotnet/aspnetcore/blob/c56aa320c32ee5429d60647782c91d53ac765865/src/Identity/Core/src/SignInManager.cs#L638-L674). In this case, we will be using a minorly modified version of the source code which explicitly shows the namespaces of the methods and properties to help better understanding of the concept. -````xml -public override async Task GetExternalLoginInfoAsync(string expectedXsrf = null) +````csharp +public override async Task GetExternalLoginInfoAsync(string expectedXsrf = null) { - var auth = await Context.AuthenticateAsync(IdentityConstants.ExternalScheme); + var auth = await Context.AuthenticateAsync(Microsoft.AspNetCore.Identity.IdentityConstants.ExternalScheme); var items = auth?.Properties?.Items; - if (auth?.Principal == null || items == null || !items.ContainsKey("LoginProvider")) + if (auth?.Principal == null || items == null || !items.ContainsKey("LoginProviderKey")) { - return null; + return null; } if (expectedXsrf != null) { - if (!items.ContainsKey("XsrfId")) + if (!items.ContainsKey("XsrfKey")) { - return null; + return null; } var userId = items[XsrfKey] as string; if (userId != expectedXsrf) { - return null; + return null; + } } + var providerKey = auth.Principal.FindFirstValue(ClaimTypes.NameIdentifier); var provider = items[LoginProviderKey] as string; if (providerKey == null || provider == null) { - return null; + return null; } - var providerDisplayName = (await GetExternalAuthenticationSchemesAsync()).FirstOrDefault(p => p.Name == provider)?.DisplayName ?? provider; - return new ExternalLoginInfo(auth.Principal, provider, providerKey, providerDisplayName) + var providerDisplayName = (await GetExternalAuthenticationSchemesAsync()).FirstOrDefault(p => p.Name == provider)?.DisplayName + ?? provider; + return new Microsoft.AspNetCore.Identity.ExternalLoginInfo(auth.Principal, provider, providerKey, providerDisplayName) { - AuthenticationTokens = auth.Properties.GetTokens() + AuthenticationTokens = auth.Properties.GetTokens() }; } ```` +To get your overridden method invoked and your customized SignIn Manager class to work, you need to register your class to the [Dependency Injection System](../Dependency-Injection.md). +## Register to Dependency Injection -## Registering to DI +Registering `CustomSignInManager` should be done with adding **AddSignInManager** extension method of the [IdentityBuilderExtensions](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Core/src/IdentityBuilderExtensions.cs) of the [IdentityBuilder](https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Extensions.Core/src/IdentityBuilder.cs). -You need to register your Custom SignIn Manager to DI to activate it. Inside the `.Web` project, locate the `ApplicationNameWebModule` and add the following under `ConfigureServices` method: +Inside your `.Web` project, locate the `ApplicationNameWebModule` and add the following under `ConfigureServices` method to replace the old SignInManager with your customized one. -````xml +````csharp context.Services .GetObject() .AddSignInManager(); -```` \ No newline at end of file +```` + +## The Source Code + +You can find the source code of the completed example [here](https://github.com/abpframework/abp-samples/tree/master/aspnet-core/Authentication-Customization). + +## See Also + +* [How to Customize the Login Page for MVC / Razor Page Applications](Customize-Login-Page-MVC). \ No newline at end of file