Table of Contents

Interface IRefreshTokenService

Namespace
Fdyay.IdentityServer.Services.Tokens
Assembly
Fdyay.IdentityServer.Core.dll

Creates, validates, and rotates refresh tokens according to client policy.

public interface IRefreshTokenService

Methods

CreateRefreshTokenAsync(ClaimsPrincipal, Client, IEnumerable<string>, bool, string?, IEnumerable<string>?, string?, Token?, string?, string?, CancellationToken)

Issues a refresh token, bound to a DPoP key when the client proved it holds one.

Task<string> CreateRefreshTokenAsync(ClaimsPrincipal subject, Client client, IEnumerable<string> scopes, bool isOpenId, string? dpopKeyThumbprint = null, IEnumerable<string>? authorizedResourceIndicators = null, string? sessionId = null, Token? accessToken = null, string? requestedResourceIndicator = null, string? description = null, CancellationToken cancellationToken = default)

Parameters

subject ClaimsPrincipal

The user the token is issued for; its subject id and every claim are stored with it.

client Client

The client the token is issued to; only that client may redeem it, and its lifetime policy applies.

scopes IEnumerable<string>

The scopes granted, which every later token request on this refresh token is held to.

isOpenId bool

Whether the grant included openid, so a refresh can issue an identity token.

dpopKeyThumbprint string

The JWK thumbprint of the DPoP key the client proved, binding the token to it; null when unbound.

authorizedResourceIndicators IEnumerable<string>

The APIs the authorization named by resource indicator (RFC 8707), which every later token request on this refresh token is held to. Null or empty for a grant whose authorization named none.

sessionId string

The user's session id (sid), so ending the session can find and revoke the token.

accessToken Token

The access token issued alongside, stored with the refresh token for the resource it was issued for.

requestedResourceIndicator string

The resource indicator the access token was requested for, if the request named one.

description string

What the user or client called this grant, shown in the user's grant list.

cancellationToken CancellationToken

Cancels the store's write.

Returns

Task<string>

The handle the client presents to redeem the token.

RotateAsync(string, RefreshToken, Client, CancellationToken)

Rotates the refresh token per the client's usage policy, returning the handle to return.

Task<string> RotateAsync(string handle, RefreshToken token, Client client, CancellationToken cancellationToken = default)

Parameters

handle string
token RefreshToken
client Client
cancellationToken CancellationToken

Returns

Task<string>

Remarks

Under OneTimeOnly the predecessor is consumed rather than deleted, so a later presentation of it is recognisable as a replay — unless PersistentGrantOptions.DeleteOneTimeOnlyRefreshTokensOnUse is on. Under ReUse nothing is consumed and the same handle comes back: a client on that policy is meant to present it repeatedly, and treating the second use as a replay would revoke a working session. Under either, a Sliding token's lifetime is extended from its use, never past AbsoluteRefreshTokenLifetime when that is above zero — the reused one in place, under its handle (0.174.0). A token TryRedeemAsync(string, RefreshToken, Client, CancellationToken) has taken is already consumed, or deleted, and is not consumed again.

TryRedeemAsync(string, RefreshToken, Client, CancellationToken)

Takes a validated refresh token for the one request about to be answered with it: false when another request took it first, and the request is then refused as a replay would be.

Task<bool> TryRedeemAsync(string handle, RefreshToken token, Client client, CancellationToken cancellationToken = default)

Parameters

handle string

The handle the client presented.

token RefreshToken

The token ValidateRefreshTokenAsync(string, Client, CancellationToken) returned for it.

client Client

The client redeeming it.

cancellationToken CancellationToken

Cancels the store's write.

Returns

Task<bool>

True when this request may be answered with tokens; false when it must be refused.

Remarks

Ours (security), 0.176.0. Validating a token reads it; until this, rotating it consumed it in a second step, so two requests presenting one OneTimeOnly token at the same moment both read it unconsumed and were both answered with a successor — two live lineages from one token, and no replay detected. The token endpoint asks this once every check on the request has passed and before any token is issued. Duende reads and consumes in two steps, as this did. This default answers true, so a refresh token service of a host's own behaves as before.

ValidateRefreshTokenAsync(string, Client, CancellationToken)

The token behind a handle, or null if it cannot be used.

Task<RefreshToken?> ValidateRefreshTokenAsync(string handle, Client client, CancellationToken cancellationToken = default)

Parameters

handle string
client Client
cancellationToken CancellationToken

Returns

Task<RefreshToken>

Remarks

Null covers absent, expired, issued to another client, and replayed. The caller answers all four the same way — invalid_grant — and deliberately learns no more than that: which one it was tells an attacker whether a handle was ever real, and the client cannot act differently on any of them. A replay is not only refused here; it revokes the lineage it belongs to. A consumed token presented within PersistentGrantOptions.ConsumedRefreshTokenGracePeriod of its consumption is not a replay — off by default.