【问题标题】:How to use SimpleProvider with my own MSAL C# code如何将 SimpleProvider 与我自己的 MSAL C# 代码一起使用
【发布时间】:2021-03-25 20:13:25
【问题描述】:

我正在尝试使用我自己的 MSAL 代码来协同工作。使用 .NET Core 5 MVC 开发。 我在下面的链接中发现了类似的问题。但我只是不知道如何使它与建议的答案一起工作。或者换句话说,我仍然对这种集成是如何完成的感到困惑。

[必须使用登录组件才能使用其他组件]It is mandatory to use the login component in order to use the other components

[MSAL JS 快速入门]https://github.com/microsoftgraph/microsoft-graph-toolkit/blob/main/samples/examples/simple-provider.html

我也读过以下文章: 【简单提供者示例】https://github.com/microsoftgraph/microsoft-graph-toolkit/blob/main/samples/examples/simple-provider.html

[微软图形工具包第 7 天一圈]https://developer.microsoft.com/en-us/office/blogs/a-lap-around-microsoft-graph-toolkit-day-7-microsoft-graph-toolkit-providers/

有没有人可以指点我更多关于如何存档的详细说明。

有人可以在下面进一步解释吗?怎么做。我应该在哪里放置代码以及如何将 AccessToken 返回给 SimpleProvider?

已编辑:

更新我的问题,使其更准确地表达除问题之外的我想要的内容。下面是我在 Startup.cs 中使用的代码,用于在用户使用 Web 应用程序时自动触发弹出屏幕。使用提供的示例时,始终无法获取接收到的访问令牌或用户 ID 数据。 问题 2:如何将接收到的令牌保存或存储在内存或缓存或 cookie 中以供 ProxyController 及其类以后使用。

//_layouts.aspx下的登录链接
<a class="nav-link" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignIn">Sign in</a>

// Use OpenId authentication in Startup.cs
        services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        // Specify this is a web app and needs auth code flow
        .AddMicrosoftIdentityWebApp(options =>
        {
            Configuration.Bind("AzureAd", options);

            options.Prompt = "select_account";
                            
            options.Events.OnTokenValidated = async context =>
            {
                var tokenAcquisition = context.HttpContext.RequestServices
                    .GetRequiredService<ITokenAcquisition>();

                var graphClient = new GraphServiceClient(
                    new DelegateAuthenticationProvider(async (request) =>
                    {
                        var token = await tokenAcquisition
                            .GetAccessTokenForUserAsync(GraphConstants.Scopes, user: context.Principal);
                        
                        request.Headers.Authorization =
                            new AuthenticationHeaderValue("Bearer", token);
                    })
                );

                // Get user information from Graph
                try
                {
                    var user = await graphClient.Me.Request()
                        .Select(u => new
                        {
                            u.DisplayName,
                            u.Mail,
                            u.UserPrincipalName,
                            u.MailboxSettings
                        })
                        .GetAsync();

                    context.Principal.AddUserGraphInfo(user);
                }
                catch (ServiceException)
                {
                }

                // Get the user's photo
                // If the user doesn't have a photo, this throws
                try
                {
                    var photo = await graphClient.Me
                        .Photos["48x48"]
                        .Content
                        .Request()
                        .GetAsync();

                    context.Principal.AddUserGraphPhoto(photo);
                }
                catch (ServiceException ex)
                {
                    if (ex.IsMatch("ErrorItemNotFound") ||
                        ex.IsMatch("ConsumerPhotoIsNotSupported"))
                    {
                        context.Principal.AddUserGraphPhoto(null);
                    }
                }
            };

            options.Events.OnAuthenticationFailed = context =>
            {
                var error = WebUtility.UrlEncode(context.Exception.Message);
                context.Response
                    .Redirect($"/Home/ErrorWithMessage?message=Authentication+error&debug={error}");
                context.HandleResponse();

                return Task.FromResult(0);
            };

            options.Events.OnRemoteFailure = context =>
            {
                if (context.Failure is OpenIdConnectProtocolException)
                {
                    var error = WebUtility.UrlEncode(context.Failure.Message);
                    context.Response
                        .Redirect($"/Home/ErrorWithMessage?message=Sign+in+error&debug={error}");
                    context.HandleResponse();
                }

                return Task.FromResult(0);
            };
        })
        // Add ability to call web API (Graph)
        // and get access tokens
        .EnableTokenAcquisitionToCallDownstreamApi(options =>
        {
            Configuration.Bind("AzureAd", options);
        }, GraphConstants.Scopes)
        // Add a GraphServiceClient via dependency injection
        .AddMicrosoftGraph(options =>
        {
            options.Scopes = string.Join(' ', GraphConstants.Scopes);
        })
        // Use in-memory token cache
        // See https://github.com/AzureAD/microsoft-identity-web/wiki/token-cache-serialization
        .AddInMemoryTokenCaches();

