同一回调路径上的ASP.NET Core OpenIdConnect和管理员同意



我已经用Azure实现了OpenIdConnect。代码大致如下:

var options = new OpenIdConnectOptions
{
SignInScheme = PersistentSchemeName,
CallbackPath = "/oauth2office2",
ClientId = pubConf.ApplicationId,
Authority = $"https://login.microsoftonline.com/{configuration.TenantId}"
};

它工作得很好。但我也需要管理员的同意,我不希望我的用户在我的应用程序中添加两个CallbackPaths。所以我手工制作了管理员同意url。并添加了重定向,这样它就不会与OpenId中间件发生冲突:

app.UseRewriter(new RewriteOptions().Add(context =>
{
var request = context.HttpContext.Request;
if (request.Path.StartsWithSegments("/oauth2office2") && request.Method == HttpMethods.Get)
{
request.Path = "/oauth2office";
}
}));

现在我在/oauth2office有一个控制器,它为我做一些额外的事情(实际上是获取租户id(。

问题-有没有一种方法可以用OpenIdConnect中间件实现它?同时仍在同一回调路径上。因为添加两条路径是我想要避免的额外操作。我甚至不确定我是否能让OpenIdConnect在管理员同意的情况下工作。

一个选项是添加两个具有不同架构名称和不同回调端点的AddOpenIDConnect(…(实例?

每个身份验证处理程序只能有一个端点。

此外,请注意,对openidconnect处理程序的回调请求是使用HTTPPOST完成的,如

POST/signin oidc HTTP/1.1

在您的代码中,您正在寻找一个GET

if (request.Path.StartsWithSegments("/oauth2office2") && request.Method == HttpMethods.Get)

这可以通过覆盖事件RedirectToIdentityProvider和MessageReceived,使用单个OpenIdConnect处理程序来完成。

public override async Task RedirectToIdentityProvider(RedirectContext context)
{
if (!context.Properties.Items.TryGetValue("AzureTenantId", out var azureTenantId))
azureTenantId = "organizations";
if (context.Properties.Items.TryGetValue("AdminConsent", out var adminConsent) && adminConsent == "true")
{
if (context.Properties.Items.TryGetValue("AdminConsentScope", out var scope))
context.ProtocolMessage.Scope = scope;
context.ProtocolMessage.IssuerAddress =
$"https://login.microsoftonline.com/{azureTenantId}/v2.0/adminconsent";
}
await base.RedirectToIdentityProvider(context);
}
public override async Task MessageReceived(MessageReceivedContext context)
{
// Handle admin consent endpoint response.
if (context.Properties.Items.TryGetValue("AdminConsent", out var adminConsent) && adminConsent == "true")
{
if (!context.ProtocolMessage.Parameters.ContainsKey("admin_consent"))
throw new InvalidOperationException("Expected admin_consent parameter");
var redirectUri = context.Properties.RedirectUri;
var parameters = context.ProtocolMessage.Parameters.ToQueryString();
redirectUri += redirectUri.IndexOf('?') == -1
? "?" + parameters
: "&" + parameters;
context.Response.Redirect(redirectUri);
context.HandleResponse();
return;
}
await base.MessageReceived(context);
}

然后,当你需要进行管理员同意时,用正确的属性进行挑战:

public IActionResult Register()
{
var redirectUrl = Url.Action("RegisterResponse");
var properties = new OpenIdConnectChallengeProperties
{
RedirectUri = redirectUrl,
Items =
{
{ "AdminConsent", "true" },
{ "AdminConsentScope", "https://graph.microsoft.com/.default" }
}
};
return Challenge(properties, "AzureAd");
}
public IActionResult RegisterResponse(
bool admin_consent,
string tenant,
string scope)
{
_logger.LogInformation("Admin Consent for tenant {tenant}: {admin_consent} {scope}", tenant, admin_consent,
scope);
return Ok();
}

最新更新