Authentication
This guide assumes familiarity with the Spring Framework.
If you are new to Spring, we recommend starting with their official guides to get up to speed.
Authentication in Singularity relies on Json Web Tokens (JWT). You can learn more about tokens in Singularity here.
Singularity uses several different types of tokens to authenticate and authorize the user or to store information about the user. Two particular tokens have a high relevance throughout the whole framework:
| Token | Lifespan | Usage |
|---|---|---|
AccessToken | Short (5 min by default) | It will be used in every request as HTTP-only cookie or in the authorization header as bearer token to authenticate the user. |
RefreshToken | Long (3 months by default) | It's only purpose is to to request a new AccessToken. Learn more here. |
In summary, the short-lived AccessToken is the workhorse for every request,
while the long-lived RefreshToken serves as a secure backup to renew the session without the user having to log in again.
Both tokens are generated on every successful login or register and automatically set as HTTP-only cookie. If header authentication is enabled, it will also be returned in the response body.
Example
After the user authenticated successfully (either through login or registration),
bothAccessToken and RefreshToken will be set as HTTP-only cookies.
If you perform another request from the same browser context,
you don't need to explicitly set any tokens in your request.
Cookie
If you want to test or explicitly override the AccessToken,
you can send a request to your app like this:
curl -X GET 'https://example.com/api/users/me' \
--cookie 'access_token=<your-access-token>'
Header
If header authentication is enabled, you can set the access token as bearer token in the authorization header.
curl -X GET 'https://example.com/api/users/me' \
-H 'Authorization: Bearer <your-access-token>'
Registering Users
A new user can be registered by calling the endpoint POST /api/auth/register.
Users are uniquely identified by email address.
If successful and if the email is not linked to any existing account, the user will receive an email with a link to verify the email address.
In case that email is already connected to an existing account, a warning will be sent to the corresponding email address informing the user.
To prevent account enumeration attacks, this endpoint will return response code 201
no matter if a new account is created or not.
Email Verification
If email is enabled, an email with a link to verify the email address will be sent to the user automatically after successful registration.
The link will be generated based on the URI you configure here:
| Property | Type | Description | Default value |
|---|---|---|---|
| singularity.ui.email-verification-uri | String | The URI that will included in the verification email that leads to the email verification page in your frontend application. | http://localhost:4200/auth/verify-email |
This URI should lead to the email verification page of your frontend application.
This generated link will look like this: <your-uri>?token=<generated-token>.
For example, if you set the property to https://example.com/auth/verify-email,
the generated link will look like this https://example.com/auth/verify-email?token=ey27308dh7a7....
The link will include the query parameter token containing the token you need to verify the email.
Your frontend application should then request POST /api/auth/email/verification
attaching the token.
If successful, the user's email address is verified.
If there is no account associated with the given email address, a No Account Information email will be sent to the given email address.
Resending the Verification Email
You can resend the verification email using POST /api/auth/email/verification/send.
After sending the email, a cooldown will be started.
The number of seconds the cooldown will take will be returned in the response body.
You are not allowed to send another email while the cooldown is active. The cooldown can be configured here.
You can check the state of the cooldown here GET /api/auth/email/verification/cooldown.
OAuth2
If authentication via OAuth2 providers is enabled, users can also register using configured providers. You can find more information here.
Login
You can log in a user by calling POST /api/auth/login.
After the login succeeded,
an HTTP-only cookie with AccessToken and RefreshToken will be set automatically.
If header authentication is enabled,
access token and refresh token will be returned in the response body.
A login alert will be sent to the user's email if this setting is enabled and email is enabled and configured correctly.
2FA
If the user enabled 2FA,
a TwoFactorAuthenticationToken will be set as an HTTP-only cookie and returned in the response body
if header authentication is enabled.
This token is necessary to perform the second step in the login process.
Depending on the methods the user configured,
you can use the code you obtained from one of those methods to perform a second request to POST /api/auth/2fa/login.
If verification was successful,
an HTTP-only cookie containing an AccessToken and one containing a RefreshToken will be set automatically.
If header authentication is enabled,
access token and refresh token will be returned in the response body.
The TwoFactorAuthenticationToken will also be deleted.
Password Reset
You need to enable mail. Otherwise, the password reset will not be possible.
You can request a password reset using POST /api/auth/password/reset-request.
An email with a link to reset the password will be sent to the user.
The link will be generated based on the URI you configure here:
| Property | Type | Description | Default value |
|---|---|---|---|
| singularity.ui.password-reset-uri | String | The URI that will be included in the password reset email that leads to the password reset page in your frontend application. | http://localhost:4200/auth/reset-password |
This URI should lead to the password reset page of your frontend application.
This generated link will look like this: <your-uri>?token=<generated-token>.
For example, if you set the property to https://example.com/auth/reset-password,
the generated link will look like this https://example.com/auth/reset-password?token=ey27308dh7a7....
The link will include the query parameter token containing the token you need to reset the password.
Your frontend application should then request `POST /api/auth/password/reset
attaching the token and specifying the new password.
If successful, the new password is set and the user can log in again.
All active sessions will be deleted after resetting the password.
If there is no account associated with the given email address, a No Account Information email will be sent to the given email address.
Resending the Reset Password Request
You can resend the password reset request using POST /api/auth/password/reset-request.
After sending each email, a cooldown will be started.
The number of seconds the cooldown will take will be returned in the response body.
You are not allowed to send another email while the cooldown is active. The cooldown can be configured here.
You can check the state of the cooldown here GET /api/auth/password/reset/cooldown.
OAuth2
If authentication via OAuth2 providers is enabled and the user connected a provider, users can log in using their connected providers. You can find more information here.
Refresh
You can request a new AccessToken using POST /api/auth/refresh
using a valid RefreshToken as HTTP-only cookie refresh_token or as bearer token in the Authorization header if header authentication is enabled.
If successful, the RefreshToken you used becomes invalid,
a new AccessToken and RefreshToken will be generated.
Both tokens will be set as HTTP-only cookies and returned in the response body if header authentication is enabled.
Example
Cookie
If you want to test or explicitly override the RefreshToken,
you can send a request to your app like this:
curl -X GET 'https://example.com/api/auth/refresh' \
--cookie 'refresh_token=<your-refresh-token>'
Header
If header authentication is enabled,
you can set the RefreshToken as bearer token in the authorization header.
curl -X GET 'https://example.com/api/auth/refresh' \
-H 'Authorization: Bearer <your-refresh-token>'
Logout
You can perform a logout using POST /api/auth/logout.
Please note that you need to be authenticated to perform a logout.
If successful and authorized,
the session will be deleted and all AccessTokens will be invalidated.
You can also delete all active sessions. You can find more information here.
Step-Up
Singularity allows you to secure critical endpoints with a second step.
Operations like changing the password or deleting the user account require reauthentication.
This means, an AccessToken is not enough to perform these requests.
You need to provide a StepUpToken to authorize a step-up.
You can learn more on how to secure your endpoints by requiring a step-up here
You can request a StepUpToken using POST /api/auth/step-up.
Keep in mind that you also need to provide a valid AccessToken.
Otherwise, the reauthentication will not be successful.
If reauthenticated successfully, the StepUpToken will be set
as HTTP-only cookie and return in the response body if header authentication is enabled.
2FA
If the user enabled 2FA,
a TwoFactorAuthenticationToken will be set as an HTTP-only cookie and returned in the response body
if header authentication is enabled.
This token is necessary to perform the second step in the step-up process.
Depending on the methods the user configured,
you can use one of those methods to perform a second request to POST /api/auth/2fa/step-up.
If verification was successful,
an HTTP-only cookie containing your StepUpToken will be set automatically.
If header authentication is enabled,
the StepUpToken will be returned in the response body.
The TwoFactorAuthenticationToken will also be deleted.
OAuth2
If authentication via OAuth2 providers is enabled and the user connected a provider, users can request a step-up using their connected providers. You can find more information here.
Status
You can request the current authentication status using GET /api/auth/status.
This will check the cookies and headers you set in the request.
Header authentication
It is possible to authorize users using a bearer token in the request header. This option is enabled by default.
You can also configure if the access token stored inside an HTTP-only cookie or the bearer token should be preferred.
Please note that header authentication can be less secure because the tokens can be read from JavaScript. This allows XSS-attacks if not configured properly.
HTTP-only cookies on the other hand are hidden from JavaScript and not directly accessible. If you don't need header authentication, you can disable it here.
Properties
| Property | Type | Description | Default value |
|---|---|---|---|
| singularity.auth.allow-header-authentication | Boolean | Allow authentication using a bearer token placed in the header along HTTP-only Cookies. Allowed by default. | true |
| singularity.auth.prefer-header-authentication | Boolean | "If header authentication is allowed, this property controls the precedence: if true, the Authorization header is preferred over HTTP-only cookies.", | true |
Example
singularity:
auth:
allow-header-authentication: true
prefer-header-authentication: true