### Configure OpenIddict Client Services Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/getting-started/integrating-with-a-remote-server-instance.md Configure the OpenIddict client services in Program.cs or Startup.cs. This setup allows for client credentials flow and disables token storage for non-interactive flows. It also registers the System.Net.Http integration and adds a client registration with server-issued credentials. ```csharp services.AddOpenIddict() // Register the OpenIddict client components. .AddClient(options => { // Allow grant_type=client_credentials to be negotiated. options.AllowClientCredentialsFlow(); // Disable token storage, which is not necessary for non-interactive flows like // grant_type=password, grant_type=client_credentials or grant_type=refresh_token. options.DisableTokenStorage(); // Register the System.Net.Http integration. options.UseSystemNetHttp(); // Add a client registration with the client identifier and secrets issued by the server. options.AddRegistration(new OpenIddictClientRegistration { Issuer = new Uri("https://localhost:44385/", UriKind.Absolute), ClientId = "service-worker", ClientSecret = "388D45FA-B36B-4988-BA59-B187D329C207" }); }); ``` -------------------------------- ### Example Nested Userinfo Response Log Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/contributing-a-new-web-provider.md This log entry shows an example of a nested userinfo response from a provider, where user details are contained within a 'data' object. This format necessitates the use of the `UnwrapUserinfoResponse` handler. ```log OpenIddict.Client.OpenIddictClientDispatcher: Information: The userinfo response returned by https://contoso.com/users/me was successfully extracted: { "data": { "username": "odile.donat", "name": "Odile Donat", "email": "odile.donat@fabrikam.com" } }. ``` -------------------------------- ### Handle Authorization Request with Minimal API Source: https://github.com/openiddict/openiddict-documentation/blob/dev/introduction.md Implement a minimal API endpoint to handle authorization requests in pass-through mode. This example demonstrates authenticating with Steam, extracting claims, and creating a new principal for OpenIddict. ```csharp app.MapGet("/authorize", async (HttpContext context) => { // Resolve the claims stored in the principal created after the Steam authentication dance. // If the principal cannot be found, trigger a new challenge to redirect the user to Steam. var principal = (await context.AuthenticateAsync(SteamAuthenticationDefaults.AuthenticationScheme))?.Principal; if (principal is null) { return Results.Challenge(properties: null, [SteamAuthenticationDefaults.AuthenticationScheme]); } var identifier = principal.FindFirst(ClaimTypes.NameIdentifier)!.Value; // Create a new identity and import a few select claims from the Steam principal. var identity = new ClaimsIdentity(TokenValidationParameters.DefaultAuthenticationType); identity.AddClaim(new Claim(Claims.Subject, identifier)); identity.AddClaim(new Claim(Claims.Name, identifier).SetDestinations(Destinations.AccessToken)); return Results.SignIn(new ClaimsPrincipal(identity), properties: null, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); }); ``` -------------------------------- ### Initiate Interactive Authentication Flow Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/operating-systems.md Use `ChallengeInteractivelyAsync` and `AuthenticateInteractivelyAsync` to start and complete an interactive authentication process, typically involving the system browser. ```csharp try { // Ask OpenIddict to initiate the authentication // flow (typically, by starting the system browser). var result = await _service.ChallengeInteractivelyAsync(new() { ProviderName = provider }); // Wait for the user to complete the authorization process. var response = await _service.AuthenticateInteractivelyAsync(new() { Nonce = result.Nonce }); MessageBox.Show($"Welcome, {response.Principal.FindFirst(ClaimTypes.Name)!.Value}.", "Authentication successful", MessageBoxButton.OK, MessageBoxImage.Information); } catch (ProtocolException exception) when (exception.Error is Errors.AccessDenied) { MessageBox.Show("The authorization was denied by the end user.", "Authorization denied", MessageBoxButtons.OK, MessageBoxIcon.Warning); } ``` -------------------------------- ### Authorization Controller for Client Credentials Grant Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/getting-started/creating-your-own-server-instance.md Example implementation of an authorization controller to handle token requests for the client credentials grant type. ```csharp public class AuthorizationController : Controller { private readonly IOpenIddictApplicationManager _applicationManager; public AuthorizationController(IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; [HttpPost("~/connect/token"), Produces("application/json")] public async Task Exchange() { var request = HttpContext.GetOpenIddictServerRequest(); if (request.IsClientCredentialsGrantType()) { // Note: the client credentials are automatically validated by OpenIddict: // if client_id or client_secret are invalid, this action won't be invoked. var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ?? throw new InvalidOperationException("The application cannot be found."); // Create a new ClaimsIdentity containing the claims that // will be used to create an id_token, a token or a code. ``` -------------------------------- ### Configure OpenIddict Core Services Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/getting-started/integrating-with-a-remote-server-instance.md Register the core OpenIddict components and configure them to use Entity Framework Core stores. This setup is essential for OpenIddict's internal operations. ```csharp services.AddOpenIddict() // Register the OpenIddict core components. .AddCore(options => { // Configure OpenIddict to use the Entity Framework Core stores and models. // Note: call ReplaceDefaultEntities() to replace the default entities. options.UseEntityFrameworkCore() .UseDbContext(); }); ``` -------------------------------- ### Configure System.Net.Http Client with Custom Header Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/system-net-http.md Register a delegate to configure HttpClient instances used by OpenIddict client and validation integrations. This example adds a custom static header to all outgoing requests. ```csharp services.AddOpenIddict() .AddClient(options => { options.UseSystemNetHttp() .ConfigureHttpClient(client => client.DefaultRequestHeaders.Add("Custom-Header", "value")); }) .AddValidation(options => { options.UseSystemNetHttp() .ConfigureHttpClient(client => client.DefaultRequestHeaders.Add("Custom-Header", "value")); }); ``` -------------------------------- ### Set Product Information using Assembly Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/system-net-http.md Configure product information for the User-Agent header using a .NET Assembly reference in the System.Net.Http integration. ```csharp services.AddOpenIddict() .AddClient(options => { options.UseSystemNetHttp() .SetProductInformation(typeof(Program).Assembly); }) .AddValidation(options => { options.UseSystemNetHttp() .SetProductInformation(typeof(Program).Assembly); }); ``` -------------------------------- ### Implicit Flow Authorization Request Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/choosing-the-right-flow.md Example GET request for the implicit flow, requesting an access token directly. The `response_type=token` parameter is key for this flow. ```http GET /connect/authorize?response_type=token&client_id=s6BhdRkqt3&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb&scope=openid&state=af0ifjsldkj&nonce=n-0S6_WzA2Mj HTTP/1.1 Host: server.example.com ``` -------------------------------- ### Configure and Add Web Providers Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/contributing-a-new-web-provider.md Register web providers in your client application's configuration, typically in `Program.cs` or `Startup.cs`. Ensure unique redirection URIs for each provider to mitigate mix-up attacks. ```csharp // Register the Web providers integrations. // // Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint // URI per provider, unless all the registered providers support returning a special "iss" // parameter containing their URL as part of authorization responses. For more information, // see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4. options.UseWebProviders() // ... other providers... .Add[provider name](options => { options.SetClientId("[client identifier]"); options.SetClientSecret("[client secret]"); options.SetRedirectUri("callback/login/[provider name]"); // Note: depending on the provider, configuring other options MAY be required. }); ``` -------------------------------- ### Configure OpenIddict with Custom Key Type Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/entity-framework-core.md Configure OpenIddict to use a custom primary key type (e.g., Guid) for its entities. ```csharp services.AddOpenIddict() .AddCore(options => { // Configure OpenIddict to use the default entities with a custom key type. options.UseEntityFrameworkCore() .UseDbContext() .ReplaceDefaultEntities(); }); ``` -------------------------------- ### Set Product Information for System.Net.Http Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/system-net-http.md Configure product name and version for the User-Agent header in the System.Net.Http integration. ```csharp services.AddOpenIddict() .AddClient(options => { options.UseSystemNetHttp() .SetProductInformation("Contoso", "1.0.0"); }) .AddValidation(options => { options.UseSystemNetHttp() .SetProductInformation("Contoso", "1.0.0"); }); ``` -------------------------------- ### Add Quartz.NET Package Reference Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/quartz.md Reference the OpenIddict.Quartz package in your project file. ```xml ``` -------------------------------- ### Initiate Login with Specific GitHub Instance Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/web-providers.md Initiate the authentication flow for a specific GitHub instance (e.g., 'GitHub-Instance-A') by using the Challenge method with the provider name. Ensure the return URL is local to prevent open redirect attacks. ```csharp [HttpPost("~/login"), ValidateAntiForgeryToken] public async Task LogInWithGitHubInstanceA(string returnUrl) { var properties = new AuthenticationProperties { // Only allow local return URLs to prevent open redirect attacks. RedirectUri = Url.IsLocalUrl(returnUrl) ? returnUrl : "/" }; // Ask the OpenIddict client middleware to redirect the // user agent to GitHub using the "Instance A" settings. return Challenge(properties, "GitHub-Instance-A"); } ``` -------------------------------- ### Authorization Code Grant Request Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/choosing-the-right-flow.md Example of a POST request to the token endpoint using the authorization code grant type. Ensure all parameters are correctly encoded. ```http POST /connect/token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb&client_id=s6BhdRkqt3&client_secret=gX1fBat3bV&scope=openid ``` -------------------------------- ### Configure OpenIddict Client Services Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/getting-started/integrating-with-a-remote-server-instance.md Set up the OpenIddict client, enabling the authorization code flow, configuring encryption and signing certificates, and integrating with System.Net.Http and web providers like GitHub. ```csharp services.AddOpenIddict() // Register the OpenIddict client components. .AddClient(options => { // Note: this sample only uses the authorization code flow, // but you can enable the other flows if necessary. options.AllowAuthorizationCodeFlow(); // Register the signing and encryption credentials used to protect // sensitive data like the state tokens produced by OpenIddict. options.AddDevelopmentEncryptionCertificate() .AddDevelopmentSigningCertificate(); // Register the ASP.NET Core host and configure the ASP.NET Core-specific options. options.UseAspNetCore() .EnableRedirectionEndpointPassthrough(); // Register the System.Net.Http integration. options.UseSystemNetHttp(); // Register the Web providers integrations. // // Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint // URI per provider, unless all the registered providers support returning a special "iss" // parameter containing their URL as part of authorization responses. For more information, // see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4. options.UseWebProviders() .AddGitHub(options => { options.SetClientId("c4ade52327b01ddacff3") .SetClientSecret("da6bed851b75e317bf6b2cb67013679d9467c122") .SetRedirectUri("callback/login/github"); }); }); ``` -------------------------------- ### Enable System Integration in Client Options Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/operating-systems.md Call `UseSystemIntegration()` within the `AddClient` configuration to enable system integration. ```csharp services.AddOpenIddict() .AddClient(options => { // ... options.UseSystemIntegration(); }); ``` -------------------------------- ### Create MongoDB Indexes for OpenIddict Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/mongodb.md Initialize the MongoDB database and create necessary indexes for OpenIddict entities to improve performance. This script demonstrates index creation for applications, authorizations, scopes, and tokens. ```csharp using System.Threading; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using MongoDB.Driver; using OpenIddict.MongoDb; using OpenIddict.MongoDb.Models; var services = new ServiceCollection(); services.AddOpenIddict() .AddCore(options => options.UseMongoDb()); services.AddSingleton(new MongoClient("mongodb://localhost:27017").GetDatabase("openiddict")); var provider = services.BuildServiceProvider(); var context = provider.GetRequiredService(); var options = provider.GetRequiredService>().CurrentValue; var database = await context.GetDatabaseAsync(CancellationToken.None); var applications = database.GetCollection(options.ApplicationsCollectionName); await applications.Indexes.CreateManyAsync( [ new CreateIndexModel( Builders.IndexKeys.Ascending(application => application.ClientId), new CreateIndexOptions { Unique = true }), new CreateIndexModel( Builders.IndexKeys.Ascending(application => application.PostLogoutRedirectUris), new CreateIndexOptions { Background = true }), new CreateIndexModel( Builders.IndexKeys.Ascending(application => application.RedirectUris), new CreateIndexOptions { Background = true }) ]); var authorizations = database.GetCollection(options.AuthorizationsCollectionName); await authorizations.Indexes.CreateOneAsync( new CreateIndexModel( Builders.IndexKeys .Ascending(authorization => authorization.ApplicationId) .Ascending(authorization => authorization.Scopes) .Ascending(authorization => authorization.Status) .Ascending(authorization => authorization.Subject) .Ascending(authorization => authorization.Type), new CreateIndexOptions { Background = true })); var scopes = database.GetCollection(options.ScopesCollectionName); await scopes.Indexes.CreateOneAsync(new CreateIndexModel( Builders.IndexKeys.Ascending(scope => scope.Name), new CreateIndexOptions { Unique = true })); var tokens = database.GetCollection(options.TokensCollectionName); await tokens.Indexes.CreateManyAsync( [ new CreateIndexModel( Builders.IndexKeys.Ascending(token => token.ReferenceId), new CreateIndexOptions { // Note: partial filter expressions are not supported on Azure Cosmos DB. // As a workaround, the expression and the unique constraint can be removed. PartialFilterExpression = Builders.Filter.Exists(token => token.ReferenceId), Unique = true }), new CreateIndexModel( Builders.IndexKeys.Ascending(token => token.AuthorizationId), new CreateIndexOptions() { ``` -------------------------------- ### Configure Server with PKCE Support (XML) Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/contributing-a-new-web-provider.md Add a CodeChallengeMethod node under Configuration when the provider supports Proof Key for Code Exchange (PKCE). This ensures the OpenIddict client sends the necessary parameters for PKCE. ```xml ``` -------------------------------- ### Handle Authorization Requests in ASP.NET Core Minimal API Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/aspnet-core.md Example of handling authorization requests within an ASP.NET Core minimal API endpoint when pass-through mode is enabled. It includes logic for authenticating users, creating claims-based identities, and generating tokens. ```csharp app.MapMethods("authorize", [HttpMethods.Get, HttpMethods.Post], async (HttpContext context) => { // Resolve the claims stored in the cookie created after the GitHub authentication dance. // If the principal cannot be found, trigger a new challenge to redirect the user to GitHub. // // For scenarios where the default authentication handler configured in the ASP.NET Core // authentication options shouldn't be used, a specific scheme can be specified here. var principal = (await context.AuthenticateAsync())?.Principal; if (principal is null) { var properties = new AuthenticationProperties { RedirectUri = context.Request.GetEncodedUrl() }; return Results.Challenge(properties, [Providers.GitHub]); } var identifier = principal.FindFirst(ClaimTypes.NameIdentifier)!.Value; // Create the claims-based identity that will be used by OpenIddict to generate tokens. var identity = new ClaimsIdentity( authenticationType: TokenValidationParameters.DefaultAuthenticationType, nameType: Claims.Name, roleType: Claims.Role); // Import a few select claims from the identity stored in the local cookie. identity.AddClaim(new Claim(Claims.Subject, identifier)); identity.AddClaim(new Claim(Claims.Name, identifier).SetDestinations(Destinations.AccessToken)); identity.AddClaim(new Claim(Claims.PreferredUsername, identifier).SetDestinations(Destinations.AccessToken)); return Results.SignIn(new ClaimsPrincipal(identity), properties: null, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); }); ``` -------------------------------- ### Add OpenIddict Client System Integration Package Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/operating-systems.md Reference the OpenIddict.Client.SystemIntegration package in your project file. ```xml ``` -------------------------------- ### Configure OpenIddict to Use Quartz.NET Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/quartz.md Configure OpenIddict's core services to utilize the Quartz.NET integration for background tasks. ```csharp services.AddOpenIddict() .AddCore(options => { options.UseQuartz(); }); ``` -------------------------------- ### Add OpenIddict Packages to .csproj Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/getting-started/creating-your-own-server-instance.md Reference the necessary OpenIddict packages in your project file to enable server functionality. ```xml ``` -------------------------------- ### Initiate Interactive Authentication with GitHub in WPF Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/web-providers.md Use `OpenIddictClientService` to initiate and authenticate the user interactively with GitHub in a WPF application. This involves challenging the user and then authenticating the interactive flow. Includes handling for operation cancellation and timeouts. ```csharp public partial class MainWindow : Window, IWpfShell { private readonly OpenIddictClientService _service; public MainWindow(OpenIddictClientService service) { _service = service ?? throw new ArgumentNullException(nameof(service)); InitializeComponent(); } private async void LoginButton_Click(object sender, RoutedEventArgs e) { // Disable the login button to prevent concurrent authentication operations. LoginButton.IsEnabled = false; try { using var source = new CancellationTokenSource(delay: TimeSpan.FromSeconds(90)); try { // Ask OpenIddict to initiate the authentication flow (typically, by starting the system browser). var result = await _service.ChallengeInteractivelyAsync(new() { CancellationToken = source.Token, ProviderName = OpenIddictClientWebIntegrationConstants.Providers.GitHub }); // Wait for the user to complete the authorization process. var principal = (await _service.AuthenticateInteractivelyAsync(new() { CancellationToken = source.Token, Nonce = result.Nonce })).Principal; MessageBox.Show($"Welcome, {principal.FindFirst(ClaimTypes.Name)!.Value}.", ``` -------------------------------- ### Configure Multitenant Provider with Dynamic URIs (XML) Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/contributing-a-new-web-provider.md Use a Setting node to store tenant-specific information for multitenant providers. URIs can then include placeholders like {settings.Tenant} which OpenIddict will resolve at runtime. ```xml ``` -------------------------------- ### Enable Web Providers in Client Options Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/web-providers.md Call `UseWebProviders()` within the OpenIddict client configuration to enable web provider integrations. ```csharp services.AddOpenIddict() .AddClient(options => { // ... // Register the Web providers integrations. options.UseWebProviders(); }); ``` -------------------------------- ### Configure System.Net.Http Client with Registration Context Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/system-net-http.md Configure the HttpClient using a delegate that receives both the OpenIddict client registration and the HttpClient instance. This enables conditional configuration based on registration details, like the RegistrationId. ```csharp services.AddOpenIddict() .AddClient(options => { options.UseSystemNetHttp() .ConfigureHttpClient((registration, client) => { if (registration.RegistrationId is "447fbedf-dcec-47b0-9355-6e199e8f2576") { client.DefaultRequestHeaders.Add("Custom-Header", "value"); } }); }); ``` -------------------------------- ### Enable Reference Access and Refresh Tokens Source: https://github.com/openiddict/openiddict-documentation/blob/dev/configuration/token-storage.md Use this to enable reference access and refresh tokens in server options. This is recommended when dealing with token size limits or preferring shorter tokens. ```csharp services.AddOpenIddict() .AddServer(options => { options.UseReferenceAccessTokens() .UseReferenceRefreshTokens(); }); ``` -------------------------------- ### Register Quartz.NET Services Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/quartz.md Register Quartz.NET services and configure dependency injection with an in-memory store. ```csharp services.AddQuartz(options => { options.UseMicrosoftDependencyInjectionJobFactory(); options.UseSimpleTypeLoader(); options.UseInMemoryStore(); }) ``` -------------------------------- ### Configure Local OpenIddict Validation Services Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/getting-started/implementing-token-validation-in-your-apis.md Use `options.UseLocalServer()` to import configuration from a local OpenIddict server instance, including keys. This is suitable when APIs and the server are in the same project. ```csharp services.AddOpenIddict() // Register the OpenIddict validation components. .AddValidation(options => { // Import the configuration from the local OpenIddict server instance. options.UseLocalServer(); // Register the ASP.NET Core host. options.UseAspNetCore(); }); ``` -------------------------------- ### Configure Entity Framework Core and OpenIddict Core Services Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/getting-started/creating-your-own-server-instance.md Register your Entity Framework Core database context and configure OpenIddict core services in Program.cs. ```csharp services.AddDbContext(options => { // Configure Entity Framework Core to use Microsoft SQL Server. options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")); // Register the entity sets needed by OpenIddict. // Note: use the generic overload if you need to replace the default OpenIddict entities. options.UseOpenIddict(); }); services.AddOpenIddict() // Register the OpenIddict core components. .AddCore(options => { // Configure OpenIddict to use the Entity Framework Core stores and models. // Note: call ReplaceDefaultEntities() to replace the default entities. options.UseEntityFrameworkCore() .UseDbContext(); }); ``` -------------------------------- ### Add OpenIddict Client Package Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/getting-started/integrating-with-a-remote-server-instance.md Reference the latest OpenIddict package in your .csproj file to enable client functionalities. ```xml ``` -------------------------------- ### Configure Local Server Integration Source: https://github.com/openiddict/openiddict-documentation/blob/dev/configuration/encryption-and-signing-credentials.md Use this when the API and authorization server reside in the same project to automatically import credentials. ```csharp services.AddOpenIddict() .AddValidation(options => { options.UseLocalServer(); }); ``` -------------------------------- ### Add OpenIddict Client Web Integration Package Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/web-providers.md Reference the OpenIddict.Client.WebIntegration package in your project file. ```xml ``` -------------------------------- ### Configure OpenID Connect Discovery Source: https://github.com/openiddict/openiddict-documentation/blob/dev/configuration/encryption-and-signing-credentials.md Use this for cross-application validation with asymmetric signing keys. Requires the OpenIddict.Validation.SystemNetHttp package and calling UseSystemNetHttp(). ```csharp services.AddOpenIddict() .AddValidation(options => { options.SetIssuer("https://localhost:44319/"); options.UseSystemNetHttp(); }); ``` -------------------------------- ### Add System.Net.Http Packages Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/system-net-http.md Reference the necessary OpenIddict System.Net.Http packages for client and/or validation features. ```xml ``` -------------------------------- ### Configure System.Net.Http Integration Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/system-net-http.md Enable the System.Net.Http integration for OpenIddict client and validation features in your services. ```csharp services.AddOpenIddict() .AddClient(options => { options.UseSystemNetHttp(); }) .AddValidation(options => { options.UseSystemNetHttp(); }); ``` -------------------------------- ### Configure HttpClientHandler with Registration Context for OpenIddict Client Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/system-net-http.md Use an Action delegate for advanced HttpClientHandler configuration within the OpenIddict client integration. This allows conditional customization based on the client registration details, such as its ID. ```csharp services.AddOpenIddict() .AddClient(options => { options.UseSystemNetHttp() .ConfigureHttpClientHandler((registration, handler) => { if (registration.RegistrationId is "447fbedf-dcec-47b0-9355-6e199e8f2576") { handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; } }); }); ``` -------------------------------- ### Configure GitHub and Twitter Providers Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/web-providers.md Add specific provider instances like GitHub and Twitter to the client options, configuring their client ID, secret, and redirect URI. It's recommended to use a unique redirection endpoint URI per provider to mitigate mix-up attacks. ```csharp services.AddOpenIddict() .AddClient(options => { // Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint // URI per provider, unless all the registered providers support returning a special "iss" // parameter containing their URL as part of authorization responses. For more information, // see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4. options.UseWebProviders() .AddGitHub(options => { options.SetClientId("[client identifier]") .SetClientSecret("[client secret]") .SetRedirectUri("callback/login/github"); }) .AddTwitter(options => { options.SetClientId("[client identifier]") .SetClientSecret("[client secret]") .SetRedirectUri("callback/login/twitter"); }); }); ``` -------------------------------- ### Configure OpenIddict to Use EF 6.x Stores Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/entity-framework.md Configure OpenIddict services to use Entity Framework 6.x stores with the specified DbContext. ```csharp services.AddOpenIddict() .AddCore(options => { options.UseEntityFramework() .UseDbContext(); }); ``` -------------------------------- ### Configure OpenIddict stacks Source: https://github.com/openiddict/openiddict-documentation/blob/dev/introduction.md Register the core, client, server, and validation stacks within the service collection. ```csharp services.AddOpenIddict() .AddCore(options => { // ... }) .AddClient(options => { // ... }) .AddServer(options => { // ... }) .AddValidation(options => { // ... }); ``` -------------------------------- ### Attach a certificate to the client application Source: https://github.com/openiddict/openiddict-documentation/blob/dev/configuration/mutual-tls-authentication.md Configures an OpenIddictApplicationDescriptor with a JsonWebKeySet containing the public part of the authentication certificate. ```csharp var descriptor = new OpenIddictApplicationDescriptor { ApplicationType = ApplicationTypes.Web, ClientId = "mvc", ClientType = ClientTypes.Confidential, DisplayName = "MVC client application", JsonWebKeySet = new JsonWebKeySet { Keys = { // This application authenticates by using a self-signed client authentication // certificate during the TLS handshake. While the client needs access to the // private key, the server only needs to know the public part - included by the // ExportCertificatePem() API - to be able to validate the certificates it receives. JsonWebKeyConverter.ConvertFromX509SecurityKey(new X509SecurityKey( X509Certificate2.CreateFromPem("[PEM-encoded certificate exported via ExportCertificatePem()]"))) } }, RedirectUris = { new Uri("https://localhost:44381/callback/login/local") }, PostLogoutRedirectUris = { new Uri("https://localhost:44381/callback/logout/local") }, Permissions = { Permissions.Endpoints.Authorization, Permissions.Endpoints.EndSession, Permissions.Endpoints.PushedAuthorization, Permissions.Endpoints.Token, Permissions.GrantTypes.AuthorizationCode, Permissions.GrantTypes.RefreshToken, Permissions.ResponseTypes.Code, Permissions.Scopes.Email, Permissions.Scopes.Profile, Permissions.Scopes.Roles }, Requirements = { Requirements.Features.ProofKeyForCodeExchange, Requirements.Features.PushedAuthorizationRequests } }; await manager.CreateAsync(descriptor); ``` -------------------------------- ### Enable Activation Handling and Redirection Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/operating-systems.md Explicitly enables protocol activation handling and redirection on platforms where it's not default. Ensure the selected interaction method supports these features. ```csharp services.AddOpenIddict() .AddClient(options => { options.UseSystemIntegration() .EnableActivationHandling() .EnableActivationRedirection(); }); ``` -------------------------------- ### Add Entity Framework 6.x Package Reference Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/entity-framework.md Reference the OpenIddict.EntityFramework package to enable EF 6.x integration. ```xml ``` -------------------------------- ### Use System Integration and System Browser Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/operating-systems.md Forces OpenIddict to use the system integration and system browser for client interactions. This is an alternative to the default method. ```csharp services.AddOpenIddict() .AddClient(options => { options.UseSystemIntegration() .UseSystemBrowser(); }); ``` -------------------------------- ### Register Quartz.NET Hosted Service Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/quartz.md Register the Quartz.NET hosted service and configure it to wait for jobs to complete during shutdown. ```csharp services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true); ``` -------------------------------- ### Configure Client Registration with Custom Redirect URIs Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/operating-systems.md Configure client registrations with specific `RedirectUri` and `PostLogoutRedirectUri` for custom URI schemes, essential for mobile platforms. ```csharp services.AddOpenIddict() .AddClient(options => { // ... options.AddRegistration(new OpenIddictClientRegistration { Issuer = new Uri("https://localhost:44395/", UriKind.Absolute), ProviderName = "Local", ClientId = "maui", // This sample uses protocol activations with a custom URI scheme to handle callbacks. // // For more information on how to construct private-use URI schemes, // read https://www.rfc-editor.org/rfc/rfc8252#section-7.1 and // https://www.rfc-editor.org/rfc/rfc7595#section-3.8. PostLogoutRedirectUri = new Uri("com.openiddict.sandbox.maui.client:/callback/logout/local", UriKind.Absolute), RedirectUri = new Uri("com.openiddict.sandbox.maui.client:/callback/login/local", UriKind.Absolute), Scopes = { Scopes.Email, Scopes.Profile, Scopes.OfflineAccess, "demo_api" } }); // Register the Web providers integrations. // // Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint // address per provider, unless all the registered providers support returning an "iss" // parameter containing their URL as part of authorization responses. For more information, // see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4. options.UseWebProviders() .AddTwitter(options => { options.SetClientId("bXgwc0U3N3A3YWNuaWVsdlRmRWE6MTpjaQ") // Note: Twitter doesn't support the recommended ":/" syntax and requires using "://". .SetRedirectUri("com.openiddict.sandbox.maui.client://callback/login/twitter"); }); }); ``` -------------------------------- ### Handle Authorization Requests in MVC Controller or Minimal API Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/owin.md Once pass-through mode is enabled, this code demonstrates how to handle authorization requests. It includes logic for authenticating the user, potentially redirecting to an external provider like GitHub, and creating a claims-based identity for OpenIddict. ```csharp app.MapMethods("authorize", [HttpMethods.Get, HttpMethods.Post], async (HttpContext context) => { // Resolve the claims stored in the cookie created after the GitHub authentication dance. // If the principal cannot be found, trigger a new challenge to redirect the user to GitHub. // // For scenarios where the default authentication handler configured in the ASP.NET Core // authentication options shouldn't be used, a specific scheme can be specified here. var principal = (await context.AuthenticateAsync())?.Principal; if (principal is null) { var properties = new AuthenticationProperties { RedirectUri = context.Request.GetEncodedUrl() }; return Results.Challenge(properties, [Providers.GitHub]); } var identifier = principal.FindFirst(ClaimTypes.NameIdentifier)!.Value; // Create the claims-based identity that will be used by OpenIddict to generate tokens. var identity = new ClaimsIdentity( authenticationType: TokenValidationParameters.DefaultAuthenticationType, nameType: Claims.Name, roleType: Claims.Role); // Import a few select claims from the identity stored in the local cookie. identity.AddClaim(new Claim(Claims.Subject, identifier)); identity.AddClaim(new Claim(Claims.Name, identifier).SetDestinations(Destinations.AccessToken)); identity.AddClaim(new Claim(Claims.PreferredUsername, identifier).SetDestinations(Destinations.AccessToken)); return Results.SignIn(new ClaimsPrincipal(identity), properties: null, OpenIddictServerOwinDefaults.AuthenticationScheme); }); ``` -------------------------------- ### Add OpenIddict OWIN Packages Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/owin.md Reference the necessary OpenIddict OWIN packages for client, server, or validation features in your project. ```xml ``` -------------------------------- ### Add OpenIddict Entity Framework Core Package Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/entity-framework-core.md Reference the OpenIddict.EntityFrameworkCore package to enable EF Core integration. ```xml ``` -------------------------------- ### Register Inline Event Handler for Server Configuration Source: https://github.com/openiddict/openiddict-documentation/blob/dev/introduction.md This C# code demonstrates how to register an inline event handler for the server configuration context using dependency injection. It shows how to attach custom metadata to the configuration document. This is useful for extending the OpenID Connect discovery endpoint. ```csharp services.AddOpenIddict() .AddServer(options => { options.AddEventHandler(builder => builder.UseInlineHandler(context => { // Attach custom metadata to the configuration document. context.Metadata["custom_metadata"] = 42; return default; })); }); ``` -------------------------------- ### New IOpenIddictApplicationStore APIs in C# Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/migration/40-to-50.md Implement these new APIs in your custom application store to support features in OpenIddict 5.0. ```csharp ValueTask GetApplicationTypeAsync(TApplication application, CancellationToken cancellationToken); ValueTask GetJsonWebKeySetAsync(TApplication application, CancellationToken cancellationToken); ValueTask> GetSettingsAsync(TApplication application, CancellationToken cancellationToken); ValueTask SetApplicationTypeAsync(TApplication application, string? type, CancellationToken cancellationToken); ValueTask SetJsonWebKeySetAsync(TApplication application, JsonWebKeySet? set, CancellationToken cancellationToken); ValueTask SetSettingsAsync(TApplication application, ImmutableDictionary settings, CancellationToken cancellationToken); ``` -------------------------------- ### Configure application endpoint permissions Source: https://github.com/openiddict/openiddict-documentation/blob/dev/configuration/application-permissions.md Define allowed endpoints for a client application during registration using OpenIddictApplicationDescriptor. ```csharp if (await manager.FindByClientIdAsync("mvc") is null) { await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "mvc", ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654", DisplayName = "MVC client application", PostLogoutRedirectUris = { new Uri("http://localhost:53507/signout-callback-oidc") }, RedirectUris = { new Uri("http://localhost:53507/signin-oidc") }, Permissions = { OpenIddictConstants.Permissions.Endpoints.Authorization, OpenIddictConstants.Permissions.Endpoints.EndSession, OpenIddictConstants.Permissions.Endpoints.Token } }); } ``` -------------------------------- ### Update Endpoint URI Configuration Methods Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/migration/50-to-60.md Replace deprecated 5.x endpoint URI configuration methods with their 6.0 equivalents in the Startup file. ```csharp options.SetCryptographyEndpointUris() ``` ```csharp options.SetJsonWebKeySetEndpointUris() ``` ```csharp options.SetDeviceEndpointUris() ``` ```csharp options.SetDeviceAuthorizationEndpointUris() ``` ```csharp options.SetLogoutEndpointUris() ``` ```csharp options.SetEndSessionEndpointUris() ``` ```csharp options.SetUserinfoEndpointUris() ``` ```csharp options.SetUserInfoEndpointUris() ``` ```csharp options.SetVerificationEndpointUris() ``` ```csharp options.SetEndUserVerificationEndpointUris() ``` -------------------------------- ### Registering a Client Application Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/getting-started/creating-your-own-server-instance.md This code registers a client application with OpenIddict, specifying its client ID, secret, and the permissions it requires. Ensure the database is updated with OpenIddict tables before running. ```csharp // ... // Before starting the host, create the database used to store the application data. // // Note: in a real world application, this step should be part of a setup script. await using (var scope = app.Services.CreateAsyncScope()) { var context = scope.ServiceProvider.GetRequiredService(); await context.Database.EnsureCreatedAsync(); var manager = scope.ServiceProvider.GetRequiredService(); if (await manager.FindByClientIdAsync("service-worker") is null) { await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "service-worker", ClientSecret = "388D45FA-B36B-4988-BA59-B187D329C207", Permissions = { Permissions.Endpoints.Token, Permissions.GrantTypes.ClientCredentials } }); } } await app.RunAsync(); ``` -------------------------------- ### Configure OpenIddict with Entity Framework Core Stores Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/entity-framework-core.md Configure OpenIddict services to use Entity Framework Core for storing its data, specifying the custom DbContext. ```csharp services.AddOpenIddict() .AddCore(options => { options.UseEntityFrameworkCore() .UseDbContext(); }); ``` -------------------------------- ### Configure OpenIddict Server Services Source: https://github.com/openiddict/openiddict-documentation/blob/dev/guides/getting-started/creating-your-own-server-instance.md Register the OpenIddict server components and enable specific endpoints and flows. ```csharp services.AddOpenIddict() // Register the OpenIddict server components. .AddServer(options => { // Enable the token endpoint. options.SetTokenEndpointUris("connect/token"); // Enable the client credentials flow. options.AllowClientCredentialsFlow(); // Register the signing and encryption credentials. options.AddDevelopmentEncryptionCertificate() .AddDevelopmentSigningCertificate(); // Register the ASP.NET Core host and configure the ASP.NET Core options. options.UseAspNetCore() .EnableTokenEndpointPassthrough(); }); ``` -------------------------------- ### Add OpenIddict.MongoDb Package Source: https://github.com/openiddict/openiddict-documentation/blob/dev/integrations/mongodb.md Reference the OpenIddict.MongoDb NuGet package in your project file. ```xml ``` -------------------------------- ### Enable PKI-Based TLS Client Authentication (Server) Source: https://github.com/openiddict/openiddict-documentation/blob/dev/configuration/mutual-tls-authentication.md Enables support for TLS client authentication relying on a Public Key Infrastructure (PKI). Requires registering root and intermediate certificate authorities. ```csharp services.AddOpenIddict() .AddServer(options => { // ... options.EnablePublicKeyInfrastructureTlsClientAuthentication( [ X509Certificate2.CreateFromPem("[PEM-encoded root certificate]"), // Required, if intermediate certificate authorities are used: X509Certificate2.CreateFromPem("[PEM-encoded intermediate certificate 1]"), X509Certificate2.CreateFromPem("[PEM-encoded intermediate certificate 2]") ]); }); ``` -------------------------------- ### Handle Consent and Permanent Authorizations in OpenIddict Source: https://github.com/openiddict/openiddict-documentation/blob/dev/configuration/authorization-storage.md Retrieves existing authorizations and creates a new permanent authorization if necessary to bypass future consent prompts. Requires an active OpenIddict server configuration and appropriate manager services. ```csharp // Retrieve the application details from the database. var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ?? throw new InvalidOperationException("The application cannot be found."); // Retrieve the permanent authorizations associated with the user and the application. var authorizations = await _authorizationManager.FindAsync( subject: await _userManager.GetUserIdAsync(user), client : await _applicationManager.GetIdAsync(application), status : Statuses.Valid, type : AuthorizationTypes.Permanent, scopes : request.GetScopes()).ToListAsync(); switch (await _applicationManager.GetConsentTypeAsync(application)) { // If the consent is external (e.g when authorizations are granted by a sysadmin), // immediately return an error if no authorization can be found in the database. case ConsentTypes.External when !authorizations.Any(): return Forbid( authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, properties: new AuthenticationProperties(new Dictionary { [OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired, [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The logged in user is not allowed to access this client application." })); // If the consent is implicit or if an authorization was found, // return an authorization response without displaying the consent form. case ConsentTypes.Implicit: case ConsentTypes.External when authorizations.Any(): case ConsentTypes.Explicit when authorizations.Any() && !request.HasPrompt(Prompts.Consent): // Create the claims-based identity that will be used by OpenIddict to generate tokens. var identity = new ClaimsIdentity( authenticationType: TokenValidationParameters.DefaultAuthenticationType, nameType: Claims.Name, roleType: Claims.Role); // Add the claims that will be persisted in the tokens. identity.SetClaim(Claims.Subject, await _userManager.GetUserIdAsync(user)) .SetClaim(Claims.Email, await _userManager.GetEmailAsync(user)) .SetClaim(Claims.Name, await _userManager.GetUserNameAsync(user)) .SetClaims(Claims.Role, (await _userManager.GetRolesAsync(user)).ToImmutableArray()); // Note: in this sample, the granted scopes match the requested scope // but you may want to allow the user to uncheck specific scopes. // For that, simply restrict the list of scopes before calling SetScopes. identity.SetScopes(request.GetScopes()); identity.SetResources(await _scopeManager.ListResourcesAsync(identity.GetScopes()).ToListAsync()); // Automatically create a permanent authorization to avoid requiring explicit consent // for future authorization or token requests containing the same scopes. var authorization = authorizations.LastOrDefault(); authorization ??= await _authorizationManager.CreateAsync( identity: identity, subject : await _userManager.GetUserIdAsync(user), client : await _applicationManager.GetIdAsync(application), type : AuthorizationTypes.Permanent, scopes : identity.GetScopes()); identity.SetAuthorizationId(await _authorizationManager.GetIdAsync(authorization)); identity.SetDestinations(static claim => claim.Type switch { // If the "profile" scope was granted, allow the "name" claim to be // added to the access and identity tokens derived from the principal. Claims.Name when claim.Subject.HasScope(Scopes.Profile) => [ OpenIddictConstants.Destinations.AccessToken, OpenIddictConstants.Destinations.IdentityToken ], // Never add the "secret_value" claim to access or identity tokens. // In this case, it will only be added to authorization codes, // refresh tokens and user/device codes, that are always encrypted. "secret_value" => [], // Otherwise, add the claim to the access tokens only. _ => [OpenIddictConstants.Destinations.AccessToken] }); ```