Authentication
Introduction
See Security Overview for an high level view of the RESTHeart security model.
RESTHeart is built around a pluggable architecture. It comes with a strong security implementation but you can easily extend it by implementing plugins. This section documents the authentication plugins available out-of-the-box. You can also develop your own authentication plugins.
Authentication Mechanisms
JWT Authentication
JWT Authentication manages the authentication following the JSON Web Token standard.
The token is verified against the configured issuer
and audience
and according to the specified algorithm
. If you want to disable checking issuer
or audience
, set them to null
. The property audience
can be null
, a String or an array of Strings.
The authenticated client will gain the roles included in the JWT claim set by rolesClaim
or the roles specified by the configuration option fixedRoles
. It’s not possible to set both rolesClaim
and fixedRoles
Supported algorithms are the HMAC256, HMAC384, HMAC512, RSA256, RSA384, RSA512.
For HMAC the key
configuration option specifies the secret, for RSA the public key.
jwtAuthenticationMechanism:
enabled: true
algorithm: HS256
key: secret
base64Encoded: false
usernameClaim: sub
rolesClaim: roles
fixedRoles:
# - admin
issuer: myIssuer
audience: myAudience
Basic Authentication
BasicAuthMechanism manages the Basic Authentication method, where the client credentials are sent via the Authorization
request header using the format Authorization: Basic base64(id:pwd)
. The configuration allows specifying the Authenticator that will be used to verify the credentials.
basicAuthMechanism:
enabled: true
authenticator: fileRealmAuthenticator
Cookie Authentication
Cookie Authentication allows the client browser to store an authentication token in a secure cookie. This mechanism enables authentication based on the stored cookie, allowing the client to remain authenticated across multiple requests without having to send credentials each time. The token is securely saved in the cookie, ensuring that sensitive data is protected and accessible only to the intended server.
Note
|
this is the suggested authentication mechanism when the client is the browser. |
Typically, a client first authenticates using Basic Authentication and then uses the auth token returned in the first response for further requests. This auth token is usually stored in the local storage by web clients. The local storage is readable by JavaScript, thus exposing this approach to Cross-site Scripting (XSS) security attacks. Storing the auth token in a secure cookie avoids XSS.
Important
|
Using cookie authentication and JWT tokens effectively enables Single Sign-On. |
Configuration Options
Cookie Authentication is disabled by default. To enable it, the following three plugins must be enabled and configured: authCookieSetter
, authCookieHandler
, and authCookieRemover
.
The cookie authentication mechanism can function using three different options:
Option 1: JWT Verified by jwtAuthenticationMechanism
This option is recommended if you also want to allow clients to authenticate via JWTs sent in the Authorization
header (not stored in a cookie).
/tokenBasicAuthMechanism/enabled->true
/jwtAuthenticationMechanism/enabled->true
/jwtTokenManager/enabled->true
/rndTokenManager/enabled->false
Option 2: JWT Verified by tokenBasicAuthMechanism
Choose this option if you have multiple instances of RESTHeart verifying cookies, and JWT header-based authentication isn’t required.
/tokenBasicAuthMechanism/enabled->true
/jwtAuthenticationMechanism/enabled->false
/jwtTokenManager/enabled->true
/rndTokenManager/enabled->false
Option 3: RGT Cookies (Randomly Generated Tokens) For authentication via RGT cookies, enable these components:
-
tokenBasicAuthMechanism
: Manages the basic authentication process. -
rndTokenManager
: Manages and validates randomly generated tokens for Basic Authentication cookies.
/tokenBasicAuthMechanism/enabled->true
/jwtAuthenticationMechanism/enabled->false
/jwtTokenManager/enabled->false
/rndTokenManager/enabled->true
Note
|
RGT cookies can only be verified by the RESTHeart instance that issued them. For multi-instance deployments, it is advisable to use JWT cookies instead. |
authCookieSetter
This component is responsible for initiating a user’s authenticated session by setting the authentication cookie.
Activates when a URL includes the query parameter ?set-auth-cookie
and a user is authenticated, setting a cookie populated with a token generated by the enabled Token Manager.
Configuration
authCookieSetter:
enabled: false # Not enabled by default
secure: true # true if only allow setting the cookie on https
name: rh_auth # The name of the cookie to be set
domain: localhost # The domain within which the cookie is valid
path: / # The cookie path, applicable to the entire domain
http-only: true # If true, enhances security by making the cookie inaccessible to JavaScript
same-site: true # Restricts the cookie to first-party contexts, preventing CSRF attacks
same-site-mode: strict # Strictly prevents the cookie from being sent along with cross-site requests
expires-ttl: 86400 # Defines the duration (in seconds, default 1 day) for which the cookie is valid
When using JWT tokens, the cookie can be updated by specifying both ?set-auth-cookie&renew-auth-token
. The query parameter renew-auth-token
forces the jwtTokenManager
to update the JWT.
authCookieHandler
Responsible for utilizing the authentication cookie to maintain authenticated sessions across requests.
Reads the rh_auth
cookie (actual cookie name is defined in authCookieSetter configuration), if available, and constructs an Authorization header. This allows for seamless continuation of sessions and supports both Basic and JWT authentication mechanisms.
Configuration
authCookieHandler:
enabled: false # Not enabled by default
authCookieRemover
Handles the secure and explicit termination of authenticated sessions.
Clears the authentication cookie in response to a POST /logout
request. This effectively logs out the user by wiping the authentication cookie from the user’s browser, ensuring the session is securely terminated.
Configuration
authCookieRemover:
enabled: false # Not enabled by default
secure: false # If the request to clean the cookie should be authenticated
uri: /logout # The endpoint that triggers this service
Example usage
This is an example of how a user might log in, make some requests, and then log out within a system using cookie authentication with the configuration described previously. This example assumes that the system is web-based and communicates over HTTP.
Logging In
The user submits their credentials (username and password) via Basic Authentication (Authorization
header) from a form on a client application, which sends a GET request to the`/roles/{username}` endpoint, including the ?set-auth-cookie
query parameters
GET /roles/{username}?set-auth-cookie HTTP/1.1
Host: localhost
Content-Type: application/json
Authorization: Basic YWRtaW46c2VjcmV0
If the credentials are valid, the server responds by setting an rh_auth
cookie containing the authentication token and returns a success response.
HTTP/1.1 200 OK
Set-Cookie: rh_auth="Basic YWRtaW46MmliNWFsaDFxajZ4eHY5aWlyOTZsejh1bnJjMHQzNWFucnEyYzh1cG12cHNpOGc3dDQ="; Version=1; Path=/; Domain=localhost; Secure; HttpOnly; Expires=Sat, 20 Apr 2024 11:53:00 GMT; SameSite=Strict
Content-Type: application/json
{
"authenticated": true,
"roles": [ "user-role" ]
}
Note that the value of the cookie doesn’t include the actual user credentials but uses the auth token generated by the enabled Token Manager.
Making Authenticated Requests
Once the cookie is set, the user can make subsequent requests to the server. The browser automatically includes the rh_auth
cookie with each request to the domain.
For example, if the user wants to access a protected resource, they might send a GET request to the server:
GET /protected-resource HTTP/1.1
Host: localhost
Cookie: rh_auth="Basic YWRtaW46MmliNWFsaDFxajZ4eHY5aWlyOTZsejh1bnJjMHQzNWFucnEyYzh1cG12cHNpOGc3dDQ="
The server checks the cookie, validates the session, and if valid, responds with the requested data.
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": "Here is your protected resource data."
}
Logging Out
To log out, the user sends a POST request to the logout endpoint. This request doesn’t need to include user credentials but should be made from the same domain to ensure the browser includes the authentication cookie.
POST /logout HTTP/1.1
Host: localhost
Cookie: rh_auth=
The server processes the logout request and clears the authentication cookie by setting its value to null.
HTTP/1.1 200 OK
Set-Cookie: rh_auth=; path=/; domain=localhost; secure; HttpOnly; SameSite=Strict
Content-Type: application/json
After this, the user is logged out, and their session is terminated. The cookie is invalidated, and any subsequent requests to the server that require authentication will fail until the user logs in again.
Digest Authentication
DigestAuthMechanism manages the Digest Authentication method. The configuration allows specifying the Authenticator that will be used to verify the credentials.
digestAuthMechanism:
enabled: true
realm: RESTHeart Realm
domain: localhost
authenticator: fileRealmAuthenticator
Token Authentication
TokenBasicAuthMechanism manages the Basic Authentication method with the actual password replaced by the auth token generated by RESTHeart, i.e. the client credentials are sent via the Authorization
request header using the format Authorization: Basic base64(id:auth-token)
. It requires a Token Manager to be configured (eg. RndTokenManager).
tokenBasicAuthMechanism:
enabled: true
Identity Authentication
IdentityAuthMechanism just authenticates any request building an BaseAccount with the username and roles specified in the configuration. Useful for testing purposes. Note that enabling this causes the DigestAuthMechanism to fail, you cannot use both.
identityAuthMechanism:
enabled: false
username: admin
roles:
- admin
- user
Tip
|
Watch Authentication mechanisms |
Authenticators
Mongo Realm Authenticator
mongoRealAuthenticator authenticates users defined in a MongoDB collection.
Note
|
Mongo Realm Authenticator is suggested for production usage. |
The configuration allows:
-
defining the collection to use (
users-db
andusers-collection
), the properties of the user document to use as user id, password and roles (prop-id
,prop-password
andjson-path-roles
). -
enabling hashed password using the strong bcrypt hashing algorithm (
bcrypt-hashed-password
andbcrypt-complexity
); note that the password is automatically hashed on write requests and that the password property is automatically removed from responses. -
allows initializing the users collection and the admin user if not existing. See
create-user
option. -
allows controlling the users caching.
mongoRealmAuthenticator:
users-db: restheart
users-collection: users
prop-id: _id
prop-password: password
json-path-roles: $.roles
bcrypt-hashed-password: true
bcrypt-complexity: 12
create-user: true
create-user-document: '{"_id": "admin", "password": "$2a$12$lZiMMNJ6pkyg4uq/I1cF5uxzUbU25aXHtg7W7sD2ED7DG1wzUoo6u", "roles": ["admin"]}'
# create-user-document.password must be hashed when bcrypt-hashed-password=true
# default password is 'secret'
# see https://bcrypt-generator.com but replace initial '$2y' with '$2a'
cache-enabled: false
cache-size: 1000
cache-ttl: 60000
cache-expire-policy: AFTER_WRITE
enforce-minimum-password-strenght: false
# Integer from 0 to 4
# 0 Weak (guesses < 3^10)
# 1 Fair (guesses < 6^10)
# 2 Good (guesses < 8^10)
# 3 Strong (guesses < 10^10)
# 4 Very strong (guesses >= 10^10)
minimum-password-strength: 3
File Realm Authenticator
fileRealmAuthenticator defines users credentials and roles in the configuration or in a simple yml configuration file.
fileRealmAuthenticator:
enabled: true
#conf-file: ./etc/users.yml
users:
- userid: admin
password: null
roles: [admin]
The conf-file
path is either absolute, or relative to the restheart configuration file (if specified) or relative to the plugins directory (if using the default configuration).
See users.yml for an example users definition.
Token Managers
Random Token Manager
rndTokenService generates an auth token using a random number generator. It has two arguments, ttl
, which is the tokens Time To Live in minutes, and srv-uri
the URI of the service that allows to get and invalidate the user auth token.
rndTokenManager:
enabled: true
ttl: 15
srv-uri: /tokens
JWT Token Manager
jwtTokenManager An implementation of Token Manger that issues and verifies auth tokens in a cluster compatible way.
Each token can be verified by any node of the cluster regardless which one actually issued it (as long as they share the same secret)
jwtTokenManager:
key: secret
enabled: true
ttl: 15
srv-uri: /tokens
issuer: restheart.com
The query parameter renew-auth-token forces the token to be renewed.
Generating a new token is a cryptographic operation, and it can have a significant performance overhead. It is responsibility of the client to renew the token using this query parameter when it is going to expiry somehow soon.
Tip
|
Watch Authenticators in RESTHeart |
Avoid browsers to open the login popup window
The Basic and Digest Authentication protocols requires responding with a challenge when the request cannot be authenticated as follows:
WWW-Authenticate: Basic realm="RESTHeart Realm"
WWW-Authenticate: Digest realm="RESTHeart Realm",domain="localhost",nonce="Toez71bBUPoNMTU0NDAwNDMzNjEwMXBY+Jp7YX/GVMcxAd61FpY=",opaque="00000000000000000000000000000000",algorithm=MD5,qop="auth"
In browsers this leads to the login popup windows. In our web applications we might want to redirect to a fancy login page when the 401 Unauthorized response code.
To avoid the popup window just add to the request the noauthchallenge
query parameter or the header No-Auth-Challenge
. This will skip the challenge response.