动态更改 asp.net 核心的授权方法质询方案
Dynamically change the authorization method challenge scheme for asp.net core
我有一个 IdentityServer 和其他几个 OpenID Connect 提供商。当我将我的 ASP.Net 核心应用程序连接到我的 IdentityServer 时,我将此代码包含在我的 Startup.ConfigureServices
方法中:
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "https://myIdentityServer";
options.ClientId = "myClientId";
options.ClientSecret = "myClientSecret";
options.ResponseType = "code";
options.UsePkce = true;
options.SaveTokens = true;
});
到目前为止,如此标准。问题是我的应用程序将在几个不同的 URL 上 运行。例如,我可以在 https://foo.example.com, and another one under https://bar.example.com 下有一个实例 运行 。对于其中的每一个,我都想使用不同的客户端。所以我开始在我的 ConfigureServices
方法中添加另一个 OIDC 注册:
services.AddAuthentication(...
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", ...)
.AddOpenIdConnect("anotherregistration", options =>
{
options.Authority = "https://myIdentityServer";
options.ClientId = "mySecondClientId";
options.ClientSecret = "anotherClientSecret";
options.ResponseType = "code";
options.UsePkce = true;
options.SaveTokens = true;
});
我无法找到如何让我的 ASP.Net 核心应用程序根据 URL 应用程序 运行 决定使用哪个 OIDC 注册。我该怎么做?
一个问题是您需要为每个 OpenIDConnect 条目设置不同的回调路径。对于来自 IdentityServer 的传入请求,这是每个人都在监听的唯一 URL。
像这个例子:
.AddOpenIdConnect(options =>
{
//...
options.CallbackPath = "/app1-signin-oidc";
}
.AddOpenIdConnect(options =>
{
//...
options.CallbackPath = "/app2-signin-oidc";
}
您需要配置的三个路径如下(定义在OpenIdConnectOptions class)
public OpenIdConnectOptions()
{
CallbackPath = new PathString("/signin-oidc");
SignedOutCallbackPath = new PathString("/signout-callback-oidc");
RemoteSignOutPath = new PathString("/signout-oidc");
当用户点击“sign-in”按钮时,您可以select使用什么sign-in方案,像这样:
HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user, authProperties);
我自己想出来了。有一个名为 IAuthenticationSchemeProvider
的接口,您可以覆盖它。我的代码如下。 GetRequestSchemeAsync()
是大部分工作的内容。此代码假定您的 OIDC 注册名称与子域相同。因此对于子域 foo
,您需要注册 AddOpenIdConnect("foo", ....)
public class SubdomainAuthenticationSchemeProvider : AuthenticationSchemeProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
public CustomAuthenticationSchemeProvider(
IHttpContextAccessor httpContextAccessor,
IOptions<AuthenticationOptions> options)
: base(options)
{
this._httpContextAccessor = httpContextAccessor;
}
private Task<AuthenticationScheme> GetRequestSchemeAsync()
{
// Get the subdomain for the host the request came from. Assumes no WWW in the string.
var subdomainName = _httpContextAccessor.HttpContext.Request.Host.Host.Split(new char[] { '.' })[0];
return GetSchemeAsync(subdomainName);
}
public override async Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync() => await GetRequestSchemeAsync() ;
public override async Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultChallengeSchemeAsync();
public override async Task<AuthenticationScheme> GetDefaultForbidSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultForbidSchemeAsync();
public override async Task<AuthenticationScheme> GetDefaultSignInSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultSignInSchemeAsync();
public override async Task<AuthenticationScheme> GetDefaultSignOutSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultSignOutSchemeAsync();
}
在此之后,将其添加到 ConfigureServices
方法中。
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IAuthenticationSchemeProvider, SubdomainAuthenticationSchemeProvider>();
我有一个 IdentityServer 和其他几个 OpenID Connect 提供商。当我将我的 ASP.Net 核心应用程序连接到我的 IdentityServer 时,我将此代码包含在我的 Startup.ConfigureServices
方法中:
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "https://myIdentityServer";
options.ClientId = "myClientId";
options.ClientSecret = "myClientSecret";
options.ResponseType = "code";
options.UsePkce = true;
options.SaveTokens = true;
});
到目前为止,如此标准。问题是我的应用程序将在几个不同的 URL 上 运行。例如,我可以在 https://foo.example.com, and another one under https://bar.example.com 下有一个实例 运行 。对于其中的每一个,我都想使用不同的客户端。所以我开始在我的 ConfigureServices
方法中添加另一个 OIDC 注册:
services.AddAuthentication(...
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", ...)
.AddOpenIdConnect("anotherregistration", options =>
{
options.Authority = "https://myIdentityServer";
options.ClientId = "mySecondClientId";
options.ClientSecret = "anotherClientSecret";
options.ResponseType = "code";
options.UsePkce = true;
options.SaveTokens = true;
});
我无法找到如何让我的 ASP.Net 核心应用程序根据 URL 应用程序 运行 决定使用哪个 OIDC 注册。我该怎么做?
一个问题是您需要为每个 OpenIDConnect 条目设置不同的回调路径。对于来自 IdentityServer 的传入请求,这是每个人都在监听的唯一 URL。
像这个例子:
.AddOpenIdConnect(options =>
{
//...
options.CallbackPath = "/app1-signin-oidc";
}
.AddOpenIdConnect(options =>
{
//...
options.CallbackPath = "/app2-signin-oidc";
}
您需要配置的三个路径如下(定义在OpenIdConnectOptions class)
public OpenIdConnectOptions()
{
CallbackPath = new PathString("/signin-oidc");
SignedOutCallbackPath = new PathString("/signout-callback-oidc");
RemoteSignOutPath = new PathString("/signout-oidc");
当用户点击“sign-in”按钮时,您可以select使用什么sign-in方案,像这样:
HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user, authProperties);
我自己想出来了。有一个名为 IAuthenticationSchemeProvider
的接口,您可以覆盖它。我的代码如下。 GetRequestSchemeAsync()
是大部分工作的内容。此代码假定您的 OIDC 注册名称与子域相同。因此对于子域 foo
,您需要注册 AddOpenIdConnect("foo", ....)
public class SubdomainAuthenticationSchemeProvider : AuthenticationSchemeProvider
{
private readonly IHttpContextAccessor _httpContextAccessor;
public CustomAuthenticationSchemeProvider(
IHttpContextAccessor httpContextAccessor,
IOptions<AuthenticationOptions> options)
: base(options)
{
this._httpContextAccessor = httpContextAccessor;
}
private Task<AuthenticationScheme> GetRequestSchemeAsync()
{
// Get the subdomain for the host the request came from. Assumes no WWW in the string.
var subdomainName = _httpContextAccessor.HttpContext.Request.Host.Host.Split(new char[] { '.' })[0];
return GetSchemeAsync(subdomainName);
}
public override async Task<AuthenticationScheme> GetDefaultAuthenticateSchemeAsync() => await GetRequestSchemeAsync() ;
public override async Task<AuthenticationScheme> GetDefaultChallengeSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultChallengeSchemeAsync();
public override async Task<AuthenticationScheme> GetDefaultForbidSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultForbidSchemeAsync();
public override async Task<AuthenticationScheme> GetDefaultSignInSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultSignInSchemeAsync();
public override async Task<AuthenticationScheme> GetDefaultSignOutSchemeAsync() =>
await GetRequestSchemeAsync() ??
await base.GetDefaultSignOutSchemeAsync();
}
在此之后,将其添加到 ConfigureServices
方法中。
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IAuthenticationSchemeProvider, SubdomainAuthenticationSchemeProvider>();