Open Closed

AzureAd Login with AddMicrosoftIdentityWebApi #5670


User avatar
0
Fabio.Zinesi created
  • ABP Framework version: v7.3.0
  • UI Type: Angular
  • Database System: EF Core (SQL Server, Oracle, MySQL, PostgreSQL, etc..)
  • **Tiered (for MVC)
  • Exception message and full stack trace:
  • Steps to reproduce the issue:

I am tring to add

 private void ConfigureExternalProviders(ServiceConfigurationContext context)
{
        context.Services.AddAuthentication()
            .AddMicrosoftIdentityWebApi( ..... )

but i cannot find the parameters for function. What are the right parameters?

After the login i have to make this kind of call:

var accessToken = await m_tokenAcquisition.GetAccessTokenForUserAsync(Configuration["AzureAd:Scopes:0"].Split(" "));

// Get username of logged in user
var userInfo = await m_graphServiceClient.Me.Request().GetAsync();
var userName = userInfo.DisplayName;

AuthDetails authDetails = new AuthDetails
{
    UserName = userName,
    AccessToken = accessToken
};

How can i do this?

Best Regards.


6 Answer(s)
  • User Avatar
    0
    Fabio.Zinesi created

    If i do this:

    private void ConfigureExternalProviders(ServiceConfigurationContext context)
    {
        var configuration = context.Services.GetConfiguration();
    
        context.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAd"));
        context.Services.AddMicrosoftIdentityWebApiAuthentication(configuration, "AzureAd");
    
    
        context.Services.AddControllersWithViews();
    
        context.Services.AddAuthentication()
    
            
            .AddJwtBearer("Default", options =>
            {
                options.Authority = configuration["AuthServer:Authority"];
                options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
                options.Audience = "DruidAI";
                options.Configuration = new OpenIdConnectConfiguration();
            })
    

    .....

    It works but do not login in ABP.

  • User Avatar
    0
    Anjali_Musmade created
    Support Team Support Team Member

    Hi,

    in the current ABP io Microsoft authentication implementation you can get access token of Microsoft identity provider like this

    add below line as showing in the image

                    options.SaveTokens = true;
    

    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Options;
    using Owl.reCAPTCHA;
    using System.Linq;
    using System.Threading.Tasks;
    using Volo.Abp.Account.ExternalProviders;
    using Volo.Abp.Account.Public.Web;
    using Volo.Abp.Account.Public.Web.Pages.Account;
    using Volo.Abp.Account.Security.Recaptcha;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.Security.Claims;
    
    namespace Acme.Penstore.Pages.Account
    {
        [ExposeServices(typeof(LoginModel))]
        [Dependency(ReplaceServices = true)]
        public class AppLoginModel : LoginModel
        {
            public AppLoginModel(IAuthenticationSchemeProvider schemeProvider, IOptions<AbpAccountOptions> accountOptions, IAbpRecaptchaValidatorFactory recaptchaValidatorFactory, IAccountExternalProviderAppService accountExternalProviderAppService, ICurrentPrincipalAccessor currentPrincipalAccessor, IOptions<IdentityOptions> identityOptions, IOptionsSnapshot<reCAPTCHAOptions> reCaptchaOptions) : base(schemeProvider, accountOptions, recaptchaValidatorFactory, accountExternalProviderAppService, currentPrincipalAccessor, identityOptions, reCaptchaOptions)
            {
            }
    
    
            public override async Task<IActionResult> OnGetExternalLoginCallbackAsync(string returnUrl = "", string returnUrlHash = "", string remoteError = null)
            {
                var token = await SignInManager.GetExternalLoginInfoAsync();
                var accessToken = token?.AuthenticationTokens?.FirstOrDefault(x => x.Name == "access_token");
    
                return await base.OnGetExternalLoginCallbackAsync(returnUrl, returnUrlHash, remoteError);
            }
        }
    }
    
    
    

    also add you Microsoft client id and client secret on the Account Settings here

  • User Avatar
    0
    Fabio.Zinesi created

    In witch file i have to add the code?


    using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Owl.reCAPTCHA; using System.Linq; using System.Threading.Tasks; using Volo.Abp.Account.ExternalProviders; using Volo.Abp.Account.Public.Web; using Volo.Abp.Account.Public.Web.Pages.Account; using Volo.Abp.Account.Security.Recaptcha; using Volo.Abp.DependencyInjection; using Volo.Abp.Security.Claims;

    namespace Acme.Penstore.Pages.Account { [ExposeServices(typeof(LoginModel))] [Dependency(ReplaceServices = true)] public class AppLoginModel : LoginModel { public AppLoginModel(IAuthenticationSchemeProvider schemeProvider, IOptions accountOptions, IAbpRecaptchaValidatorFactory recaptchaValidatorFactory, IAccountExternalProviderAppService accountExternalProviderAppService, ICurrentPrincipalAccessor currentPrincipalAccessor, IOptions identityOptions, IOptionsSnapshot reCaptchaOptions) : base(schemeProvider, accountOptions, recaptchaValidatorFactory, accountExternalProviderAppService, currentPrincipalAccessor, identityOptions, reCaptchaOptions) { }

        public override async Task OnGetExternalLoginCallbackAsync(string returnUrl = "", string returnUrlHash = "", string remoteError = null)
        {
            var token = await SignInManager.GetExternalLoginInfoAsync();
            var accessToken = token?.AuthenticationTokens?.FirstOrDefault(x => x.Name == "access_token");
    
            return await base.OnGetExternalLoginCallbackAsync(returnUrl, returnUrlHash, remoteError);
        }
    }
    

    }

  • User Avatar
    0
    Anjali_Musmade created
    Support Team Support Team Member

    Hi,

    You can create this file under HttpApi.Host project if you don't have auth server seperated.

    create following folder structure and place above code in Login.cshtml.cs

    if you have a project with AuthServer then please do above steps in that project

    Read more about overriding existing models and services https://docs.abp.io/en/abp/latest/UI/AspNetCore/Customization-User-Interface#example-2

  • User Avatar
    0
    Fabio.Zinesi created

    Hi Anialy,

    thank you very much for your support.

    Unfortunaly, for this project I have to use Microsoft.Identity.Web and Microsoft.Graph.

    Witch is the best way to add this authentication metod?

    Best Regards.

    Fabio.

  • User Avatar
    0
    Anjali_Musmade created
    Support Team Support Team Member

    Hi

    i found that Microsoft.Identity.Web doesn't work with await SignInManager.GetExternalLoginInfoAsync(); so that's why you are not able to proceed with login.

    I tried with <PackageReference Include="Microsoft.Graph" Version="5.25.0" />

    i am able get GraphServiceClient working

    by creating a IAccessTokenProvider implementation

    creaate a IntegratedAbpioTokenProvider like below in authservermodule

    using Microsoft.AspNetCore.Identity;
    using Microsoft.Kiota.Abstractions.Authentication;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace Acme.BookStore
    {
        public class IntegratedAbpioTokenProvider : IAccessTokenProvider
        {
            public IntegratedAbpioTokenProvider(SignInManager< Volo.Abp.Identity.IdentityUser > signInManager)
            {
                SignInManager = signInManager ?? throw new Exception();
            }
    
            public SignInManager< Volo.Abp.Identity.IdentityUser > SignInManager { get; set; }
    
            public AllowedHostsValidator AllowedHostsValidator { get; }
    
            public async Task< string > GetAuthorizationTokenAsync(Uri uri, Dictionary<string, object>? additionalAuthenticationContext = null, CancellationToken cancellationToken = default)
            {
                var token = await SignInManager.GetExternalLoginInfoAsync();
                var accessToken = token?.AuthenticationTokens?.FirstOrDefault(x => x.Name == "access_token");
                return accessToken?.Value ?? string.Empty;
            }
        }
    }
    
    

    and you can initialize GraphServiceClient like this

    if you still want to go with identity web please follow this github example

    https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/master/2-WebApp-graph-user/2-1-Call-MSGraph

    you just have to add following code

                   context.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
      .AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAd"), displayName: "Webapp")
             .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
             .AddMicrosoftGraph(configuration.GetSection("DownstreamApi"))
             .AddInMemoryTokenCaches();
    

    but after doing that you have to create a user inside OnGetExternalLoginCallbackAsync

    please see the full implementation of OnGetExternalLoginCallbackAsynchttps://github.com/abpframework/abp/blob/3fb86d658981748289ba8b6d5c59e857bc8c9e18/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs#L175 which you have to modify it based on Microsoft.Identity.Webresults.

    SigninManager docs on microsoft https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.signinmanager-1.getexternallogininfoasync?view=aspnetcore-7.0

Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11