I have an IdentityServer, and a couple of other OpenID Connect providers. When I connect my ASP.Net Core application to my IdentityServer, I include this code in my Startup.ConfigureServices method:
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;
});
So far, so standard. The problem is that my application will be running on several different URLs. For example, I can have an instance running under https://foo.example.com, and another one under https://bar.example.com . For each of these, I want to use a different client. So I started with adding another OIDC registration in my ConfigureServices method:
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;
});
I am having trouble with finding out how to have my ASP.Net Core application decide which OIDC registration to use based on what URL the application is running on. How do I do this?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Figured it out myself. There’s an interface called IAuthenticationSchemeProvider that you can overwrite. My code is as below. GetRequestSchemeAsync() is what does most of the work. This code assumes your OIDC registrations are the same name as the subdomain. So with subdomain foo, you need a registration 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();
}
After this, add it to the ConfigureServices method.
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton<IAuthenticationSchemeProvider, SubdomainAuthenticationSchemeProvider>();
Method 2
One issue is that you need set different callback paths for each OpenIDConnect entry. This is the unique URL that each one is listening on, for the incoming requests form IdentityServer.
Like this example:
.AddOpenIdConnect(options =>
{
//...
options.CallbackPath = "/app1-signin-oidc";
}
.AddOpenIdConnect(options =>
{
//...
options.CallbackPath = "/app2-signin-oidc";
}
The three paths that you need to configure are the following (defined in the OpenIdConnectOptions class)
public OpenIdConnectOptions()
{
CallbackPath = new PathString("/signin-oidc");
SignedOutCallbackPath = new PathString("/signout-callback-oidc");
RemoteSignOutPath = new PathString("/signout-oidc");
When a user clicks on the “sign-in” button, you can select what sign-in scheme to use, like this:
HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user, authProperties);
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0