4.9 KiB
4.9 KiB
| stage | group | info | title |
|---|---|---|---|
| none | unassigned | Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review. | Using the `TokenAuthenticatable` concern |
The TokenAuthenticatable module is a concern that provides token-based authentication functionality for ActiveRecord models.
It allows you to define authentication tokens for your models.
Overview
This module provides a flexible way to add token-based authentication to your models.
It supports three storage strategies:
digest: theSHA256digests of the token is stored in the databaseencrypted: the token is stored encrypted in the database using the AES 256 GCM algorithminsecure: the token is stored as-is (not encrypted nor digested) in the database. We strongly discourage the usage of this strategy.
It also supports several options for each storage strategies.
Usage
To define a token_field attribute in your model, include the module and call add_authentication_token_field:
class User < ApplicationRecord
include TokenAuthenticatable
add_authentication_token_field :token_field, encrypted: :required
end
Storage strategies
encrypted: :required: Stores the encrypted token in thetoken_field_encryptedcolumn. Thetoken_field_encryptedcolumn needs to exist. We strongly encourage to use this strategy.encrypted: :migrating: Stores the encrypted and plaintext tokens respectively intoken_field_encryptedandtoken_field. Always reads the plaintext token. This should be used while an attribute is transitioning to be encrypted. Bothtoken_fieldandtoken_field_encryptedcolumns need to exist.encrypted: :optional: Stores the encrypted token in thetoken_field_encryptedcolumn. Reads fromtoken_field_encryptedfirst and fallbacks totoken_field. Nullifies the plaintext token in thetoken_fieldcolumn when writing the encrypted token. Bothtoken_fieldandtoken_field_encryptedcolumns need to exist.digest: true: Stores the token's digest in the database. Thetoken_field_digestcolumn needs to exist.insecure: true: Stores the token as-is (not encrypted nor digested) in the database. We strongly discourage the usage of this strategy.
{{< alert type="note" >}}
By default, the SHA256 digest of the tokens are stored in the database, if no storage strategy is chosen.
{{< /alert >}}
Other options
unique: false: Doesn't enforce token uniqueness and disables the generation offind_by_token_field(wheretoken_fieldis the attribute name). Default istrue.format_with_prefix: :compute_token_prefix: Allows to define a prefix for the token. The#compute_token_prefixmethod needs to return aString. Default is no prefix.expires_at: :compute_token_expiration_time: Allows to define a time when the token should expire. The#compute_token_expiration_timemethod needs to return aTimeobject. Default is no expiration.token_generator:A proc that returns a token. If absent, a random token is generated usingDevise.friendly_token.routable_token:: A hash allowing to define "routable" parts that should be encoded in the token. This follows the Routable Tokens design document. Supported keys are:if:: a proc receiving the token owner record. The proc usually has a feature flag check, and/or other checks. If the proc returnsfalse, a random token is generated usingDevise.friendly_token.payload:: A{ key => proc }hash with allowed keysc,o,g,p,uwhich complies with the specification. See an example in the Routable Tokens design document.
require_prefix_for_validation:(only for the:encryptedstrategy): Checks that the token prefix matches the expected prefix. If the prefix doesn't match, it behaves as if the token isn't set. Defaultfalse.
Accessing and manipulating tokens
user = User.new
user.token_field # Retrieves the token
user.set_token_field('new_token') # Sets a new token
user.ensure_token_field # Generates a token if not present
user.ensure_token_field! # Generates a token if not present
user.reset_token_field! # Resets the token and saves the model with #save!
user.token_field_matches?(other_token) # Securely compares the token with another
user.token_field_expires_at # Returns the expiration time
user.token_field_expired? # Checks if the token has expired
user.token_field_with_expiration # Returns a API::Support::TokenWithExpiration object, useful for API response