Persisted Grant Store
The IPersistedGrantStore
interface is the contract for a service that stores,
retrieves, and deletes persisted grants. A grant is a somewhat abstract
concept that is used in various protocol flows and represents that a resource
owner has given authorization of some kind. Grants that require server side
state in IdentityServer are the persisted grants stored by the
IPersistedGrantStore
.
The IPersistedGrantStore
is abstracted to allow for storage of several grant
types, including authorization codes, refresh tokens, user consent, and
reference tokens. Some specialized grant types, including device flow and CIBA,
use their own specialized stores instead.
IdentityServer includes two implementations of the IPersistedGrantStore
. The
InMemoryPersistedGrantStore
unsurprisingly persists grants in memory and is
intended for demos, tests, and other situations where persistent storage is not
actually necessary. In contrast, the
Duende.IdentityServer.EntityFramework.Stores.PersistedGrantStore
durably
persists grants to a database using EntityFramework, and can be used with any
database with an EF provider.
You can also provide your own implementation of the IPersistedGrantStore
. This
allows for complete control of the data access code so that you can support
other data stores that lack an EF provider, and so that you can optimize the
data access for your environment and usage.
Duende.IdentityServer.Stores.IPersistedGrantStore
Section titled “Duende.IdentityServer.Stores.IPersistedGrantStore”Members
Section titled “Members”name | description |
---|---|
Task StoreAsync(PersistedGrant grant); | Stores a grant. |
Task | Retrieves a grant by its key. |
Task<IEnumerable | Retrieves all grants that fulfill the conditions of a filter. |
Task RemoveAsync(string key); | Removes a grant by key. |
Task RemoveAllAsync(PersistedGrantFilter filter); | Removes all grants that fulfill the conditions of a filter. |
Duende.IdentityServer.Models.PersistedGrant
Section titled “Duende.IdentityServer.Models.PersistedGrant”Members
Section titled “Members”name | description |
---|---|
string Key | A string that uniquely identifies the grant. |
string Type | A string that specifies the type of grant. The possible values are constants in the PersistedGrantTypes class (see below). |
string SubjectId | The identifier of the subject that granted authorization. |
string SessionId | The identifier of the session where the grant was made, if applicable. |
string ClientId | The identifier of the client that was granted authorization. |
string Description | The description the user assigned to the device being authorized. |
DateTime CreationTime | The time that the grant expires. |
DateTime? Expiration | The time that the grant expires. |
DateTime? ConsumedTime | The time that the grant was consumed. |
string Data | A serialized and data protected representation of the grant. |
Key Property
Section titled “Key Property”The Key
property contains a SHA256 hash of the value used to refer to
individual grants. For authorization codes, refresh tokens, and reference
tokens, the stored Key
hashes the actual value sent to the client as part of
the protocol flow. For example, refresh token records use a hash of the actual
refresh token parameter sent to the client as their Key
. In contrast, user
consent is not identified by a single protocol parameter. Instead, the Key
value for user consent records comes from a hash of a combination of subject id
and client id. In all cases, the value that is hashed to compute the Key
also
includes the grant type.
Beginning in v6.0
, the hashes that IdentityServer passes to the
IPersistedGrantStore
to use as Key
values are formatted as hex values. In
earlier versions, the Keys
were base-64 encoded. That occasionally caused
database collation issues in case-insensitive databases, which prompted the
change to hex encoding. To facilitate migration, IdentityServer adds a version
suffix (“-1”) to indicate that the newer hex encoding should be used during
hashing. For example, the refresh token parameter
“27931A10FBCA75583C5576DAFB5DBDF0A9BCA8D6BD38B7CF142C47D6E44ED24D-1” ends in the
“-1” suffix, so when IdentityServer searches for its persisted grant record, it
computes the hash of the parameter value, applies hex encoding, and then calls
IPersistedGrantStore.GetAsync(...)
, passing the resulting hex encoded value. A
refresh token created before v6.0
would not include the “-1” suffix, so
IdentityServer would instead pass a base-64 encoded hash to the GetAsync
method.
However, consent records were not migrated to use hex encoding of their Key
values until IdentityServer v7.0
. Since there’s no protocol parameter that
corresponds to consent records, there’s no way to use the protocol parameters to
determine which encoding to use. So, prior to v7.0
, the consent Key
values
remained in the base-64 encoding.
Beginning in v7.0
, IdentityServer uses hex encoding for Consent Key
values,
but falls back to base-64 encoding when hex encoding fails to find a grant. In
that case, IdentityServer will automatically update the grant to use a hex
encoded Key
.
Data Property
Section titled “Data Property”The Data
property contains information that is specific to the grant type. For
example, consent records contain the scopes that the user consented to grant
to the client.
The Data
property also contains a copy of the SubjectId
, SessionId
,
ClientId
, Description
, CreationTime
, and Expiration
properties when
those properties are applicable to the grant type. The copy in the Data
is
treated as authoritative by IdentityServer, in the sense that the copy is used
when grants are retrieved from the store. The other properties exist to enable
querying the grants and/or for informational purposes and should be treated as
read-only.
By default, the Data
property is encrypted at rest using the ASP.NET Data
Protection API. The DataProtectData
option can be used to
disable this
encryption.
Time Stamps
Section titled “Time Stamps”All grants set their CreationTime
when they are created as a UTC timestamp.
Grants that expire set their Expiration
when they are created as well. Consent
records only expire if the ConsentLifetime
property of the Client
is set. By
default, ConsentLifetime
is not set and consent lasts until it is revoked.
Authorization code records always include an Expiration
. They expire after the
AuthorizationCodeLifetime
has
elapsed, so they are initialized with their Expiration
set that far into the
future. Reference token records expire in the same way, with their Expiration
controlled by the AccessTokenLifetime
. Refresh token records also
always include
Expiration
, controlled by the AbsoluteRefreshTokenLifetime
and
SlidingRefreshTokenLifetime
client settings. Custom grant
records should set the
Expiration
to indicate that they are only usable for a length of time, or not
set it to indicate that they can be used indefinitely.
Some grants can set a ConsumedTime
when they are used. This applies to grants
that are intended to be used once and that need to be retained after their use
for some purpose (for example, replay detection or to allow certain kinds of
limited reuse). Refresh tokens can be configured to have one-time use
semantics. Refresh tokens
that are configured this way can be further configured to set a ConsumedTime
when they are used.
Authorization codes do not set a ConsumedTime
. They are instead always removed
on use. ConsumedTime
is not applicable to reference tokens and consent, so
they both never set it. Custom grant records should set the ConsumedTime
if
one-time use semantics are appropriate for the grant.
PersistedGrantFilter
Section titled “PersistedGrantFilter”/// <summary>/// Represents a filter used when accessing the persisted grants store./// Setting multiple properties is interpreted as a logical 'AND' to further filter the query./// At least one value must be supplied./// </summary>public class PersistedGrantFilter{ /// <summary> /// Subject id of the user. /// </summary> public string SubjectId { get; set; }
/// <summary> /// Session id used for the grant. /// </summary> public string SessionId { get; set; }
/// <summary> /// Client id the grant was issued to. /// </summary> public string ClientId { get; set; }
/// <summary> /// Client ids the grant was issued to. /// </summary> public IEnumerable<string> ClientIds { get; set; }
/// <summary> /// The type of grant. /// </summary> public string Type { get; set; }
/// <summary> /// The types of grants. /// </summary> public IEnumerable<string> Types { get; set; }}
PersistedGrantTypes
Section titled “PersistedGrantTypes”The types of persisted grants are defined by the IdentityServerConstants.PersistedGrantTypes
constants:
public static class PersistedGrantTypes{ public const string AuthorizationCode = "authorization_code"; public const string BackChannelAuthenticationRequest = "ciba"; public const string ReferenceToken = "reference_token"; public const string RefreshToken = "refresh_token"; public const string UserConsent = "user_consent"; public const string DeviceCode = "device_code"; public const string UserCode = "user_code";}