首页 > 解决方案 > OIDC 关联在 MS Teams Blazor 应用程序中失败,但在浏览器中有效

问题描述

我正在为 MS Teams 编写 Blazor 应用程序(ASP.NET Core 3.1)。
在应用程序中,用户必须通过身份验证弹出窗口进行身份验证。
该应用程序通过 localhost 上的内部 IIS 托管,并通过 MS Teams 中的 ngrok 进行隧道传输。
在 Blazor 中有 Blazor 组件,它们通过Blazor Security@attribute [Authorize]中描述的标志保存。 该应用程序已在 Azure AD 门户中正确注册。 当我尝试通过托管在 MS Teams 中的应用程序中的 Azure AD 进行身份验证时,应用程序会读取用户凭据并将其发送到 Azure。我认为在重定向时会抛出错误。 调用如下所示:

An unhandled exception occurred while processing the request. Exception: Correlation failed. Unknown location Exception: An error was encountered while handling the remote login. Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<TOptions>.HandleRequestAsync()

https://login.microsoftonline.com/[tenantid]/oauth2/authorize?client_id=[clientId]&redirect_uri=https%3A%2F%2Flocalhost%3A44302%2Fsignin-oidc&response_type=id_token&scope=openid%20profile&response_mode=form_post&nonce=[nonce]&state=[state]&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.5.0.0

也没有创建cookie。
有趣的是在浏览器 (Chrome) 中,身份验证流程运行良好,并且 cookie 也被正确创建。Blazor AuthentificationStateProvider 也从弹出窗口中正确获取 UserState。
带有身份验证弹出窗口的我的登录页面:
function login() {
        $(".auth-data").hide();
        microsoftTeams.authentication.authenticate({
            url: window.location.origin + "/AzureAD/Account/SignIn",
            width: 600,
            height: 535,
            successCallback: function (result) {
                window.location.replace(window.location.origin + "/");
            },
            failureCallback: function (reason) {
                console.log("Login failed: " + reason);
                if (reason === "CancelledByUser" || reason === "FailedToOpenWindow") {
                    console.log("Login was blocked by popup blocker or canceled by user.");
                }
                // At this point we have to get the user involved, so show the login button
                $("#btnLogin").show();
                $(".auth-data").hide();
                $("#divError").text(reason).show();
            }
        });
    }

我的启动页面:

private void CheckSameSite(HttpContext httpContext, CookieOptions options)
    {
        if (options.SameSite == SameSiteMode.None)
        {
            var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
            // TODO: Use your User Agent library of choice here.
            if (userAgent.Contains("Chrome"))
            {
                options.SameSite = SameSiteMode.Unspecified;
            }
        }
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
            options.OnAppendCookie = cookieContext =>
                CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
            options.OnDeleteCookie = cookieContext =>
                CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
            options.HttpOnly = HttpOnlyPolicy.None;
            options.Secure = CookieSecurePolicy.Always;
        });

        services
            .AddAuthentication(AzureADDefaults.AuthenticationScheme)
            .AddAzureAD(options => Configuration.Bind("AzureAd", options));

        services.Configure<JwtBearerOptions>(
        AzureADDefaults.JwtBearerAuthenticationScheme, options =>
        {
            options.TokenValidationParameters.NameClaimType = "name";
        });

        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddBlazoredLocalStorage();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseCookiePolicy();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapBlazorHub();
            endpoints.MapFallbackToPage("/_Host");
        });
    }

如您所见,我使用了另一个堆栈溢出问题堆栈溢出中提到的方法, 这不适用于我的任务。
如果在我的 Startup 或其他地方配置错误,我可能需要帮助,因为通过 Teams 的身份验证仅通过浏览器对我不起作用。

标签: c#azure-active-directorymicrosoft-teamsblazor-server-side

解决方案


推荐阅读