【问题讨论】:

    标签: microsoft-graph-api microsoft-graph-sdks microsoft-graph-toolkit


    【解决方案1】:

    由于您使用的是 MVC,我建议使用 ProxyProvider 而不是 Simple Provider。

    • SimpleProvider - 当您在客户端拥有现有身份验证(例如 Msal.js)时很有用
    • ProxyProvider - 当您在后端进行身份验证并且所有图形调用都从客户端代理到您的后端时很有用。

    This .NET core MVC sample 可能会有所帮助 - 它正在将 ProxyProvider 与组件一起使用

    【讨论】:

    • 我已设法更改“普通”租户以根据我的 Azure 配置指定租户 ID。下面是我编写的代码行: .WithAuthority(AzureCloudInstance.AzurePublic, AadAuthorityAudience.AzureAdMyOrg) .WithTenantId(azureOptions.TenantId)
    • 嗨@Nikola,我现在能够成功运行示例。问题:如何使用我自己的登录和注销按钮与示例合并?有什么我可以遵循的提示吗?
    • 我相信样本,你可以拨打mgt.Providers.globalProvider.login/logout做你想做的事。
    • 嗨@Nikola,我尝试了很多方法来获取访问令牌以传递给ProxyController,但没有成功。我已经更新了我的问题,以更准确地达到我试图归档的目标。你能在这方面进一步协助我吗?我已经阅读了很多关于客户凭证流和授权码流的相关文章和https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Acquiring-tokens-with-authorization-codes-on-web-apps
    • 我已经设法让它工作了。非常感谢您提供的示例链接,它为我提供了一些线索,让我了解如何选择 .NET 5 Core 开发的最佳方法。
    【解决方案2】:

    最后,我发现了如何为这两种技术做最后一英里的桥接。

    以下是我进行更改的代码行。由于我使用的是与MSAL.NET相反的新开发方法,所以很多实现都被简化了,所以很多例子或文章,可能并不能直接使用。

    除了使用上面@Nikola和我分享的链接,你也可以尝试在下面使用 https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/master/ 巩固成为您自己的解决方案。以下是我为使其正常工作所做的更改。

    Startup.cs 类的变化

    // Add application services. services.AddSingleton&lt;IGraphAuthProvider, GraphAuthProvider&gt;(); //services.AddSingleton&lt;IGraphServiceClientFactory, GraphServiceClientFactory&gt;();

    ProxyController.cs 类中的更改

    private readonly GraphServiceClient _graphClient; 
    
    public ProxyController(IWebHostEnvironment hostingEnvironment, GraphServiceClient graphclient)
        {
            _env = hostingEnvironment;
            //_graphServiceClientFactory = graphServiceClientFactory;
            _graphClient = graphclient;
        }
    

    ProxyController.cs 下 ProcessRequestAsync 方法的变化

     //var graphClient = _graphServiceClientFactory.GetAuthenticatedGraphClient((ClaimsIdentity)User.Identity);
           
            var qs = HttpContext.Request.QueryString;
            var url = $"{GetBaseUrlWithoutVersion(_graphClient)}/{all}{qs.ToUriComponent()}";
    
            var request = new BaseRequest(url, _graphClient, null)
            {
                Method = method,
                ContentType = HttpContext.Request.ContentType,
            };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多