在通过 oidc 和中间件使用 Azure AD 身份验证的 Web 应用程序中指定自定义 redirect_uri

Specify custom redirect_uri in a web app that uses Azure AD authentication with oidc and a middleware

我正在尝试使用 Azure AD 对应用程序进行身份验证。在 localhost 中一切正常,它重定向到 Azure AD,我在其中输入详细信息以进行身份​​验证,然后发回允许查看资源的令牌。 在 aspnetcore 3.1 应用程序中使用 Microsoft.AspNetCore.Authentication.AzureAD.UI 3.1.10 在幕后管理所有内容。

我的应用程序在 http://localhost:5000 上运行,我可以在 Azure AD 为该应用程序配置 redirectUri/replyUri 以支持此 url。一切顺利。

当我的应用程序在 Service Fabric 集群中运行时,问题出在不同的环境中。 我可以看到问题

AADSTS50011: The reply URL specified in the request does not match the reply URLs configured for the application

当我检查 url 时,我可以看到 redirect_uri 有一些像这样的 url http://12.12.12.12/signin-oidc

这里的问题是双重的。首先,我不知道集群将分配哪个 IP。其次,它是 http,而不是 https,Azure AD 不支持它。

幸运的是,我的应用程序有一个外部 Url,带有我可以用来访问的反向代理。像 https://myservicefabriccluster.com/MyApp

我可以在我的应用程序和 Azure AD 中将 Url 配置为我的 redirect_uri,但是 我不知道该怎么做

我的代码是这样的:

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

我在哪里绑定我的设置。

"AzureAd": {
  "Instance": "https://login.microsoftonline.com/",
  "ClientId": "76245c66-354e-4a94-b34d-...",
  "TenantId": "59c56bd4-ce18-466a-b515-..."
},

我可以看到 AzureADOptions 支持一些其他参数,例如 Domain(不需要)或 CallbackPath(默认情况下可以是 /signin-oidc)但是与 ReplyUrl 或 RedirectUri 完全不同,我可以在其中指定绝对 URL 作为回调。

我发现了几个没有答案的类似问题。其他人建议使用某种技巧,例如在重定向到 Azure AD 之前重写该参数的中间件。

当然,必须有一种更简单的方法来处理这个问题,我认为这并不奇怪。有什么帮助吗?

看看这个,你应该将 public URL 配置为重定向 URI,它的值如下:

看起来上面的库并没有轻易支持这个,并且强制重定向URI基于代码的HTTP监听URL。作为解决此问题的一部分,值得考虑如何编写代码:

这行代码表明您的应用仅限于使用 Azure AD:

- services.AddAzureAD

这行代码将确保您的代码适用于 AzureAD 和任何其他符合 Open Id Connect 标准的授权服务器:

- services.AddOpenIdConnect

后一个选项还有一个事件 class,带有常用的 OnRedirectToIdentityProvider 操作,您可以使用它来覆盖 CallbackPath 并提供完整的 RedirectUri。

Azure AD 端点是基于标准的,因此您不必严格使用 AzureAD 特定库。出于兴趣,我有一个 Single Page App Azure code sample 使用像这样的中性库,所以我知道这种技术有效。

用自定义值覆盖 redirect_uri 参数的解决方案是使用 OpenIdConnect 库中可用的事件。这个库应该可用,因为它是 Microsoft.AspNetCore.Authentication.AzureAD.UI 的依赖项,所以这是我的解决方案,除了 AzureADOptions 的标准属性外,它还添加了一个标志来确定是否必须覆盖重定向 uri 以及一个这样做的值.我希望它是不言自明的

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

var isCustomRedirectUriRequired = configuration.GetValue<bool>("AzureAd:IsCustomRedirectUriRequired");
if (isCustomRedirectUriRequired)
{
    services
        .Configure<OpenIdConnectOptions>(
            AzureADDefaults.OpenIdScheme,
            options =>
            {
                options.Events =
                    new OpenIdConnectEvents
                    {
                        OnRedirectToIdentityProvider = async ctx =>
                        {
                            ctx.ProtocolMessage.RedirectUri =
                                configuration.GetValue<string>("AzureAd:CustomRedirectUri");
                            await Task.Yield();
                        }
                    };
            });
}

services
    .AddAuthorization(
        options =>
        {
            options.AddPolicy(
                PolicyConstants.DashboardPolicy,
                builder =>
                {
                    builder
                        .AddAuthenticationSchemes(AzureADDefaults.AuthenticationScheme)
                        .RequireAuthenticatedUser();
                });
        });

appsettings.json 会是这样的:

"AzureAd": {
  "Instance": "https://login.microsoftonline.com/",
  "ClientId": "76245c66-354e-4a94-b34d-...",
  "TenantId": "59c56bd4-ce18-466a-b515-..."
  "IsCustomRedirectUriRequired": true,
  "CustomRedirectUri": "https://platform-cluster-development01.cubictelecom.com:19008/Scheduler/WebApi/signin-oidc"
},

请注意 IsCustomRedirectUriRequiredCustomRedirectUri 是我明确读取的自定义属性,以便在重定向到身份提供程序时覆盖(或不覆盖)重定向 uri 查询参数(即:Azure AD)