### Initiate Authentication Flow (WPF Application) Source: https://documentation.openiddict.com/integrations/web-providers This C# code example demonstrates how to start the interactive authentication process for a desktop application (WPF) using the 'OpenIddictClientService'. It handles initiating the challenge, authenticating interactively, and displaying a welcome message upon successful login. ```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}.", "Authentication successful", MessageBoxButton.OK, MessageBoxImage.Information); } catch (OperationCanceledException) { MessageBox.Show("The authentication process was aborted.", "Authentication timed out", MessageBoxButton.OK, MessageBoxImage.Warning); } catch (ProtocolException exception) when (exception.Error is Errors.AccessDenied) { MessageBox.Show("The authorization was denied by the end user.", "Authorization denied", MessageBoxButton.OK, MessageBoxImage.Warning); } catch { MessageBox.Show("An error occurred while trying to authenticate the user.", ``` -------------------------------- ### Log: Userinfo Response Example Source: https://documentation.openiddict.com/guides/contributing-a-new-web-provider This is an example log entry showing a successfully extracted userinfo response from a provider. It illustrates the format of the raw JSON payload before it's processed by handlers like UnwrapUserinfoResponse, demonstrating a common nested structure under a 'data' node. ```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" } }. ``` -------------------------------- ### Authorization Request Example (HTTP GET) Source: https://documentation.openiddict.com/guides/choosing-the-right-flow An example of an HTTP GET request to the authorization endpoint, typically initiated by the user agent after a redirection. It shows the parameters sent to the identity provider. ```http GET /connect/authorize?response_type=code&client_id=s6BhdRkqt3&state=af0ifjsldkj&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1 Host: server.example.com ``` -------------------------------- ### Configuration with PKCE Support (XML) Source: https://documentation.openiddict.com/guides/contributing-a-new-web-provider This XML configuration is used for providers that support Proof Key for Code Exchange (PKCE). It includes a `` node under `` to ensure the OpenIddict client correctly sends the `code_challenge` and `code_challenge_method` parameters. This example is for the Fitbit provider. ```xml ``` -------------------------------- ### Add Specific Web Providers (GitHub, Twitter) Source: https://documentation.openiddict.com/integrations/web-providers This C# example illustrates how to add and configure specific web providers like GitHub and Twitter within the OpenIddict client setup. It requires setting the client identifier, client secret, and redirect URI for each provider. ```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"); }); }); ``` -------------------------------- ### Implement Client Credentials Grant in AuthorizationController Source: https://documentation.openiddict.com/guides/getting-started/creating-your-own-server-instance Provides an example of an authorization controller action to handle the client credentials grant type. It demonstrates how to retrieve the application, create a ClaimsIdentity, and set claims for token creation, assuming OpenIddict has already validated the client credentials. ```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. var identity = new ClaimsIdentity(TokenValidationParameters.DefaultAuthenticationType, Claims.Name, Claims.Role); // Use the client_id as the subject identifier. identity.SetClaim(Claims.Subject, await _applicationManager.GetClientIdAsync(application)); identity.SetClaim(Claims.Name, await _applicationManager.GetDisplayNameAsync(application)); identity.SetDestinations(static claim => claim.Type switch ``` -------------------------------- ### Implement Interactive Authentication Flow Source: https://documentation.openiddict.com/integrations/operating-systems Use OpenIddictClientService to initiate and complete an interactive authentication process. Call ChallengeInteractivelyAsync() to start the authentication flow, then AuthenticateInteractivelyAsync() to wait for user authorization and retrieve the authenticated principal with claims. ```csharp try { var result = await _service.ChallengeInteractivelyAsync(new() { ProviderName = provider }); 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); } ``` -------------------------------- ### Add OpenIddict.MongoDb NuGet Package Source: https://documentation.openiddict.com/integrations/mongodb Installs the OpenIddict MongoDB integration package. This is the first step to enable MongoDB support for OpenIddict. ```xml ``` -------------------------------- ### Configure OpenIddict Core Services in Program.cs Source: https://documentation.openiddict.com/guides/getting-started/integrating-with-a-remote-server-instance Configures the core OpenIddict services, including database context setup with Entity Framework Core and SQL Server. This is essential for the stateful nature of the OpenIddict client, which uses token stores to protect against attacks like CSRF and session fixation. ```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(); }); ``` ```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(); }); ``` -------------------------------- ### Implicit Flow Authorization Request (HTTP) Source: https://documentation.openiddict.com/guides/choosing-the-right-flow An example of an HTTP request initiating the implicit flow. It includes parameters like `response_type=token`, `client_id`, `redirect_uri`, and `scope`. ```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 ``` -------------------------------- ### Authorization Code Flow - Step 1: Authorization Request Source: https://documentation.openiddict.com/guides/choosing-the-right-flow Initiates the authentication process by redirecting the user to the authorization endpoint with necessary parameters. Supports GET and POST requests. ```APIDOC ## GET /connect/authorize ### Description Initiates the authorization code flow by redirecting the user agent to the authorization endpoint. This step involves the client application generating an authorization request with mandatory and optional parameters. ### Method GET (or POST for large requests) ### Endpoint `/connect/authorize` ### Parameters #### Query Parameters - **response_type** (string) - Required - Must be set to `code`. - **client_id** (string) - Required - The unique identifier of the client application. - **redirect_uri** (string) - Required - The URI to which the user agent will be redirected after authorization. - **scope** (string) - Optional - Defines the level of access requested (e.g., `openid`). - **state** (string) - Optional - A value used to maintain state and mitigate XSRF attacks. ### Request Example (GET) ``` GET /connect/authorize?response_type=code&client_id=s6BhdRkqt3&state=af0ifjsldkj&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1 Host: server.example.com ``` ### Response #### Success Response (302 Found) - **Location** (string) - The redirect URI with the authorization code and state parameters. #### Response Example (Location Header) ``` Location: https://client.example.org/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj ``` #### Warnings - The client application MUST ensure that the `state` parameter returned by the identity provider corresponds to the original `state` to prevent XSRF/session fixation attacks. ``` -------------------------------- ### Configure Client Registration with Custom URI Schemes Source: https://documentation.openiddict.com/integrations/operating-systems Set up a client registration with custom URI schemes for redirect and post-logout redirect URIs. This example uses custom URI schemes (com.openiddict.sandbox.maui.client://) for iOS, macOS, and Android platforms, and registers Twitter as a web provider with appropriate callback URLs. ```csharp services.AddOpenIddict() .AddClient(options => { // ... options.AddRegistration(new OpenIddictClientRegistration { Issuer = new Uri("https://localhost:44395/", UriKind.Absolute), ProviderName = "Local", ClientId = "maui", 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" } }); options.UseWebProviders() .AddTwitter(options => { options.SetClientId("bXgwc0U3N3A3YWNuaWVsdlRmRWE6MTpjaQ") .SetRedirectUri("com.openiddict.sandbox.maui.client://callback/login/twitter"); }); }); ``` -------------------------------- ### Adjust OpenIddict Endpoint Configuration (C#) Source: https://documentation.openiddict.com/guides/migration/50-to-60 This example demonstrates how to update your ASP.NET Core startup configuration to reflect the renamed server endpoints in OpenIddict 6.0. It shows the mapping from the older 5.x endpoint URIs to the new 6.x URIs. ```csharp // OpenIddict 5.x // options.SetCryptographyEndpointUris(); // options.SetDeviceEndpointUris(); // options.SetLogoutEndpointUris(); // options.SetUserinfoEndpointUris(); // options.SetVerificationEndpointUris(); // OpenIddict 6.x options.SetJsonWebKeySetEndpointUris(); options.SetDeviceAuthorizationEndpointUris(); options.SetEndSessionEndpointUris(); options.SetUserInfoEndpointUris(); options.SetEndUserVerificationEndpointUris(); ``` -------------------------------- ### Add OpenIddict Packages to .csproj Source: https://documentation.openiddict.com/guides/getting-started/creating-your-own-server-instance References the necessary OpenIddict packages for ASP.NET Core integration and Entity Framework Core support. Ensure you use the latest stable versions. ```xml ``` -------------------------------- ### Configure OpenIddict Server Services in Program.cs Source: https://documentation.openiddict.com/guides/getting-started/creating-your-own-server-instance Sets up the OpenIddict server components, enabling the token endpoint, allowing the client credentials flow, and configuring development encryption and signing certificates. It also integrates with the ASP.NET Core host. ```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(); }); ``` -------------------------------- ### Configure Entity Framework Core with Custom Key Type (Guid) Source: https://documentation.openiddict.com/integrations/entity-framework-core Configures Entity Framework Core to use a `Guid` as the primary key type for OpenIddict entities. This must align with the configuration in the OpenIddict services. ```csharp services.AddDbContext(options => { // Configure the Entity Framework Core to use Microsoft SQL Server. options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")); // Register the entity sets needed by OpenIddict but use a custom key type. options.UseOpenIddict(); }); ``` -------------------------------- ### Configure OpenIddict with Custom Key Type (Guid) Source: https://documentation.openiddict.com/integrations/entity-framework-core Shows how to configure OpenIddict to use a custom primary key type, specifically `Guid`, for its entities when using Entity Framework Core. This is useful for scenarios requiring different key structures. ```csharp services.AddOpenIddict() .AddCore(options => { // Configure OpenIddict to use the default entities with a custom key type. options.UseEntityFrameworkCore() .UseDbContext() .ReplaceDefaultEntities(); }); ``` -------------------------------- ### Register Entity Framework Core and OpenIddict Core Services in Program.cs Source: https://documentation.openiddict.com/guides/getting-started/creating-your-own-server-instance Configures the application's database context using Entity Framework Core with SQL Server and registers the core OpenIddict services. It specifies the use of EF Core stores and models, and allows for replacing default entities if needed. ```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(); }); ``` -------------------------------- ### Multi-Tenant Provider Configuration with Dynamic URIs (XML) Source: https://documentation.openiddict.com/guides/contributing-a-new-web-provider This XML demonstrates how to configure multi-tenant providers like Zendesk, where URIs include dynamic parts (e.g., subdomains). A `` node defines the tenant parameter, and placeholders like `{settings.Tenant}` are used within the URIs. The `Issuer`, `AuthorizationEndpoint`, `TokenEndpoint`, and `UserinfoEndpoint` are all configured dynamically. ```xml ``` -------------------------------- ### Implicit Flow Authorization Response (HTTP) Source: https://documentation.openiddict.com/guides/choosing-the-right-flow An example of an HTTP redirect response from the authorization server. The access token is included in the URI fragment. ```http HTTP/1.1 302 Found Location: https://client.example.org/cb#access_token=SlAV32hkKG&token_type=bearer&expires_in=3600&state=af0ifjsldkj ``` -------------------------------- ### GET /connect/authorize (Implicit Flow) Source: https://documentation.openiddict.com/guides/choosing-the-right-flow Initiates the Implicit Flow by requesting an access token directly. The token is returned in the URI fragment of the redirect. ```APIDOC ## GET /connect/authorize (Implicit Flow) ### Description This endpoint initiates the Implicit Flow, allowing a client application to obtain an access token directly as part of the authorization response. It's primarily used for browser-based applications and is not recommended for new development due to security limitations. ### Method GET ### Endpoint /connect/authorize ### Parameters #### Query Parameters - **response_type** (string) - Required - Must be set to `token` for the Implicit Flow. - **client_id** (string) - Required - The identifier of the client application. - **redirect_uri** (string) - Required - The URI to which the user agent is redirected after authorization. - **scope** (string) - Required - The scopes of the access request (e.g., `openid`). - **state** (string) - Required - An opaque value used to maintain state between the request and callback to prevent CSRF attacks. - **nonce** (string) - Optional - A value used in OpenID Connect to mitigate replay attacks. ### Request Example ```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 ``` ### Response #### Success Response (302 Found) - **Location** (string) - The redirect URI with the access token and other parameters appended in the URI fragment. #### Response Example ```http HTTP/1.1 302 Found Location: https://client.example.org/cb#access_token=SlAV32hkKG&token_type=bearer&expires_in=3600&state=af0ifjsldkj ``` ### Security Considerations - **State Parameter Verification**: Client applications MUST verify that the `state` parameter returned matches the original `state` to prevent CSRF/session fixation attacks. - **Confused Deputy Attacks (Legacy OAuth 2.0)**: For legacy OAuth 2.0 implicit flow (`response_type=token`), client applications should implement checks to ensure the access token was issued to the correct application, as there's no standard mechanism for this. - **OpenID Connect**: In the OpenID Connect version, the `aud` claim in the JWT identity token can be used to verify the token's intended audience (`client_id`), mitigating confused deputy attacks. ``` -------------------------------- ### Initiate Authentication with a Specific GitHub Instance Source: https://documentation.openiddict.com/integrations/web-providers Shows how to trigger the authentication flow for a specific registered provider instance (e.g., 'GitHub-Instance-A') using the Challenge method in an ASP.NET Core controller. This directs the user's agent to the corresponding provider. ```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"); } ``` -------------------------------- ### Reference OpenIddict Package (XML) Source: https://documentation.openiddict.com/guides/getting-started/integrating-with-a-remote-server-instance This XML snippet shows how to update a .NET project's .csproj file to include the necessary OpenIddict package, ensuring version 7.2.0 or later is referenced for client functionality. ```xml ``` -------------------------------- ### Client Credentials Grant Request Source: https://documentation.openiddict.com/guides/choosing-the-right-flow Example HTTP request for the Client Credentials grant. This flow is recommended for machine-to-machine communication where no user is involved. It requires the grant_type, client_id, and client_secret. ```http POST /connect/token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=s6BhdRkqt3&client_secret=gX1fBat3bV ``` -------------------------------- ### Add OpenIddict Client Services (C#) Source: https://documentation.openiddict.com/guides/getting-started/integrating-with-a-remote-server-instance Configures the OpenIddict client services in Program.cs or Startup.cs. It enables the client credentials flow, disables token storage for non-interactive flows, registers the System.Net.Http integration, and adds a specific client registration with issuer, client ID, and secret. ```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" }); }); ``` -------------------------------- ### Configure Product Information for User-Agent Header Source: https://documentation.openiddict.com/integrations/system-net-http Illustrates how to configure product name and version information for the System.Net.Http integration in OpenIddict. This enhances the 'User-Agent' header, providing more detail about your application to servers. ```csharp services.AddOpenIddict() .AddClient(options => { options.UseSystemNetHttp() .SetProductInformation("Contoso", "1.0.0"); }) .AddValidation(options => { options.UseSystemNetHttp() .SetProductInformation("Contoso", "1.0.0"); }); ``` ```csharp services.AddOpenIddict() .AddClient(options => { options.UseSystemNetHttp() .SetProductInformation(typeof(Program).Assembly); }) .AddValidation(options => { options.UseSystemNetHttp() .SetProductInformation(typeof(Program).Assembly); }); ``` -------------------------------- ### Create Error Controller for OpenIddict Server Errors Source: https://documentation.openiddict.com/integrations/aspnet-core An example of an error controller action designed to handle errors from the OpenIddict server. It uses `HttpContext.GetOpenIddictServerResponse()` to fetch server-specific error details for display. ```csharp public class ErrorController : Controller { [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true), Route("~/error")] public IActionResult Error() { // If the error originated from the OpenIddict server, render the error details. var response = HttpContext.GetOpenIddictServerResponse(); if (response is not null) { return View(new ErrorViewModel { Error = response.Error, ErrorDescription = response.ErrorDescription }); } return View(new ErrorViewModel()); } } ``` -------------------------------- ### Configure OpenIddict Client Services with GitHub Integration Source: https://documentation.openiddict.com/guides/getting-started/integrating-with-a-remote-server-instance Sets up the OpenIddict client services, enabling the authorization code flow and integrating with GitHub as an OAuth provider. This includes configuring encryption and signing certificates, ASP.NET Core host options, System.Net.Http integration, and specific provider settings like client ID, secret, and redirect URI. ```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"); }); }); ``` -------------------------------- ### Create Error Controller for OpenIddict Client Errors Source: https://documentation.openiddict.com/integrations/aspnet-core An example of an error controller action that handles errors originating from the OpenIddict client. It retrieves client-specific error information using `HttpContext.GetOpenIddictClientResponse()` and displays it in a view. ```csharp public class ErrorController : Controller { [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true), Route("~/error")] public IActionResult Error() { // If the error originated from the OpenIddict client, render the error details. var response = HttpContext.GetOpenIddictClientResponse(); if (response is not null) { return View(new ErrorViewModel { Error = response.Error, ErrorDescription = response.ErrorDescription }); } return View(new ErrorViewModel()); } } ``` -------------------------------- ### Configure Allowed Ports for Embedded Web Server in OpenIddict Source: https://documentation.openiddict.com/integrations/operating-systems Specifies an ordered list of ports that OpenIddict will attempt to use when starting the embedded web server for localhost callbacks. Useful when the authorization server does not support dynamic ports or native applications. ```csharp services.AddOpenIddict() .AddClient(options => { options.UseSystemIntegration() .SetAllowedEmbeddedWebServerPorts(17812, 17813, 17814); }); ``` -------------------------------- ### Create Authentication Controller for Callbacks Source: https://documentation.openiddict.com/guides/getting-started/integrating-with-a-remote-server-instance Defines an authentication controller with an action method designed to handle OAuth 2.0/OpenID Connect callback requests from external providers. The `[HttpGet]` and `[HttpPost]` attributes, along with `IgnoreAntiforgeryToken`, are important for allowing requests from the identity provider. ```csharp [HttpGet("~/callback/login/{provider}"), HttpPost("~/callback/login/{provider}"), IgnoreAntiforgeryToken] public async Task LogInCallback() { // ... implementation to handle the callback ``` -------------------------------- ### Reference OpenIddict System Integration Package Source: https://documentation.openiddict.com/integrations/operating-systems Add the OpenIddict.Client.SystemIntegration NuGet package to your project. This package is required as an extension to the OpenIddict client for operating system integration support. ```xml ``` -------------------------------- ### Configure OpenIddict ASP.NET Core Features Source: https://documentation.openiddict.com/integrations/aspnet-core Configure OpenIddict's client, server, and validation features within the ASP.NET Core dependency injection setup, enabling the ASP.NET Core integration for each desired feature. ```csharp services.AddOpenIddict() .AddCore(options => { // ... }) .AddClient(options => { // ... options.UseAspNetCore(); }) .AddServer(options => { // ... options.UseAspNetCore(); }) .AddValidation(options => { // ... options.UseAspNetCore(); }); ``` -------------------------------- ### Register Client Application with OpenIddict (C#) Source: https://documentation.openiddict.com/guides/getting-started/creating-your-own-server-instance Registers a client application using an IHostedService. It ensures the database is created and checks if a client with the ID 'service-worker' already exists, creating it if necessary with specified permissions. ```csharp public class Worker : IHostedService { private readonly IServiceProvider _serviceProvider; public Worker(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; public async Task StartAsync(CancellationToken cancellationToken) { using var scope = _serviceProvider.CreateScope(); 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 } }); } } public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; } ``` -------------------------------- ### Register Multiple GitHub Instances with OpenIddict Client Source: https://documentation.openiddict.com/integrations/web-providers Demonstrates how to register two distinct instances of the GitHub provider within the OpenIddict client configuration. Each instance requires unique client credentials, redirect URIs, and provider names to differentiate them. ```csharp services.AddOpenIddict() .AddClient(options => { options.UseWebProviders() .AddGitHub(options => { options.SetClientId("[client identifier A]") .SetClientSecret("[client secret A]") .SetRedirectUri("callback/login/github/a") .SetProviderName("GitHub-Instance-A"); }) .AddGitHub(options => { options.SetClientId("[client identifier B]") .SetClientSecret("[client secret B]") .SetRedirectUri("callback/login/github/b") .SetProviderName("GitHub-Instance-B"); }); }); ``` -------------------------------- ### Update OpenIddict Request Caching and Permissions (C#) Source: https://documentation.openiddict.com/guides/migration/50-to-60 This code example shows the renaming of constants and configuration options related to request caching and endpoint permissions in OpenIddict 6.0. It highlights the changes from 'Logout' to 'EndSession' and 'Device' to 'DeviceAuthorization'. ```csharp // OpenIddict 5.x // options.EnableLogoutRequestCaching(); // OpenIddictConstants.Permissions.Endpoints.Device // OpenIddictConstants.Permissions.Endpoints.Logout // OpenIddict 6.x options.EnableEndSessionRequestCaching(); OpenIddictConstants.Permissions.Endpoints.DeviceAuthorization; OpenIddictConstants.Permissions.Endpoints.EndSession; // Additionally, update your applications table/database for permissions: // 'ept:device' -> 'ept:device_authorization' // 'ept:logout' -> 'ept:end_session' ``` -------------------------------- ### Define Custom OpenIddict Entities Source: https://documentation.openiddict.com/integrations/entity-framework-core Provides examples of creating custom entity classes that inherit from OpenIddict's default Entity Framework Core entities. This allows for storing additional properties specific to your application. ```csharp public class CustomApplication : OpenIddictEntityFrameworkCoreApplication { public string CustomProperty { get; set; } } public class CustomAuthorization : OpenIddictEntityFrameworkCoreAuthorization { public string CustomProperty { get; set; } } public class CustomScope : OpenIddictEntityFrameworkCoreScope { public string CustomProperty { get; set; } } public class CustomToken : OpenIddictEntityFrameworkCoreToken { public string CustomProperty { get; set; } } ``` -------------------------------- ### Retrieve Access Token with Client Credentials (C#) Source: https://documentation.openiddict.com/guides/getting-started/integrating-with-a-remote-server-instance Demonstrates how to use the OpenIddictClientService to authenticate with client credentials and retrieve an access token from the remote authorization server. It requires dependency injection to obtain the service instance. ```csharp var service = provider.GetRequiredService(); var result = await service.AuthenticateWithClientCredentialsAsync(new()); var token = result.AccessToken; ``` -------------------------------- ### Configure Issuer in XML Source: https://documentation.openiddict.com/guides/contributing-a-new-web-provider This XML snippet demonstrates how to set the 'Issuer' attribute within the '' tag for an OpenIddict provider. It shows the standard configuration and an example where a separate 'ConfigurationEndpoint' is needed if the issuer in the metadata doesn't match the discovery document's base URL. ```xml ``` -------------------------------- ### Configure Claims Mapping for OpenIddict Server (C#) Source: https://documentation.openiddict.com/guides/getting-started/creating-your-own-server-instance Configures how claims, like the 'name' claim, are stored in access and identity tokens based on granted scopes. It uses a switch expression to determine the claim destinations. ```csharp Claims.Name when claim.Subject.HasScope(Scopes.Profile) => [Destinations.AccessToken, Destinations.IdentityToken], _ => [Destinations.AccessToken] }); return SignIn(new ClaimsPrincipal(identity), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); ``` -------------------------------- ### Resource Owner Password Credentials Grant (ROPC) Response Source: https://documentation.openiddict.com/guides/choosing-the-right-flow Example HTTP response for a successful Resource Owner Password Credentials (ROPC) grant. It returns an access token, token type, and expiration time in JSON format. ```http HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"2YotnFZFEjr1zCsicMWpAA", "token_type":"bearer", "expires_in":3600 } ``` -------------------------------- ### Trigger Login with GitHub (ASP.NET Core) Source: https://documentation.openiddict.com/integrations/web-providers This C# code snippet shows how to initiate the authentication flow with GitHub in an ASP.NET Core application using the 'Challenge' method. It specifies the return URL and the provider name (GitHub). ```csharp [HttpPost("~/login"), ValidateAntiForgeryToken] public async Task LogInWithGitHub(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. return Challenge(properties, OpenIddictClientWebIntegrationConstants.Providers.GitHub); } ``` -------------------------------- ### Update Custom Authorization Store for IOpenIddictEntityFrameworkCoreContext Source: https://documentation.openiddict.com/guides/migration/60-to-70 This example demonstrates updating a custom EF Core authorization store to use IOpenIddictEntityFrameworkCoreContext instead of a DbContext generic argument. This change is required for OpenIddict 7.0's updated EF Core store architecture. ```csharp public sealed class CustomAuthorizationStore : OpenIddictEntityFrameworkCoreAuthorizationStore< CustomAuthorization, CustomApplication, CustomToken, string> { public CustomAuthorizationStore( IMemoryCache cache, IOpenIddictEntityFrameworkCoreContext context, IOptionsMonitor options) : base(cache, context, options) { } } ``` -------------------------------- ### Register Custom HttpClient Configuration Delegate in OpenIddict Source: https://documentation.openiddict.com/integrations/system-net-http Shows how to register a custom `Action` delegate using `ConfigureHttpClient()` to modify the HttpClient instances used by OpenIddict. This is useful for adding default headers like 'Custom-Header'. This example applies to both AddClient and AddValidation. ```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")); }); ``` -------------------------------- ### Configure Custom HTTP Error Policy for Resilience Source: https://documentation.openiddict.com/integrations/system-net-http Provides an example of overriding the default HTTP error policy for the System.Net.Http integration in OpenIddict. This allows customization of retry behavior for transient HTTP errors, including specific status codes like 'NotFound'. ```csharp services.AddOpenIddict() .AddClient(options => { options.UseSystemNetHttp() .SetHttpErrorPolicy(HttpPolicyExtensions.HandleTransientHttpError() .OrResult(static response => response.StatusCode is HttpStatusCode.NotFound) .WaitAndRetryAsync(4, static attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)))); }) .AddValidation(options => { options.UseSystemNetHttp() .SetHttpErrorPolicy(HttpPolicyExtensions.HandleTransientHttpError() .OrResult(static response => response.StatusCode is HttpStatusCode.NotFound) .WaitAndRetryAsync(4, static attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)))); }); ``` -------------------------------- ### Enable System Integration in OpenIddict Client Options Source: https://documentation.openiddict.com/integrations/operating-systems Configure the OpenIddict client by calling UseSystemIntegration() within the AddClient options. This enables the system integration features for handling authentication callbacks and protocol activations. ```csharp services.AddOpenIddict() .AddClient(options => { // ... options.UseSystemIntegration(); }); ``` -------------------------------- ### Register ASP.NET Core Authentication and Authorization Middleware Source: https://documentation.openiddict.com/guides/getting-started/creating-your-own-server-instance Ensures that the necessary ASP.NET Core middleware for authentication, authorization, routing, and endpoint mapping are correctly configured and placed in the request pipeline. This is crucial for the OpenIddict server to function. ```csharp app.UseDeveloperExceptionPage(); app.UseForwardedHeaders(); app.UseRouting(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(options => { options.MapControllers(); options.MapDefaultControllerRoute(); }); ``` -------------------------------- ### Static Configuration for Servers Without Metadata Endpoint (XML) Source: https://documentation.openiddict.com/guides/contributing-a-new-web-provider This XML configuration is used when an OAuth 2.0/OpenID Connect server does not provide a standard metadata endpoint. It requires manually specifying the Issuer, AuthorizationEndpoint, TokenEndpoint, and UserinfoEndpoint. The example shows configuration for Reddit, including optional GrantType nodes. ```xml ``` -------------------------------- ### Configuring OpenIddict Validation with Local Server Integration Source: https://documentation.openiddict.com/configuration/encryption-and-signing-credentials Shows how to configure OpenIddict validation options when the API and authorization server are part of the same project. The `UseLocalServer()` method simplifies the import of signing and encryption credentials. ```csharp services.AddOpenIddict() .AddValidation(options => { options.UseLocalServer(); }); ``` -------------------------------- ### Implement New IOpenIddictApplicationStore APIs in C# Source: https://documentation.openiddict.com/guides/migration/40-to-50 These methods need to be implemented in custom stores to support new features in OpenIddict 5.0. They handle application types, JSON Web Key Sets, and application settings. No specific dependencies are mentioned beyond the OpenIddict framework itself. ```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); ``` -------------------------------- ### Resource Owner Password Credentials Grant (ROPC) Request Source: https://documentation.openiddict.com/guides/choosing-the-right-flow Example HTTP request for the Resource Owner Password Credentials (ROPC) grant. This flow is not recommended for new applications as it exposes user passwords directly to the client. It requires the grant_type, username, and password as form-urlencoded data. ```http POST /connect/token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded grant_type=password&username=johndoe&password=A3ddj3w ```