Substantive.AspNetCore.Authentication.OpenIdConnect 9.17.18-build20260129r1
Substantive.AspNetCore.Authentication.OpenIdConnect is a reusable .NET library that provides
secure-by-default authentication building blocks for Razor Pages applications and API application.
It simplifies configuring:
- External OAuth / OpenID Connect identity providers (Google, GitHub, GitLab, LINE, Auth0, Okta, Keycloak, Azure AD, Azure AD B2C)
- Secure defaults (Authorization Code flow, PKCE, no token persistence)
- Strongly-typed options with validation and source-generated option validators
- API token validation using OpenIddict (OAuth 2.0 introspection)
Installation
1. Add configuration to the appsettings.json
Add the required authentication configuration to appsettings.json.
AuthenticationOpenIdConnectis used for interactive sign-in (Razor Pages / web apps)OpenIddictValidationis used for API token validation (recommended default for APIs)
{
// API applications typically DO NOT need interactive sign-in
// AuthenticationOpenIdConnect can be omitted unless the API also hosts UI endpoints
"OpenIddictValidation": {
"IssuerBaseAddress": "https://auth.example.com/",
"Audiences": "api",
"ClientId": "api-client",
"ClientSecret": "api-client-secret"
}
}
2. Load configuration and add dependencies to the program.cs
var builder = WebApplication.CreateBuilder(args);
// API-focused authentication using token validation
builder.Services
.AddApiAudienceAuthentication(options =>
builder.Configuration
.GetSection("OpenIddictValidation")
.Bind(options));
builder.Services.AddAuthorization();
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Usage
Sample 1: API Application (Token-based authentication)
This is the recommended setup for API-only applications. The API validates access tokens issued by an external authorization server using OpenIddict.
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddApiAudienceAuthentication(options =>
builder.Configuration
.GetSection("OpenIddictValidation")
.Bind(options));
builder.Services.AddAuthorization();
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Controller example
[ApiController]
[Route("api/[controller]")]
public sealed class ValuesController : ControllerBase
{
[HttpGet]
[Authorize]
public IActionResult Get()
=> Ok(new[] { "value1", "value2" });
}
Sample 2: Blazor Application (Interactive sign-in)
This setup is suitable for Blazor Server applications (or hybrid apps) that require interactive user sign-in using external identity providers.
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddAuthenticationOpenIdConnect(options =>
builder.Configuration
.GetSection("AuthenticationOpenIdConnect")
.Bind(options));
builder.Services.AddAuthorization();
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
Example configuration using presets
builder.Services.AddAuthenticationOpenIdConnect(options =>
{
options.AuthenticationOptions.DefaultScheme = "Cookies";
options.AuthenticationOptions.DefaultChallengeScheme = "Google";
// Interactive sign-in using Google
options.Google = OAuthPresets.Google();
// Optional: additional external providers
options.Providers =
[
OAuthPresets.GitHub(),
OAuthPresets.Okta("dev-123456.okta.com")
];
});
Advanced Sample: Combine OAuth presets with loaded configuration
In real-world applications, it is common to combine secure OAuth presets with configuration-bound secrets and environment-specific values. This approach provides:
- Secure, opinionated defaults from
OAuthPresets - Environment-specific values (
ClientId,ClientSecret, scopes) from configuration - Clean separation between what the provider is and how it is configured per environment
appsettings.json
{
"AuthenticationOpenIdConnect": {
"AuthenticationOptions": {
"DefaultScheme": "Cookies",
"DefaultChallengeScheme": "Google"
},
"Providers": {
"Google": {
"ClientId": "<google-client-id>",
"ClientSecret": "<google-client-secret>",
"Scope": [ "openid", "profile", "email" ]
},
"GitHub": {
"ClientId": "<github-client-id>",
"ClientSecret": "<github-client-secret>",
"Scope": [ "read:user", "user:email" ]
}
}
}
}
Program.cs
builder.Services.AddAuthenticationOpenIdConnect(options =>
{
// Bind shared authentication options
builder.Configuration
.GetSection("AuthenticationOpenIdConnect")
.Bind(options);
// Start from secure presets
var google = OAuthPresets.GoogleOAuth();
var gitHub = OAuthPresets.GitHub();
// Overlay environment-specific configuration
builder.Configuration
.GetSection("AuthenticationOpenIdConnect:Providers:Google")
.Bind(google.OAuthOptions);
builder.Configuration
.GetSection("AuthenticationOpenIdConnect:Providers:GitHub")
.Bind(gitHub.OAuthOptions);
options.Providers =
[
google,
gitHub
];
});
Why this pattern works well
- ✅ Presets define secure defaults (PKCE, callbacks, endpoints)
- ✅ Configuration controls secrets and scopes per environment
- ✅ No secrets are embedded in source code
- ✅ Easy to add/remove providers without rewriting logic
- ✅ Works cleanly with
ValidateOnStart
FAQs and Troubleshoots
Q: Why does the application fail on startup if a provider is misconfigured?
A: This library uses ValidateOnStart and explicit validation to ensure authentication
is correctly configured. Failing fast prevents insecure or partially configured
authentication from reaching production.
Q: Should I use AuthenticationOpenIdConnect in an API-only application?
A: No. API-only applications should use AddApiAudienceAuthentication with
OpenIddict token validation. AuthenticationOpenIdConnect is intended for
interactive sign-in scenarios such as Razor Pages or hybrid API + UI applications.
Q: Where should ClientId and ClientSecret values be stored?
A: Always store secrets in configuration sources such as environment variables, secret managers, or user-secrets. They are intentionally never included in presets or source code.
Showing the top 20 packages that depend on Substantive.AspNetCore.Authentication.OpenIdConnect.
| Packages | Downloads |
|---|---|
|
Substantive.Foundation.Backends
A metapackage contains all Substantive backend building blocks.
|
3 |
|
Substantive.Foundation.Backends
A metapackage contains all Substantive backend building blocks.
|
4 |
|
Substantive.Foundation.Backends
A metapackage contains all Substantive backend building blocks.
|
6 |
|
Substantive.Foundation.Backends
A metapackage contains all Substantive backend building blocks.
|
7 |
|
Substantive.Foundation.Backends
A metapackage contains all Substantive backend building blocks.
|
8 |
|
Substantive.Foundation.Backends
A metapackage contains all Substantive backend building blocks.
|
9 |
|
Substantive.Foundation.Backends
A metapackage contains all Substantive backend building blocks.
|
11 |
|
Substantive.Foundation.Backends
A metapackage contains all Substantive backend building blocks.
|
14 |
|
Substantive.Foundation.Backends
A metapackage contains all Substantive backend building blocks.
|
16 |
|
Substantive.Metapackage.AspNetCoreServer
A metapackage contains all Substantive ASP.NET Core server-side packages.
|
3 |
|
Substantive.Metapackage.Backends
A metapackage contains all Substantive backend building blocks.
|
3 |
.NET 10.0
- Microsoft.AspNetCore.Authentication.Facebook (>= 10.0.2)
- Microsoft.AspNetCore.Authentication.Google (>= 10.0.2)
- Microsoft.AspNetCore.Authentication.MicrosoftAccount (>= 10.0.2)
- Microsoft.AspNetCore.Authentication.Twitter (>= 10.0.2)
- OpenIddict.AspNetCore (>= 7.2.0)
- OpenIddict.Validation.AspNetCore (>= 7.2.0)
- OpenIddict.Validation.SystemNetHttp (>= 7.2.0)