General Information: General Information about Duende products, including license information, support options, security best practices and a glossary. ----- # AI Agent Skills and MCP Server > Enhance your AI coding assistant with Duende-specific knowledge using Agent Skills for domain expertise and an MCP server for documentation and samples retrieval. When you use AI coding assistants with Duende products, you may find that general-purpose models lack deep expertise on Duende-specific configuration patterns, protocol nuances, and production best practices. Generic responses can miss critical details, like how to configure refresh token rotation, set up a federation gateway, or wire IdentityServer into .NET Aspire. To address this, Duende provides two complementary tools that give your AI coding assistant specialized knowledge: **Duende Agent Skills** and the **Duende Documentation MCP Server**. You can use either or both, depending on your workflow. Agent Skills and the MCP server address different aspects of the same problem and work well together: * **Agent Skills** provide *knowledge*: structured, curated guidance on *what* to look up, *when*, and *how* to apply it. They are static files that run locally in your development environment. When your AI assistant encounters an identity-related task, skills give it the judgment to produce accurate, Duende-specific answers. * **MCP Server** provides *tools*: search, fetch, and sample retrieval against the full Duende documentation, blog, and sample code. It runs as a local server process and gives the AI assistant direct access to the latest published content. Think of skills as the expertise and the MCP server as the reference library. Skills help the AI *know what to do*; the MCP server helps it *look things up*. Together, they give your AI assistant both deep domain knowledge and access to up-to-date authoritative content. ## Which Tool Should You Use? [Section titled “Which Tool Should You Use?”](#which-tool-should-you-use) Choose the approach that fits your workflow: * **Want domain expertise baked into every response?** Install Agent Skills. Your AI assistant will automatically use the relevant skill when it encounters identity-related tasks. * **Want to search and fetch the latest docs and samples?** Register the MCP Server. Your AI assistant gains tools to look up current documentation on demand. * **Want both?** Install both. They are independent and complementary: skills provide structured knowledge while the MCP server provides live content retrieval. [Get Started with Agent Skills ](https://github.com/DuendeSoftware/duende-skills)Installation instructions, skill catalog, and benchmarks [Get Started with the MCP Server ](https://github.com/DuendeSoftware/products/blob/main/docs-mcp/README.md)Setup instructions for VS Code, Rider, and Claude Code ## Agent Skills [Section titled “Agent Skills”](#agent-skills) Duende IdentityServer Agent Skills are a set of `SKILL.md` files following the open [Agent Skills format](https://agentskills.io/). Each skill is a structured knowledge module covering a specific area of identity and access management. ### What They Cover [Section titled “What They Cover”](#what-they-cover) The skills library includes a number of skills and specialized agents across these areas: * **IdentityServer configuration and hosting**: setup, middleware pipeline, clients, resources, scopes, signing credentials, server-side sessions, Dynamic Client Registration (DCR) * **Token management**: token types, refresh token rotation, token exchange, DPoP, mTLS, Pushed Authorization Requests (PAR), FAPI 2.0 compliance * **API protection**: JWT bearer authentication, reference token introspection, scope-based authorization, proof-of-possession * **UI flows**: login, logout, consent, error pages, federation gateways, external providers, Home Realm Discovery * **ASP.NET Core authentication and authorization**: OIDC, JWT Bearer, cookies, policies, claims-based authorization * **Duende BFF**: Backend-for-Frontend security for SPAs, session management, API proxying * **Deployment and operations**: reverse proxy configuration, data protection, health checks, OpenTelemetry, key management, SAML 2.0 * **Testing**: integration testing with `WebApplicationFactory`, mock token issuance, protocol validation * **Specialized agents**: an IdentityServer specialist and an OAuth/OIDC specialist for complex troubleshooting ### Setup [Section titled “Setup”](#setup) Clone the [Duende Agent Skills](https://github.com/DuendeSoftware/duende-skills) repository and copy the skill folders into the skills directory for your AI coding assistant. Each skill is a folder containing a `SKILL.md` file. Copy the individual skill folders into the path your AI assistant expects: | AI Coding Assistant | Skills Path | | :------------------ | :--------------------------- | | GitHub Copilot | `.github/skills/` | | Claude Code | `.claude/skills/` | | OpenCode | `~/.config/opencode/skills/` | | Cursor | `.cursor/skills/` | | Gemini CLI | `.gemini/skills/` | | Codex CLI | `.codex/skills/` | For example, to set up skills for GitHub Copilot: * Windows (PowerShell) PowerShell ```powershell git clone https://github.com/DuendeSoftware/duende-skills.git New-Item -ItemType Directory -Force -Path .github\skills Copy-Item -Recurse duende-skills\skills\* .github\skills\ ``` * macOS / Linux Terminal ```bash git clone https://github.com/DuendeSoftware/duende-skills.git mkdir -p .github/skills cp -r duende-skills/skills/* .github/skills/ ``` Adjust the target path for your AI coding assistant (see the table above). For example, replace `.github/skills/` with `.claude/skills/` for Claude Code, or `~/.config/opencode/skills/` for OpenCode. Once the skill folders are in place, your AI assistant discovers and loads them automatically. No further configuration is needed. When your assistant encounters an identity-related task like configuring token lifetimes or setting up an external provider, it loads the relevant skill without any explicit prompting from you. ### Verify It Works [Section titled “Verify It Works”](#verify-it-works) Ask your AI assistant an identity-specific question, for example: `How do I configure refresh token rotation in IdentityServer?`. If the skills are loaded correctly, the response references Duende-specific configuration and mentions IdentityServer options like `RefreshTokenUsage`. ### Measured Impact [Section titled “Measured Impact”](#measured-impact) Every skill is evaluated using realistic prompts with concrete assertions. In benchmarks, AI responses with skills loaded significantly outperform baseline responses, with the biggest gains in deeply Duende-specific areas like UI flows, API protection, and SAML configuration. See the repository for the latest benchmark results, or run them against your model of choice. [Duende Agent Skills ](https://github.com/DuendeSoftware/duende-skills)Installation instructions, full skill catalog, and benchmark results ## MCP Server [Section titled “MCP Server”](#mcp-server) The Duende Documentation MCP Server implements the open [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) to give AI coding assistants direct access to Duende documentation, blog posts, and sample code. It runs locally and uses SQLite full-text search to index content from multiple sources. ### What It Can Do [Section titled “What It Can Do”](#what-it-can-do) The MCP server provides several tools to your AI assistant: * **Free-text search** across documentation, blog posts, or samples * **Fetch a specific page** from the documentation site * **Get all content for a sample**: retrieve the full code of a Duende sample project * **Get a specific file from a sample**: retrieve individual files from sample code The server indexes content from three sources, keeping its local database up to date with background indexing: * **Documentation**: parsed from the Duende documentation site’s [`llms.txt`](https://docs.duendesoftware.com/llms.txt) * **Blog**: indexed from the RSS feed at [duendesoftware.com/blog](https://duendesoftware.com/blog/) * **Samples**: downloaded from GitHub, including all `.cs`, `.cshtml`, and relevant `.js` files ### Requirements [Section titled “Requirements”](#requirements) * **.NET 10 SDK**: the MCP server is distributed via the `dnx` tool included in the SDK * **Network access**: the server indexes content from remote sources (documentation site, RSS feed, GitHub) * **A compatible AI coding assistant**: any IDE or CLI tool that supports the MCP protocol No Duende license is required to use the MCP server. ### Setup [Section titled “Setup”](#setup-1) To run the Duende Documentation MCP Server, you need the `dnx` tool (included in the .NET 10 SDK) in your system’s `PATH`. The `dnx` tool can download and run applications packaged and distributed through NuGet. Here are some examples of how to register the MCP server in your IDE: * VS Code You can register the MCP server [in your user settings](https://code.visualstudio.com/docs/copilot/chat/mcp-servers#_add-an-mcp-server-to-your-user-settings) to make it available in any workspace, or add a `.vscode/mcp.json` file to your workspace: .vscode/mcp.json ```json { "servers": { "duende-mcp": { "type": "stdio", "command": "dnx", "args": [ "Duende.Documentation.Mcp", "--yes", "--", "--database", "/path/to/database.db" ], "env": {} } } } ``` Replace `/path/to/database.db` with the location where the MCP server should store its SQLite index. * JetBrains Rider In Rider settings, navigate to **Tools | AI Assistant | Model Context Protocol (MCP)**. Add a new MCP server, select **As JSON**, and enter: ```json { "mcpServers": { "duende-mcp": { "command": "dnx", "args": [ "Duende.Documentation.Mcp", "--yes", "--", "--database", "/path/to/database.db" ] } } } ``` Replace `/path/to/database.db` with the location where the MCP server should store its SQLite index. * Claude Code Run the following command: PowerShell ```powershell # Windows (PowerShell) claude mcp add --transport stdio duende-mcp ` -- dnx Duende.Documentation.Mcp --yes ` -- --database C:\path\to\database.db ``` Terminal ```bash # macOS / Linux claude mcp add --transport stdio duende-mcp \ -- dnx Duende.Documentation.Mcp --yes \ -- --database /path/to/database.db ``` Replace the database path with the location where the MCP server should store its SQLite index. The MCP server creates its SQLite database at the path you specify in the `--database` parameter. On first run, it indexes documentation, blog posts, and samples in the background. Subsequent starts reuse the existing index and refresh it incrementally. ### Verify It Works [Section titled “Verify It Works”](#verify-it-works-1) Ask your AI assistant a Duende-specific question, for example: `What is automatic key management?`. If the MCP server is working, the response draws on the indexed documentation and references Duende-specific content. Adding `use Duende` to a prompt can help direct the AI assistant to query the MCP server when the topic could match multiple sources. ### Example Prompts [Section titled “Example Prompts”](#example-prompts) Once the MCP server is registered, you can ask your AI assistant questions like: * `What is a client in OpenID Connect?` * `How can I validate a JWT token in ASP.NET Core?` * `What is automatic key management?` * `Can I add passkeys to Razor Pages? Use Duende.` [Duende Documentation MCP Server ](https://github.com/DuendeSoftware/products/blob/main/docs-mcp/README.md)Setup instructions for VS Code, Rider, and Claude Code ## Support and Feedback [Section titled “Support and Feedback”](#support-and-feedback) For questions, feedback, or to report issues with either the Agent Skills or the MCP server, visit the [Duende community](https://github.com/DuendeSoftware/community/discussions). [Duende Community Forum ](https://github.com/DuendeSoftware/community/discussions)Ask questions and discuss with the Duende developer community ## Disclaimer [Section titled “Disclaimer”](#disclaimer) Duende’s AI developer tools (including the Duende Documentation MCP Server and Duende Agent Skills) are designed to provide Large Language Models (LLMs) with verified, structured context from Duende’s documentation and product knowledge. These tools improve the quality and relevance of AI-assisted development with Duende products, including IdentityServer, BFF and our Open Source offerings, but they do not guarantee the correctness, security, or completeness of AI-generated output. All code, configuration, and architectural decisions produced with the assistance of these tools must be reviewed and validated by qualified developers before deployment to any environment. Duende Software is not responsible for AI-generated output that results from the use of these tools. ----- # ASP.NET Core Data Protection > Comprehensive guide covering key aspects of ASP.NET Core Data Protection. Any Duende server-side application, like IdentityServer or BFF, is developed and deployed as an ASP.NET Core application. While there are a lot of decisions to make, this also means that your implementation can be built, deployed, hosted, and managed with the same technology you’re using for any other ASP.NET applications you have. It is important to correctly configure ASP.NET Core Data Protection in your application. ## About ASP.NET Core Data Protection [Section titled “About ASP.NET Core Data Protection”](#about-aspnet-core-data-protection) Duende’s SDKs, like IdentityServer and BFF, make extensive use of ASP.NET’s [data protection](https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/) feature. It is crucial that you configure data protection correctly when deploying your application in production. ## Data Protection Keys [Section titled “Data Protection Keys”](#data-protection-keys) In local development, ASP.NET automatically creates data protection keys, but in a deployed environment, you will need to ensure that your data protection keys are stored in a persistent way and shared across all load balanced instances of your implementation. This means you’ll need to choose where to store and how to protect the data protection keys, as appropriate for your environment. Microsoft has [extensive documentation on data protection](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview) describing how to configure storage and protection of data protection keys. A typical implementation should include data protection configuration code, like this: Program.cs ```csharp builder.Services.AddDataProtection() // Choose an extension method for key persistence, such as // PersistKeysToFileSystem, PersistKeysToDbContext, // PersistKeysToAzureBlobStorage, PersistKeysToAWSSystemsManager, or // PersistKeysToStackExchangeRedis .PersistKeysToFoo() // Choose an extension method for key protection, such as // ProtectKeysWithCertificate, ProtectKeysWithAzureKeyVault .ProtectKeysWithBar() // Explicitly set an application name to prevent issues with // key isolation. .SetApplicationName("My.Duende.IdentityServer"); ``` Ensure data protection keys are persisted Always make sure data protection is configured to persist data protection keys to storage, using `.PersistKeysTo...()` for your storage mechanism. If you lose your data protection keys, all data protected with those keys is no longer be readable. Additionally, ensure the storage mechanism itself is durable. For example, if you are using the default file system based key store, make sure that the configured path is not stored on ephemeral storage. If you are using Redis to store data protection keys using `PersistKeysToStackExchangeRedis()`, ensure that your Redis service is configured to persist data to a database backup or append-only file. Otherwise, you will lose all data protection keys when your Redis instance reboots. For a more advanced setup, you can create a [key escrow sink](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/extensibility/key-management?view=aspnetcore-10.0#xmlkeymanager), allowing you to store new data protection keys into a secure storage (e.g., Azure Key Vault) before the new keys are encrypted. This enables you to restore existing data protection keys in case they become corrupted or lost. ## Common Problems [Section titled “Common Problems”](#common-problems) Common data protection problems occur when data is protected with a key that is not available when the data is later read. A common symptom is `CryptographicException`s in the application logs. For example, when IdentityServer’s automatic key management fails to read its signing keys due to a data protection failure, it will log an error message such as `"Error unprotecting key with kid {Signing Key ID}."`, and log the underlying `System.Security.Cryptography.CryptographicException`, with a message like `"The key {Data Protection Key ID} was not found in the key ring."` Failures to read automatic signing keys are often the first place where a data protection problem manifests, but any of many places where ASP.NET uses data protection might also throw `CryptographicException`s. There are several ways that data protection problems can occur: 1. In load balanced environments, every instance of a Duende server-side app needs to be configured to share data protection keys. Without shared data protection keys, each load balanced instance will only be able to read the data that it writes. 2. Data protected data could be generated in a development environment and then accidentally included into the build output. This is most commonly the case for automatically managed signing keys that are stored on disk. If you are using automatic signing key management with the default file system based key store, you should exclude the `~/keys` directory from source control and make sure keys are not included in your builds. Note that if you are using our Entity Framework based implementation of the operational data stores, then the keys will instead be stored in the database. 3. Data protection derives keys isolated per application name from the generated key material. If you don’t specify a name, the content root path of the application will be used. In .NET 6.0, Microsoft introduced a breaking change: they changed how ASP.NET Core sets the content root path, which can cause Data Protection issues. This change was reverted in .NET 7.0, and Microsoft has [documented a workaround in case your application has to restore the correct application name](https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview#set-the-application-name-setapplicationname). A better solution is to always specify an explicit application name, but know that changing the application name will cause all existing data protected with the previous application name to become unreadable. 4. When hosting your web application on Microsoft IIS, [special configuration may be required for data protection](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/advanced#data-protection). In most default deployments, IIS falls back to using an ephemeral storage for data protection keys, which means that new keys are generated every time the application pool restarts. We recommend storing data protection keys in a shared location, such as a protected file share or database, and configuring IIS to use that location for data protection. ----- # Glossary > A comprehensive glossary of security and identity management terms, including features and concepts used in Duende IdentityServer The glossary below provides definitions and explanations of commonly used terms and features within the security and identity management domain. Explore each term to gain a deeper understanding of its functionality and relevance. ## Client [Section titled “Client”](#client) A client is a piece of software that requests tokens from your IdentityServer - either for authenticating a user ( requesting an identity token) or for accessing a resource (requesting an access token). A client must be first registered with your IdentityServer before it can request tokens and is identified by a unique client ID. There are many different client types, e.g. web applications, native mobile or desktop applications, SPAs, server processes, etc. [Documentation ](/identityserver/fundamentals/clients)Learn more about clients ## Connected Application [Section titled “Connected Application”](#connected-application) A connected application is any application or service registered with your Duende IdentityServer instance that relies on it for identity, access, or federation. Each connected application has a unique registration that defines how it interacts with IdentityServer and what it is allowed to do. Connected applications fall into four categories: 1. Interactive applications use OpenID Connect (OIDC) to authenticate users and obtain tokens. These include web applications, native mobile or desktop applications, and SPAs, each identified by its own [Client ID](/general/glossary/#client). 2. Machine-to-machine clients request access tokens without user interaction, typically using the client credentials grant. Background services, APIs calling other APIs, and MCP clients are common examples. 3. Third-party API consumer that requires a client ID and client secret, typically in a SaaS situation or B2B situation. 4. SAML Service Providers use SAML 2.0 to establish federated trust with IdentityServer acting as the Identity Provider (IdP), enabling single sign-on for applications that rely on SAML-based authentication. ## Core Protocols [Section titled “Core Protocols”](#core-protocols) **License: Lite, Standard, Advanced, Custom** Core protocols cover the OpenID Connect (OIDC) and OAuth 2.0 foundations that most applications need. If you’re building a typical web app, API, or mobile client, core protocols handle authentication, token issuance, and token validation out of the box. Here’s what’s included: | Protocol | What It Does | | :------------------------------------------------- | :--------------------------------------------------------------------- | | OAuth 2.0 Core | Token-based authorization for APIs | | OpenID Connect Core | User authentication on top of OAuth 2.0 | | OIDC Discovery / Authorization Server Metadata | Clients auto-discover your server’s endpoints and capabilities | | Authorization Code Flow | The recommended flow for interactive apps (with PKCE) | | Client Credentials Flow | Machine-to-machine token acquisition | | Token Exchange | Swap one token for another across trust boundaries | | Step-up Authentication | Require stronger authentication for sensitive operations | | JSON Web Tokens (JWT) | Standard token format for access and identity tokens | | JWT Access Token Profile | Structured JWT access tokens per the IETF profile | | JWT Client Authentication | Clients authenticate using signed JWTs instead of shared secrets | | JWT Introspection Response | Token metadata returned as a signed JWT | | Bearer Token Usage | Standard `Authorization: Bearer` header for API calls | | Token Revocation | Invalidate tokens before they expire | | Token Introspection | APIs verify opaque tokens against the server | | RP-Initiated / Front-Channel / Back-Channel Logout | Full suite of logout flows | | PAR (Pushed Authorization Requests) | Clients send auth parameters directly to the server before redirect | | DPoP (Demonstrating of Proof-of-Possession) | Binds tokens to a client’s key pair so stolen tokens can’t be replayed | | Form Post Response Mode | Auth responses delivered via POST instead of the query string | | Multiple Response Types | Support for different OAuth response modes | For the majority of .NET applications, core protocols handle every scenario: users log in, APIs validate tokens, machines talk to machines, and sessions end cleanly. ## Extended Protocols [Section titled “Extended Protocols”](#extended-protocols) **License: Standard, Advanced, Custom** Extended protocols address requirements that go beyond typical web and API scenarios. | Protocol | What It Does | | :------------------------------------------------- | :-------------------------------------------------------------------------------- | | mTLS (Mutual TLS) | Binds tokens to a client certificate for sender-constrained access | | JAR (JWT-Secured Authorization Requests) | Wraps the authorization request in a signed JWT for integrity and confidentiality | | Resource Indicators | Lets a client specify which API it’s targeting when requesting tokens | | CIBA (Client-Initiated Backchannel Authentication) | Authentication triggered by a backend service, not a browser redirect | | Device Authorization Grant | Login flow for devices without a browser (smart TVs, CLI tools, IoT) | | DCR (Dynamic Client Registration) | Clients register themselves programmatically instead of being pre-configured | These protocols solve real problems, but they’re problems that surface in specific business contexts rather than in every project. ## Automatic Key Management [Section titled “Automatic Key Management”](#automatic-key-management) **License: Business (legacy), Enterprise (legacy), Standard (add-on), Advanced, Custom** The automatic key management feature creates and manages key material for signing tokens and follows best practices for handling this key material, including storage and rotation. [More Details ](https://duendesoftware.com/blog/20201028-key-management)Automatic Key Management post [Documentation ](/identityserver/fundamentals/key-management/#automatic-key-management)Learn more about key rotation ## Server-side Session Management [Section titled “Server-side Session Management”](#server-side-session-management) **License: Business (legacy), Enterprise (legacy), Standard, Advanced, Custom** The server-side session management feature extends the ASP.NET Core cookie authentication handler to maintain a user’s authentication session state in a server-side store, rather than putting it all into a self-contained cookie. Using server-side sessions enables more architectural features in your IdentityServer, such as: * query and manage active user sessions (e.g. from an administrative app). * detect session expiration and perform cleanup, both in IdentityServer and in client apps. * centralize and monitor session activity in order to achieve a system-wide inactivity timeout. [More Details ](https://duendesoftware.com/blog/20220406-session-management)Server-side Session Management post [Documentation ](/identityserver/ui/server-side-sessions/)Learn more about Server-side Session Management ## BFF Security Framework [Section titled “BFF Security Framework”](#bff-security-framework) **License: Lite, Standard, Advanced, Custom** The Duende Backend For Frontend (BFF) security framework packages up guidance and the necessary components to secure browser-based frontends (e.g. SPAs or Blazor WASM applications) with ASP.NET Core backends. [More Details ](https://duendesoftware.com/blog/20210326-bff)BFF Security Framework post [Documentation ](/bff/)Learn more about BFF ## Dynamic Client Registration [Section titled “Dynamic Client Registration”](#dynamic-client-registration) **License: Business (legacy), Enterprise (legacy), Standard, Advanced, Custom** Implementation of [RFC 8707](https://tools.ietf.org/html/rfc8707). Provides a standards-based endpoint to register clients and their configuration. [Documentation ](/identityserver/configuration)Learn more about Dynamic Client Registration ## Pushed Authorization Requests [Section titled “Pushed Authorization Requests”](#pushed-authorization-requests) **License: Business (legacy), Lite, Standard, Advanced, Custom** Implementation of [RFC 9126](https://www.rfc-editor.org/rfc/rfc9126.html). Provides a more secure way to start a browser-based token/authentication request. [Documentation ](/identityserver/tokens/par)Learn more about Pushed Authorization Requests ## Dynamic Authentication Providers [Section titled “Dynamic Authentication Providers”](#dynamic-authentication-providers) **License: Enterprise (legacy), Advanced, Custom** The dynamic configuration feature allows dynamic loading of configuration for OpenID Connect providers from a store. This is designed to address the performance concern and allowing changes to the configuration to a running server. [More Details ](https://duendesoftware.com/blog/20210517-dynamic-providers)Dynamic Authentication Providers post [Documentation ](/identityserver/fundamentals/key-management/#automatic-key-management)Learn more about Dynamic Authentication Providers ## Resource Isolation [Section titled “Resource Isolation”](#resource-isolation) **License: Enterprise (legacy), Standard, Advanced, Custom** The resource isolation feature allows a client to request access tokens for an individual resource server. This allows API-specific features such as access token encryption and isolation of APIs that are not in the same trust boundary. [More Details ](https://duendesoftware.com/blog/20260210-implementing-zero-trust-with-resource-isolation)Resource Isolation post [Documentation ](/identityserver/fundamentals/resources/isolation/)Learn more about Resource Isolation ## Client-Initiated Backchannel Authentication (CIBA) [Section titled “Client-Initiated Backchannel Authentication (CIBA)”](#client-initiated-backchannel-authentication-ciba) **License: Enterprise (legacy), Standard, Advanced, Custom** Duende IdentityServer supports the Client-Initiated Backchannel Authentication Flow (also known as CIBA). This allows a user to log in with a higher security device (e.g. their mobile phone) than the device on which they are using an application (e.g. a public kiosk). CIBA is one of the requirements to support the Financal-grade API compliance. [More Details ](https://duendesoftware.com/blog/20220107-ciba)Client-Initiated Backchannel Authentication post [Documentation ](/identityserver/ui/ciba/)Learn more about CIBA ## Proof-of-Possession At The Application Layer / DPoP [Section titled “Proof-of-Possession At The Application Layer / DPoP”](#proof-of-possession-at-the-application-layer--dpop) **License: Enterprise (legacy), Standard, Advanced, Custom** A mechanism for sender-constraining OAuth 2.0 tokens via a proof-of-possession mechanism on the application level. This mechanism allows for the detection of replay attacks with access and refresh tokens. [Documentation ](/identityserver/tokens/pop/)Learn more about Proof-of-Possession ## SAML 2.0 Identity Provider [Section titled “SAML 2.0 Identity Provider”](#saml-20-identity-provider) **License: Enterprise (legacy), Standard (add-on), Advanced, Custom** IdentityServer can act as a SAML 2.0 Identity Provider (IdP), issuing SAML assertions to Service Providers (SPs) that use the SAML 2.0 protocol rather than OAuth 2.0 / OpenID Connect. This is useful for integrating with enterprise SaaS applications (e.g. Salesforce, ServiceNow) or legacy SSO systems that require SAML-based federation. [Documentation ](/identityserver/saml/)Learn more about SAML 2.0 Identity Provider support ## Financial-Grade Security and Conformance (FAPI 2.0) [Section titled “Financial-Grade Security and Conformance (FAPI 2.0)”](#financial-grade-security-and-conformance-fapi-20) **License: Standard (add-on), Advanced (add-on), Custom (add-on)** The [Financial-grade API (FAPI) 2.0 Security Profile](https://openid.net/specs/fapi-security-profile-2_0-final.html) is an API security profile based on OAuth 2.0 designed to protect APIs in high-value scenarios such as e-health and e-government. Duende IdentityServer implements the FAPI 2.0 best current practice features and includes a built-in conformance report that assesses your server and client configuration against OAuth 2.1 and FAPI 2.0 specifications. [Documentation ](/identityserver/tokens/fapi-2-0-specification/)Learn more about FAPI 2.0 compliance [Conformance Report ](/identityserver/diagnostics/conformance-report/)Assess your configuration against FAPI 2.0 ## Single Deployment [Section titled “Single Deployment”](#single-deployment) A single deployment acts as a single OpenID Connect / OAuth authority hosted at a single URL. It can consist of multiple physical or virtual nodes for load-balancing or fail-over purposes. ## Multiple Deployments [Section titled “Multiple Deployments”](#multiple-deployments) Can be either completely independent single deployments, or a single deployment that acts as multiple authorities. ## Multiple Authorities [Section titled “Multiple Authorities”](#multiple-authorities) A single logical deployment that acts as multiple logical token services on multiple URLs or host names (e.g. for branding, isolation or multi-tenancy reasons). ## Redistribution [Section titled “Redistribution”](#redistribution) Redistribution occurs when you bundle Duende IdentityServer as an integrated component of a product or service that you sell, lease, or provide to third parties. Redistribution typically applies to Independent Software Vendors (ISVs) who ship IdentityServer as part of a larger solution that customers host on their own local or cloud infrastructure. Each customer installation of IdentityServer is considered a separate redistribution. ## User Management - Licensed Users [Section titled “User Management - Licensed Users”](#user-management---licensed-users) The total of unique identity records stored in Duende User Management, identified by User Management user ID per billing period. ## FIDO2 [Section titled “FIDO2”](#fido2) FIDO2 is the FIDO Alliance’s umbrella standard for strong, passwordless authentication. It encompasses two specifications: **WebAuthn** (the browser/platform API) and **CTAP** (Client to Authenticator Protocol, which defines how authenticators such as hardware security keys communicate with a platform). FIDO2 credentials are based on public-key cryptography and are phishing-resistant by design. ## MFA (Multi-Factor Authentication) [Section titled “MFA (Multi-Factor Authentication)”](#mfa-multi-factor-authentication) Multi-Factor Authentication requires a user to present two or more independent verification factors before being granted access. Factors are typically categorized as something you *know* (e.g. a password or PIN), something you *have* (e.g. a TOTP authenticator app or hardware key), and something you *are* (e.g. a biometric). Requiring multiple factors significantly reduces the risk of account compromise from stolen credentials. ## OTP (One-Time Password) [Section titled “OTP (One-Time Password)”](#otp-one-time-password) A One-Time Password is a temporary, single-use code delivered out-of-band (typically via email or SMS) that authenticates a user without requiring a traditional password. Because each code is valid for only a short window and cannot be reused, OTPs provide a simple form of passwordless or second-factor authentication. ## Passkey [Section titled “Passkey”](#passkey) A passkey is a FIDO2 credential that replaces a traditional password. It is bound to a specific device (or synced across a user’s devices via a platform credential manager) and is unlocked locally using biometrics or a PIN. The private key never leaves the device, making passkeys resistant to phishing and server-side credential theft. ## Recovery Code [Section titled “Recovery Code”](#recovery-code) A recovery code is a one-time backup code generated at enrollment time and stored securely by the user. It can be used to regain account access when primary authenticators (such as a TOTP app or passkey device) are unavailable. Each code is valid for a single use only. ## Space (User Management) [Section titled “Space (User Management)”](#space-user-management) In Duende User Management, a *space* is the fundamental isolation unit. Each space has its own isolated user store, configuration, and authentication settings. This enables deployments where users, roles, and groups in one space are completely separated from those in another. A typical use case is supporting multiple tenants in a single deployment. ## Subject ID [Section titled “Subject ID”](#subject-id) A Subject ID (`sub`) is a stable, unique identifier assigned to a user within the system. It is analogous to, and typically maps directly to, the `sub` claim in OpenID Connect tokens. The Subject ID remains constant across sessions and should be used as the canonical reference to a user rather than mutable attributes such as username or email address. ## TOTP (Time-Based One-Time Password) [Section titled “TOTP (Time-Based One-Time Password)”](#totp-time-based-one-time-password) A Time-Based One-Time Password is a short-lived numeric code generated by an authenticator app (e.g. Google Authenticator, Microsoft Authenticator) according to [RFC 6238](https://www.rfc-editor.org/rfc/rfc6238). The code is derived from a shared secret and the current time, and is typically valid for 30 seconds. TOTP is widely used as a second factor in MFA flows. ## WebAuthn (Web Authentication) [Section titled “WebAuthn (Web Authentication)”](#webauthn-web-authentication) WebAuthn is the [W3C Web Authentication standard](https://www.w3.org/TR/webauthn/) that defines a browser API for creating and using public-key credentials. It is the web-facing component of FIDO2. Relying parties (web applications) use WebAuthn to register and authenticate users with device-bound or synced credentials (passkeys), hardware security keys, or platform authenticators, all without transmitting a password. ## Standard Developer Support [Section titled “Standard Developer Support”](#standard-developer-support) Online [developer community forum](https://github.com/DuendeSoftware/community/discussions) for Duende Software product issues and bugs. [Duende Developer Community ](https://github.com/DuendeSoftware/community/discussions)Learn more about the Duende Developer Community ## Priority / Premium Developer Support [Section titled “Priority / Premium Developer Support”](#priority--premium-developer-support) **License: Enterprise (legacy), Standard, Advanced, Custom** Helpdesk system with guaranteed response time for Duende Software product issues and bugs. [More Details ](https://duendesoftware.com/license/PrioritySupportLicense.pdf)Download the Priority Support License PDF ----- # Licensing > Details about Duende IdentityServer and BFF licensing requirements, editions, configuration options, and trial mode functionality. Duende products, except for our [open source tools](https://duendesoftware.com/products/opensource), require a license for production use. The [Duende Software website](https://duendesoftware.com/) provides an overview of different products and license editions. Licenses can be configured via a file system, programmatic startup, or external configuration services like Azure Key Vault, with trial mode available for development and testing. ## IdentityServer [Section titled “IdentityServer”](#identityserver) Duende IdentityServer requires a license for production use, with three editions available (Starter, Business, and Enterprise) that offer various features based on organizational needs. A [community edition](https://duendesoftware.com/products/communityedition/) is available as well. ### Editions [Section titled “Editions”](#editions) There are three license editions which include different [features](https://duendesoftware.com/products/features). #### Lite Edition [Section titled “Lite Edition”](#lite-edition) The Lite edition includes the core OIDC and OAuth protocol implementation. This is an economical option that is a good fit for organizations with basic needs. It’s also a great choice if you have an aging [IdentityServer4 implementation that needs to be updated](/identityserver/upgrades/identityserver4-to-duende-identityserver-v8/) and licensed. The Lite edition includes all the features that were part of IdentityServer4, along with support for the latest .NET releases, improved observability through [OpenTelemetry support](/identityserver/diagnostics/otel/), and years of bug fixes and enhancements. #### Standard Edition [Section titled “Standard Edition”](#standard-edition) The Standard edition adds additional features that go beyond the core protocol support included in the Starter edition. This is a popular license because it adds the most commonly needed tools and features outside a basic protocol implementation. Feature highlights include resource isolation, the OpenId Connect CIBA flow support, and server side sessions. #### Advanced Edition [Section titled “Advanced Edition”](#advanced-edition) Finally, the Advanced edition includes everything in the Standard edition and adds support for features that are typically used by enterprises with particularly complex architectures or that handle particularly sensitive data. Highlights include automatic key management, SAML, and priority developer support. This is the best option when you have a specific threat model or architectural need for these features. #### Starter Edition (legacy) [Section titled “Starter Edition (legacy)”](#starter-edition-legacy) The (legacy) Starter edition includes the core OIDC and OAuth protocol implementation. #### Business Edition (legacy) [Section titled “Business Edition (legacy)”](#business-edition-legacy) The (legacy) Business edition adds additional features that go beyond the core protocol support included in the Starter edition. Feature highlights include support for server side sessions and automatic signing key management. #### Enterprise Edition (legacy) [Section titled “Enterprise Edition (legacy)”](#enterprise-edition-legacy) The (legacy) Enterprise edition includes everything in the Business edition and adds resource isolation, the OpenId Connect CIBA flow, and dynamic federation. ### Redistribution [Section titled “Redistribution”](#redistribution) If you want to redistribute Duende IdentityServer to your customers as part of a product, you can use our [redistributable license](https://duendesoftware.com/products/identityserverredist). ### License Validation and Logging [Section titled “License Validation and Logging”](#license-validation-and-logging) All license validation happens at runtime and is self-contained. It does not leave the host, and there are no outbound network calls related to license validation. #### Startup Validation [Section titled “Startup Validation”](#startup-validation) IdentityServer loads and parses the license key at startup. If the key is present but invalid, an error is logged at that point. Beyond that, no further checks happen at startup. IdentityServer does not compare your configuration against the license at startup; that all happens at runtime, when features are actively used. #### Runtime Validation [Section titled “Runtime Validation”](#runtime-validation) IdentityServer never blocks or disables features at runtime based on licensing. A licensing oversight should never cause an outage. The runtime validator only logs; it does not prevent IdentityServer from functioning. The following features are validated at runtime. If you use one of them without the required license entitlement, IdentityServer logs a warning (rate-limited to once every 5 minutes per feature): * [Server Side Sessions](/identityserver/ui/server-side-sessions/) * [Demonstrating Proof-of-Possession (DPoP)](/identityserver/tokens/pop/) * [Resource Isolation](/identityserver/fundamentals/resources/isolation/) * [Client Initiated Backchannel Authentication (CIBA)](/identityserver/ui/ciba/) * [Dynamic Identity Providers](/identityserver/ui/login/dynamicproviders/) * [Automatic Key Management](/identityserver/fundamentals/key-management/) * [Financial-Grade Security and Conformance Report](/identityserver/diagnostics/conformance-report/) * [SAML IdP and SAML Service Provider](/identityserver/saml/) * [User Management](/identityserver/usermanagement/) For quantized limits like client count and issuer count, IdentityServer logs a warning when you exceed your licensed limit but stay within the grace threshold. If you exceed the grace threshold, it logs an error instead. An expired license also results in an error being logged. #### Trial Mode [Section titled “Trial Mode”](#trial-mode) Running IdentityServer without a license is perfectly fine for development, testing, and personal projects. There is no request limit and no automatic shutdown. All features remain available. The only difference you will notice is that IdentityServer logs a warning when you use a licensed feature without a license configured: ```text {FeatureName} is being used but no Duende license is configured. Please start a conversation with us: https://duende.link/l/contact ``` These warnings are rate-limited to once per five minutes per feature, so they won’t flood your logs. You can silence them entirely by configuring a license key, even in non-production environments. #### Redistribution [Section titled “Redistribution”](#redistribution-1) If you want to redistribute Duende IdentityServer to your customers as part of a product, you can use our [redistributable license](https://duendesoftware.com/products/identityserverredist). It can be cumbersome to deploy updated licenses in redistribution scenarios, especially if your deployment cycle does not coincide with the duration of your IdentityServer license. In that situation, update the license key at the next deployment to your redistribution customers. You are always responsible for ensuring your license is renewed. #### Log Severity [Section titled “Log Severity”](#log-severity) The severity of log messages depends on the nature of the message. All messages are rate-limited to once per 5 minutes per feature or SKU. | Type of message | Severity | | ------------------------------------------------- | ------------- | | Feature used, no license configured | Warning | | Feature used, not covered by license | Warning | | Quantized limit exceeded (within grace threshold) | Warning | | Quantized limit exceeded (beyond grace threshold) | Error | | License expired | Error | | License valid | Informational | ## BFF Security Framework [Section titled “BFF Security Framework”](#bff-security-framework) The Duende BFF Security Framework requires a license for production use, with two editions available (Starter and Enterprise) that offer various features based on organizational needs. ### Editions [Section titled “Editions”](#editions-1) BFF is a library designed to enhance the security of browser-based applications by moving authentication flows to the server side. The Duende BFF Security Framework requires a license for production use, and is available in two editions that [include different functionality](https://duendesoftware.com/products/bff) based on organizational needs. ### Redistribution [Section titled “Redistribution”](#redistribution-2) If you want to redistribute Duende BFF to your customers as part of a product, please [reach out to sales](https://duendesoftware.com/contact/sales). ### License Validation and Logging [Section titled “License Validation and Logging”](#license-validation-and-logging-1) The BFF license is validated during runtime. All license validation is self-contained and does not leave the host. There are no outbound network calls related to license validation. #### BFF v3.1+ Runtime Validation [Section titled “BFF v3.1+ Runtime Validation”](#bff-v31-runtime-validation) BFF v3.1 does not technically enforce the presence of a license key. At runtime, if no license is present, an error message will be logged. #### BFF v4 Runtime Validation [Section titled “BFF v4 Runtime Validation”](#bff-v4-runtime-validation) BFF v4 requires a valid license in production environments. When no license is present, the system operates in [trial mode](#bff-trial-mode) with a limitation of maximum of five sessions per host (not technically enforced) with any excess resulting in error logging. Trial mode is also enabled when the license could not be validated, for example when the signature validation fails. When an expired license is used, the system will continue to function with only a warning written to the logs, and not fall back to trial mode. #### BFF Trial Mode [Section titled “BFF Trial Mode”](#bff-trial-mode) Using BFF without a license is considered Trial Mode. When running in Trial Mode, you will see the following error logged on startup: ```text You do not have a valid license key for the Duende software. BFF will run in trial mode. This is allowed for development and testing scenarios. If you are running in production you are required to have a licensed version. Please start a conversation with us: https://duende.link/l/bff/contact ``` In Trial Mode, BFF will be limited to a maximum of five (5) sessions per host. Sessions exceeding the limit will cause the host to log an error for every consecutive authenticated session: ```text BFF is running in trial mode. The maximum number of allowed authenticated sessions (5) has been exceeded. See https://duende.link/l/bff/trial for more information. ``` The trial mode session limit is not distributed or shared across multiple nodes. ## License Key [Section titled “License Key”](#license-key) The license key can be configured in one of three ways: * Via a well-known file on the file system * Via `IConfiguration` (for example, `appsettings.json` or environment variables) * Programmatically in your startup code You can also use other configuration sources such as Azure Key Vault, by using the programmatic approach. We consider the license key to be private to your organization, but not necessarily a secret. If you’re using private source control that is scoped to your organization, storing your license key within it is acceptable. ### File System [Section titled “File System”](#file-system) Duende products like IdentityServer and the BFF Security Framework look for a file named `Duende_License.key` in the [ContentRootPath](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostenvironment.contentrootpath?#microsoft-extensions-hosting-ihostenvironment-contentrootpath) of your application. If present, the content of the file will be used as the license key. By default, `ContentRootPath` is the directory that contains the application’s `.csproj` file during development, and the application’s base directory in published deployments. Place the license key file there: ```text MyIdentityServer/ ├── Duende_License.key ← place license here ├── MyIdentityServer.csproj ├── Program.cs ├── appsettings.json └── ... ``` ### Configuration v8.0 [Section titled “Configuration ”v8.0](#configuration) IdentityServer can read the license key directly from `IConfiguration`, so you do not need to write any startup code. If `LicenseKey` is not set in your `AddIdentityServer` call, IdentityServer checks the following configuration keys in order, using the first non-empty value it finds: 1. `Duende:IdentityServer:LicenseKey` 2. `Duende:LicenseKey` Whitespace is trimmed, and empty or whitespace-only values are ignored. Add the license key to `appsettings.json` using the IdentityServer-specific key: appsettings.json ```json { "Duende": { "IdentityServer": { "LicenseKey": "eyJhbG..." } } } ``` Or use the shorter key: appsettings.json ```json { "Duende": { "LicenseKey": "eyJhbG..." } } ``` Because [`IConfiguration`](https://learn.microsoft.com/en-us/dotnet/core/extensions/configuration) supports many providers, you can also supply the key via environment variables (for example, `Duende__IdentityServer__LicenseKey` or `Duende__LicenseKey`), Azure App Configuration, Azure Key Vault, or any other configuration source. ### Startup [Section titled “Startup”](#startup) If you prefer to load the license key programmatically, you can do so in your startup code. This allows you to use the ASP.NET configuration system to load the license key from any [configuration provider](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-7.0#cp), including environment variables, `appsettings.json`, external configuration services such as Azure App Configuration, Azure Key Vault, etc. #### IdentityServer [Section titled “IdentityServer”](#identityserver-1) The `AddIdentityServer` method accepts a lambda expression to configure various options in your IdentityServer, including the `LicenseKey`. Set the value of this property to the content of the license key file. Program.cs ```csharp builder.Services.AddIdentityServer(options => { // the content of the license key file options.LicenseKey = "eyJhbG..."; }); ``` #### BFF Security Framework [Section titled “BFF Security Framework”](#bff-security-framework-1) The `AddBff` method accepts a lambda expression to configure various options in your BFF host, including the `LicenseKey`. Set the value of this property to the content of the license key file. Program.cs ```csharp builder.Services.AddBff(options => { // the content of the license key file options.LicenseKey = "eyJhbG..."; }); ``` ### Azure Key Vault [Section titled “Azure Key Vault”](#azure-key-vault) When deploying your application to Microsoft Azure, you can make use of [Azure Key Vault](https://azure.microsoft.com/products/key-vault/) to load the Duende license key at startup. Similarly to setting the license key programmatically, you can use the `AddIdentityServer` or `AddBff` method, and use the overload that accepts a lambda expression to configure the `LicenseKey` property. Program.cs ```csharp var keyVaultUrl = new Uri("https://.vault.azure.net/"); var secretClient = new Azure.Security.KeyVault.Secrets.SecretClient( keyVaultUrl, new Azure.Identity.DefaultAzureCredential() ); KeyVaultSecret licenseKeySecret = secretClient.GetSecret(""); var licenseKey = licenseKeySecret.Value; // Inject the secret (license key) into the IdentityServer configuration builder.Services.AddIdentityServer(options => { options.LicenseKey = licenseKey; }); ``` If you are using [Azure App Configuration](https://azure.microsoft.com/products/app-configuration/), you can use a similar approach to load the license key into your application host. ----- # Logging Fundamentals > General guidance on configuring logging for Duende Software products using Microsoft.Extensions.Logging and Serilog. All Duende Software products (IdentityServer, Backend for Frontend (BFF), Access Token Management, etc.) use the standard logging facilities provided by ASP.NET Core (`Microsoft.Extensions.Logging`). This means they integrate seamlessly with whatever logging provider you choose for your application. This guide provides general instructions for setting up logging that apply to all our products. ## Log Levels [Section titled “Log Levels”](#log-levels) We adhere to the standard Microsoft guidelines for log levels. Understanding these levels helps you configure the appropriate verbosity for your environment. * **`Trace`** * **Usage:** Extremely detailed information for troubleshooting complex issues. * **Production:** **Do not enable** in production unless specifically instructed for diagnostics. May contain sensitive data (e.g., token hashes, PII). * **`Debug`** * **Usage:** Internal flow details, useful for understanding *why* a decision was made (e.g., policy evaluation, token validation steps). * **Production:** Generally disabled in production, but safe to enable temporarily for deeper investigation. * **`Information`** * **Usage:** High-level events tracking the general flow (e.g., “Request started”, “Token issued”). * **Production:** Often the default level for production. * **`Warning`** * **Usage:** Unexpected events that didn’t stop the application but might require investigation (e.g., “Invalid client configuration detected”). * **`Error`** * **Usage:** Exceptions and errors that cannot be handled gracefully. * **`Critical`** * **Usage:** Failures that require immediate attention (e.g., “Signing key not found”). ## Setup for Microsoft.Extensions.Logging [Section titled “Setup for Microsoft.Extensions.Logging”](#setup-for-microsoftextensionslogging) This is the default logging provider for ASP.NET Core. If you haven’t configured a third-party logger, this is what you are using. You can configure log levels in your `appsettings.json` file. To get detailed logs from Duende products, you often want to set the `Duende` namespace (or specific sub-namespaces) to `Debug`. appsettings.json ```json { "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information", // Enable Debug logs for all Duende products "Duende": "Debug" } } } ``` ## Setup for Serilog [Section titled “Setup for Serilog”](#setup-for-serilog) [Serilog](https://serilog.net) is a popular structured logging library for .NET. We highly recommend it for its flexibility and rich sink ecosystem (Console, File, Seq, Elasticsearch, etc.). ### 1. Installation [Section titled “1. Installation”](#1-installation) Install the necessary packages: ```bash dotnet add package Serilog.AspNetCore ``` ### 2. Configuration In `Program.cs` [Section titled “2. Configuration In Program.cs”](#2-configuration-in-programcs) Configure Serilog early in your application startup to capture all logs, including startup errors. Program.cs ```csharp using Serilog; var builder = WebApplication.CreateBuilder(args); // Configure Serilog builder.Host.UseSerilog((ctx, lc) => lc .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}") .Enrich.FromLogContext() .ReadFrom.Configuration(ctx.Configuration)); var app = builder.Build(); app.UseSerilogRequestLogging(); // Optional: cleaner HTTP request logging // ... rest of your pipeline ``` ### 3. Configuration In `appsettings.json` [Section titled “3. Configuration In appsettings.json”](#3-configuration-in-appsettingsjson) You can then control log levels via `appsettings.json`. This approach allows you to change log levels without recompiling your code. ```json { "Serilog": { "MinimumLevel": { "Default": "Information", "Override": { "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information", "System": "Warning", // Enable detailed logging for Duende products "Duende": "Debug" } } } } ``` ## Troubleshooting Specific Products and Components [Section titled “Troubleshooting Specific Products and Components”](#troubleshooting-specific-products-and-components) If you are debugging a specific component, you can target its namespace to reduce noise. | Product | Namespace | | --------------------------- | ------------------------------ | | **IdentityServer** | `Duende.IdentityServer` | | **BFF** | `Duende.Bff` | | **User Management** | `Duende.UserManagement` | | **Access Token Management** | `Duende.AccessTokenManagement` | Example `appsettings.json` for debugging only BFF interactions: ```json "Duende.Bff": "Debug", "Duende.IdentityServer": "Information" ``` ----- # Security Best Practices > A comprehensive guide to security practices and procedures used in Duende Software development lifecycle This document describes how the integrity of software produced by Duende Software is maintained during the software development life cycle. ## Data processing [Section titled “Data processing”](#data-processing) Our products are off-the shelf downloadable developer components. They are not managed services or SaaS - nor do we store, have access to, or process any of our customers’ data or their customers’ data. ## Systems Access [Section titled “Systems Access”](#systems-access) * Multiple systems are used in the development life cycle, including GitHub, NuGet, and Microsoft Azure Key Vault. * Multi-factor authentication is required for all services mentioned above. * Only a limited subset of Duende Software employees act as administrators for each system. ## Software Development [Section titled “Software Development”](#software-development) * All code is stored in [GitHub](https://github.com/duendesoftware). * Any code added to a project must be added via pull request. * At least one other staff member must review a pull request before it can be merged to a release branch. * Static code security analysis is performed for every check-in (using GitHub [CodeQL](https://codeql.github.com/)). ## Testing [Section titled “Testing”](#testing) * Automated test suites are run on code in every pull request branch. * Pull requests cannot be merged if the automated test suite fails. ## Deployment [Section titled “Deployment”](#deployment) * Merging a pull request does not immediately release new features to users, this requires an additional release step. * All compiled software packages with associated source are available as GitHub releases. * Compiled software libraries (such as Duende IdentityServer) are published to [NuGet](https://www.nuget.org/). * Packages must be pushed to NuGet by a Duende Software staff member only after additional validation by the staff member. * All NuGet packages are signed with a code signing certificate * The private key (RSA 4096 bits) is stored in Azure Key Vault. * The private key never leaves Key Vault and the signature process is performed by Key Vault. * NuGet will validate the package signature with Duende’s public key to verify they were legitimately built by Duende Software and have not been compromised or tampered with. * NuGet client tooling can be configured to accept signed packages only. * Once on NuGet, the package is available for end users to update their own solutions. * End users still must take explicit action to upgrade after reviewing the package’s release notes. ## Vulnerability Management Process [Section titled “Vulnerability Management Process”](#vulnerability-management-process) * Potential security vulnerabilities can be responsibly disclosed via our [contact form](https://duendesoftware.com/contact/general). * We guarantee to reply within two US business days. * All licenses include a security notification service. * Whenever a medium severity or higher security vulnerability has been confirmed and fixed, customers will get a private update prior to public release. * We will publish an official advisory ## Dependencies [Section titled “Dependencies”](#dependencies) IdentityServer has two dependencies: * [Microsoft .NET](https://dot.net) * [IdentityModel](https://github.com/IdentityModel) * maintained by Duende Software using the same principles as outlined above ## Certification [Section titled “Certification”](#certification) Duende IdentityServer is a [certified](https://openid.net/certification/) implementation of OpenID Connect. ## Package Signing [Section titled “Package Signing”](#package-signing) NuGet packages published by Duende are cryptographically signed to ensure their authenticity and integrity. Our certificate is signed by DigiCert, which is a widely trusted certificate authority and installed by default in most environments. This means that in many circumstances, the NuGet tools can validate our packages’ signatures automatically. However, some environments (notably the dotnet sdk docker image which is sometimes used in build pipelines) do not trust the certificate. In that case, it might be necessary to add the root certificate to NuGet’s code signing certificate bundle. * Packages released after January 1, 2025 (IdentityServer 7.1+): Use DigiCert’s [root certificate](https://cacerts.digicert.com/DigiCertTrustedG4CodeSigningRSA4096SHA2562021CA1.crt.pem) ( PEM). * Packages released before January 1, 2025: Use Sectigo’s [root certificate](http://crt.sectigo.com/SectigoPublicCodeSigningRootR46.p7c) (P7C). #### Trusting The DigiCert Certificate [Section titled “Trusting The DigiCert Certificate”](#trusting-the-digicert-certificate) Here is an example of how to configure NuGet to trust the DigiCert root CA on the dotnet sdk docker image. This applies for Duende packages released *`after`* January 1, 2025, such as IdentityServer 7.1 and newer versions. Note the dotnet sdk docker image already includes the tools used in this section. If you are using another container image, make sure the following tools are available in the image: `wget`, `openssl`, `cat`, and the .NET SDK. First, get the DigiCert certificate: Terminal ```bash wget https://cacerts.digicert.com/DigiCertTrustedG4CodeSigningRSA4096SHA2562021CA1.crt.pem ``` Next, you validate that the thumbprint of the certificate is correct. Bootstrapping trust in a certificate chain can be challenging. Fortunately, most desktop environments already trust this certificate, so you can compare the downloaded certificate’s thumbprint to the thumbprint of the certificate on a machine that already trusts it. You should verify this independently, but for your convenience, the thumbprint is `8F:B2:8D:D3:CF:FA:5D:28:6E:7C:71:8A:A9:07:CB:4F:9B:17:67:C2`. You can check the thumbprint of the downloaded certificate with openssl: Terminal ```bash openssl x509 -in DigiCertTrustedG4CodeSigningRSA4096SHA2562021CA1.crt.pem -fingerprint -sha1 -noout ``` Then append that PEM to the certificate bundle at `/usr/share/dotnet/sdk/9.0.102/trustedroots/codesignctl.pem`: Terminal ```bash cat DigiCertTrustedG4CodeSigningRSA4096SHA2562021CA1.crt.pem >> /usr/share/dotnet/sdk/9.0.102/trustedroots/codesignctl.pem ``` After that, NuGet packages signed by Duende can be successfully verified, even if they are not distributed by NuGet.org: Terminal ```bash dotnet nuget verify Duende.IdentityServer.7.1.x.nupkg ``` #### Trusting The Sectigo Certificate [Section titled “Trusting The Sectigo Certificate”](#trusting-the-sectigo-certificate) Here is an example of how to configure NuGet to trust the Sectigo root CA on the dotnet sdk docker image for Duende packages released *`before`* January 1, 2025 Note the dotnet sdk docker image already includes the tools used in this section. If you are using another container image, make sure the following tools are available in the image: `wget`, `openssl`, `cat`, and the .NET SDK. First, get the Sectigo certificate and convert it to PEM format: Terminal ```bash wget http://crt.sectigo.com/SectigoPublicCodeSigningRootR46.p7c openssl pkcs7 -inform DER -outform PEM -in SectigoPublicCodeSigningRootR46.p7c -print_certs -out sectigo.pem ``` Next, you should validate that the thumbprint of the certificate is correct. Bootstrapping trust in a certificate chain can be challenging. Fortunately, most desktop environments already trust this certificate, so you can compare the downloaded certificate’s thumbprint to the thumbprint of the certificate on a machine that already trusts it. You should verify this independently, but for your convenience, the thumbprint is `CC:BB:F9:E1:48:5A:F6:3C:E4:7A:BF:8E:9E:64:8C:25:04:FC:31:9D`. You can check the thumbprint of the downloaded certificate with openssl: Terminal ```bash openssl x509 -in sectigo.pem -fingerprint -sha1 -noout ``` Then append that PEM to the certificate bundle at `/usr/share/dotnet/sdk/8.0.303/trustedroots/codesignctl.pem`: Terminal ```bash cat sectigo.pem >> /usr/share/dotnet/sdk/8.0.303/trustedroots/codesignctl.pem ``` After that, NuGet packages signed by Duende can be successfully verified, even if they are not distributed by NuGet.org: Terminal ```bash dotnet nuget verify Duende.IdentityServer.7.0.x.nupkg ``` ----- # Support & Issues > Comprehensive guide for accessing source code, reporting issues, and obtaining support for Duende products. This document provides information on accessing Duende’s source code, issue tracking, and community forums for support and discussions. It also outlines support policies, including priority support for enterprise users, and the procedure to report security vulnerabilities. ## Source Code [Section titled “Source Code”](#source-code) You can find all source code for Duende Products and its supporting repos in our [organization](https://github.com/duendesoftware). [Source Code ](https://github.com/duendesoftware)Learn more about Duende's codebase ## Issue Tracker [Section titled “Issue Tracker”](#issue-tracker) Join our [developer community forum](https://github.com/DuendeSoftware/community/discussions) to ask questions and discuss potential bugs. Follow our [product releases](https://github.com/DuendeSoftware/products/releases) and get notified of new releases as soon as they are published. [Release Notes ](https://github.com/DuendeSoftware/products/releases)See what's new in the latest releases ## Support [Section titled “Support”](#support) Duende Software offers three support tiers designed to meet organizations at their stage of growth and operational complexity. Each tier builds on the last, providing a clear path from community-driven help to dedicated, high-touch engagement for mission-critical deployments. | Support Tier Comparison | | | | | | ------------------------------------------- | :--------------------------------------------------: | :-------------: | :-------------: | :--------------------------: | | **Support Level** | **Community** | **Priority** | **Priority** | **Premium** | | **Applicable Licenses** | Community, Lite, Starter (legacy), Business (legacy) | Standard | Advanced | Custom, Enterprise+ (legacy) | | **Support Channel** | Public GitHub forum | Dedicated email | Dedicated email | Dedicated email + TAM | | **Response SLA** | No SLA | 2 business days | 2 business days | 1 business day | | **Escalation Calls** | – | 2 per year | 4 per year | 4 per year | | **Dedicated TAM** | – | – | – | Named TAM | | **Proactive Check-ins** | – | – | – | ✓ | | **Security Notification Service** | – | – | ✓ | ✓ | | **Feature Requests** | Public GitHub forum | Email channel | Email channel | Via TAM | | **Support for Duende open-source packages** | – | – | – | ✓ | ### Community Support [Section titled “Community Support”](#community-support) **License: Free, Community, Lite, Starter (legacy), Business (legacy)** Community Support connects users with a network of fellow developers and Duende team members through our public discussion forums. Whether you’re troubleshooting an integration, exploring a new feature, or looking to share knowledge, the community is an active and knowledgeable resource. To get help, start a discussion [on the developer community forum](https://github.com/DuendeSoftware/community/discussions). | Community Support Overview | | | :------------------------- | :------------------------------------------------------------------------------------------ | | Support Channel | [Public developer community forum](https://github.com/DuendeSoftware/community/discussions) | | SLA | None | [Get support on GitHub from the Duende community ](https://github.com/DuendeSoftware/community/discussions)Duende Developer Community Forum ### Priority Support [Section titled “Priority Support”](#priority-support) **License: Standard, Advanced, Enterprise (legacy)** [Priority Support](https://duendesoftware.com/license/PrioritySupportLicense.pdf) provides direct access to the Duende team through a dedicated email channel, with guaranteed response times tied to your license tier. For complex issues requiring deeper investigation, escalation calls are available – a focused video session where our team works alongside yours to diagnose and resolve product issues. | Priority Support Overview | | | | :------------------------ | :--------------------------- | :---------------------------- | | **License** | Standard | Advanced, Enterprise (legacy) | | **Support Channel** | Dedicated email channel | Dedicated email channel | | **Response SLA** | 2 business day response | 2 business day response | | **Escalation Calls** | Up to 2 escalations per year | Up to 4 escalations per year | **Note:** Escalation calls are development-focused pairing sessions, not ongoing operational support or on-call coverage. Response times are measured against standard US business days. Observed holidays and other events are excluded. [Priority Support PDF ](https://duendesoftware.com/license/PrioritySupportLicense.pdf)Learn more about Priority Support ### Premium Support [Section titled “Premium Support”](#premium-support) **License: Standard, Advanced, Custom, Enterprise (legacy)** Premium Support is designed for organizations with mission-critical or complex identity infrastructure where downtime presents significant business risk. It provides the benefits of Priority Support alongside a dedicated, proactive, and high-touch engagement model. This tier offers enhanced strategic continuity and the quickest guaranteed response times. **Dedicated Technical Account Manager (TAM):** Your TAM serves as a named point of contact who develops deep familiarity with your implementation, architecture, and business needs. Rather than re-explaining your environment with every interaction, your TAM brings continuity and context to every conversation, whether you’re onboarding, upgrading, or troubleshooting. **1 Business Day SLA Response:** Issues are acknowledged within 1 business day. This ensures a guaranteed response window regardless of when a problem surfaces, which is vital for organizations where swift acknowledgement is critical. **Priority Escalation:** Premium customers receive elevated priority for escalation calls, ensuring video pairing sessions are scheduled with urgency rather than standard queue prioritization. **Proactive Engagement:** Your TAM will periodically check in to review upcoming releases, flag breaking changes relevant to your configuration, and ensure you’re positioned to take advantage of new capabilities before they become blockers. | Premium Support Overview | | | :------------------------------------------ | :---------------------------------------------------------- | | **Support Channel** | Dedicated email channel + Named Technical Account Manager | | **SLA** | 1 business day response | | **Escalation Calls** | Up to 4 per year, priority scheduling | | **Account Manager** | Named TAM with deep familiarity of your environment | | **Proactive Engagement** | Periodic check-ins, release reviews, breaking change alerts | | **Support for Duende open-source packages** | Included | ## Supported Versions [Section titled “Supported Versions”](#supported-versions) Duende differentiates between two categories of NuGet packages: **Product packages** and **Component packages**. **Product packages** are the primary, user-facing products: IdentityServer and BFF. The following support rules apply: * **Major versions** are supported until the end of the associated .NET SDK lifecycle. The “associated” .NET version is determined by the target framework(s) supported at the time of release. A package can target multiple .NET versions. For example, if a release ships with support for both .NET 8 and .NET 10, it is associated with both, and support continues until the last associated .NET version reaches end-of-life. * **Minor versions** receive security fixes until the end of the associated .NET SDK lifecycle. * Product packages do **not** follow Semantic Versioning (SemVer); minor releases may contain breaking API changes. Internal namespaces Types in `Internal` namespaces, even when exposed as `public`, are intended for internal use by Duende. No bugfixes, security fixes or product support is provided for these types, and these types may change between versions. **Component packages** are transitive dependencies and supporting libraries, such as User Management, Storage, Jobs, and similar packages. The following support rules apply: * The **current major and minor** versions are supported for both bug fixes and security fixes. * Component packages follow Semantic Versioning (SemVer). The following sections track release and end of support dates for Duende product packages. ### Duende IdentityServer [Section titled “Duende IdentityServer”](#duende-identityserver) ### Duende Backend For Frontend (BFF) [Section titled “Duende Backend For Frontend (BFF)”](#duende-backend-for-frontend-bff) ## Reporting a security vulnerability [Section titled “Reporting a security vulnerability”](#reporting-a-security-vulnerability) [Security issues and bugs should be reported privately here](https://duendesoftware.com/contact/general). You should receive a response within **two business days**. [Report a security vulnerability ](https://duendesoftware.com/contact/general)privately report a security vulnerability