Logging
Duende Access Token Management uses the standard logging facilities provided by ASP.NET Core. You generally do not need to perform any extra configuration, as it will use the logging provider you have already configured for your application.
For log level definitions, environment guidance, and actionable next steps for each level, see the Logging Fundamentals guide.
Configuration
Section titled “Configuration”Logs are written under the Duende.AccessTokenManagement category. To control log output for Access Token Management specifically, set that namespace in your appsettings.json:
{ "Logging": { "LogLevel": { "Default": "Information", "Duende.AccessTokenManagement": "Debug" } }}What Gets Logged
Section titled “What Gets Logged”Access Token Management emits structured log messages across several functional areas. Each message includes contextual parameters (client ID, URL, error details, etc.) for effective filtering and troubleshooting.
User Token Acquisition
Section titled “User Token Acquisition”| Level | Message | Description |
|---|---|---|
| Warning | Cannot authenticate scheme: {Scheme} to acquire user access token | Authentication failed for the specified scheme |
| Warning | Authentication result properties are null for scheme: {Scheme} after authentication | Successful authentication but no token properties returned |
| Warning | Failed to get a UserToken because no tokens found in cookie properties | SaveTokens must be enabled for automatic token refresh |
| Debug | Starting user token acquisition | Beginning the user token retrieval process |
| Warning | Cannot retrieve token: No active user | No authenticated user context available |
| Warning | Cannot retrieve token: No token data found in user token store for user {User} | User exists but has no stored tokens |
Token Refresh
Section titled “Token Refresh”| Level | Message | Description |
|---|---|---|
| Debug | No refresh token found in user token store for user {User} / resource {Resource}. Returning current access token | No refresh token available; returning existing access token |
| Debug | No access token found in user token store for user {User} / resource {Resource}. Trying to refresh | Missing access token; attempting refresh |
| Debug | Token for user {User} will be refreshed. Expiration: {Expiration}, ForceRenewal: {ForceRenewal} | Token refresh triggered by expiration or explicit force |
| Trace | Refreshing access token using refresh token: hash={TokenHash} | Executing refresh token grant (token hashed for security) |
| Debug | Sending Refresh token request to: {Url} | HTTP request to token endpoint |
| Debug | Returning refreshed token for user: {User} | Refresh succeeded |
| Debug | Returning current token for user: {User} | Using cached token (still valid) |
| Warning | Error refreshing access token. Error = {Error}, Description: {ErrorDescription} | Refresh failed with OAuth error |
| Information | Access Token of type {TokenType} refreshed with expiration: {Expiration} | Successful refresh with new expiration |
Token Revocation
Section titled “Token Revocation”| Level | Message | Description |
|---|---|---|
| Trace | Revoking refresh token: hash={TokenHash} | Starting revocation (token hashed) |
| Debug | Sending Token revocation request to: {Url} | HTTP request to revocation endpoint |
| Warning | Error revoking refresh token. Error = {Error} | Revocation failed |
Client Credentials
Section titled “Client Credentials”| Level | Message | Description |
|---|---|---|
| Debug | Requesting client credentials access token at endpoint: {Url} | Starting client credentials grant |
| Information | Client Credentials token of type {TokenType} for Client: {ClientName} retrieved with expiration {Expiration} | Token successfully obtained |
| Warning | Error requesting access token for client {ClientName}. Error = {Error}, Description: {ErrorDescription} | Token request failed |
| Debug | Caching access token for client: {ClientName}. Expiration: {Expiration} | Storing token in cache |
| Debug | Cache hit for obtaining access token for client: {ClientName} | Using cached token |
| Debug | Cache miss while retrieving access token for client: {ClientName} | No cached token; fetching new one |
| Warning | Will not cache token result with error for {ClientName}. Error = {Error}, Description: {ErrorDescription} | Skipping cache for failed token |
| Warning | An exception has occurred while reading ClientCredentialsToken value from the cache for client {ClientName} | Cache read error; falling back to fetch |
| Warning | Error trying to set token in cache for client {ClientName} | Cache write failed |
| Warning | Error parsing cached access token for client {ClientName} | Cached value was corrupted |
| Warning | Failed to obtain token from cache for client {ClientName} using cacheKey {CacheKey}. Will obtain new token | Cache retrieval failed; fetching new token |
Request Handler
Section titled “Request Handler”These messages are emitted by AccessTokenRequestHandler when sending HTTP requests with tokens:
| Level | Message | Description |
|---|---|---|
| Debug | Sending Access token of type {TokenType} to endpoint: {Url} | Attaching token to outgoing request |
| Warning | Failed to obtain an access token while sending the request. Error: {Error}, ErrorDescription {ErrorDescription} | Could not get token; request sent without authentication |
| Warning | While sending a request, received UnAuthorized after acquiring a new access token | Fresh token was rejected by the resource server |
| Debug | Token not accepted while sending request. Retrying with new access token | 401 response triggered token refresh and retry |
DPoP (Demonstrating Proof-of-Possession)
Section titled “DPoP (Demonstrating Proof-of-Possession)”| Level | Message | Description |
|---|---|---|
| Debug | Creating DPoP proof token for token request | Generating DPoP proof for token endpoint |
| Debug | Sending DPoP proof token in request to endpoint: {Url} | Attaching DPoP proof to request |
| Debug | Failed to create DPoP proof token for request to endpoint: {Url} | DPoP proof generation failed; falling back to Bearer |
| Debug | The authorization server has supplied a new nonce on a successful response | Server-provided nonce stored for future requests |
| Debug | DPoP nonce error: {Error}. Retrying using new nonce | Retrying with server-provided nonce |
| Debug | DPoP error {Error} during token refresh. Retrying with server nonce | Nonce error during refresh; retrying |
| Warning | Failed to get DPoP Nonce because server didn’t respond with ok. StatusCode was: {StatusCode} | Nonce request failed |
| Trace | Cache hit for DPoP nonce for URL: {Url}, method: {Method} | Using cached nonce |
| Trace | Writing DPoP nonce to Cache for URL: {Url}, method: {Method}. Expiration: {Expiration} | Storing nonce in cache |
| Trace | Cache miss for DPoP nonce for URL: {Url}, method: {Method} | No cached nonce available |
| Warning | Failed to parse the cached Nonce {Value} for URL: {Url}, method: {Method}. Error: {Error} | Cached nonce was invalid |
Key Parsing
Section titled “Key Parsing”| Level | Message | Description |
|---|---|---|
| Warning | Failed to parse JsonWebKey | JWK parsing failed |
| Warning | Failed to create thumbprint from JSON web key | Could not compute key thumbprint |
OpenTelemetry Integration
Section titled “OpenTelemetry Integration”Access Token Management supports OpenTelemetry for distributed tracing and metrics collection.
Tracing
Section titled “Tracing”The library emits traces under the activity source Duende.AccessTokenManagement. Add this to your OpenTelemetry configuration:
builder.Services.AddOpenTelemetry() .WithTracing(tracing => tracing .AddSource("Duende.AccessTokenManagement") // ... other sources );Activity spans:
| Name | Description |
|---|---|
Duende.AccessTokenManagement.AcquiringToken | Wraps the entire token acquisition operation |
Metrics
Section titled “Metrics”Metrics are exposed under the meter Duende.AccessTokenManagement:
builder.Services.AddOpenTelemetry() .WithMetrics(metrics => metrics .AddMeter("Duende.AccessTokenManagement") // ... other meters );Available counters:
| Counter | Description | Tags |
|---|---|---|
access_token_used | Number of times an access token was used | ClientId, TokenType |
token_retrieved | Number of times a token was retrieved from the token endpoint | ClientId, TokenType |
token_retrieval_failed | Number of times token retrieval failed | ClientId, TokenType, Error |
token_send_retry | Number of times a token was rejected and retried | ClientId |
dpop_nonce_error_retry | Number of times a DPoP nonce error triggered a retry | ClientId, Error |
The TokenType tag distinguishes between ClientCredentials and User token flows.