Handling User Sessions

This guide covers different aspects of system security and contains all information you need to handle user sessions of Structr applications. User registration with double opt-in, user password reset, authentication via direct login, authentication via JWT and provider-based authentication (OAuth). To make your Structr application as secure as it can be, the following links will provide more information:

User self-registration

Instead of creating users in the Structr backend manually in the Users and Groups section of Structr’s admin UI, you can allow users to sign-up/self-register. The registration process uses double-opt in by default. All you need is a simple page where new users can enter their e-mail address so Structr can send them an e-mail with a confirmation link.

The following pre-defined MailTemplate keys can be used to configure the self-registration process. In version 4.0 they have been renamed to have a more uniform structure.

Note: The Mail Configuration Settings have to be done for self-registration mails to be sent.

Name Old Name (removed as of v4.1) Used as Default
CONFIRM_REGISTRATION_SENDER_ADDRESS SENDER_ADDRESS The sender address of the registration mail structr-mail-daemon@localhost
CONFIRM_REGISTRATION_SENDER_NAME SENDER_NAME The sender name of the registration mail Structr Mail Daemon
CONFIRM_REGISTRATION_SUBJECT SUBJECT The subject of the registration mail Welcome to Structr, please finalize registration
CONFIRM_REGISTRATION_TEXT_BODY TEXT_BODY The plaintext body of the registration mail Go to ${link} to finalize registration.
CONFIRM_REGISTRATION_HTML_BODY HTML_BODY The HTML body of the registration mail <div>Click <a href='${link}'>here</a> to finalize registration.</div>
CONFIRM_REGISTRATION_BASE_URL BASE_URL Used to build the link variable ${base_url}
CONFIRM_REGISTRATION_TARGET_PAGE TARGET_PAGE the target parameter value for the redirection target page name register_thanks
CONFIRM_REGISTRATION_ERROR_PAGE ERROR_PAGE the error parameter value for the error redirection target page name register_error

Notes:

  • The visibility flags of these MailTemplates are ignored because the self-registration mail is created as a privileged user.
  • A special link variable is provided for the TEXT_BODY and HTML_BODY templates and can be output with the usual syntax: ${link}
    • Example link: https://support.structr.com/confirm_registration?key=<CONFIRM_KEY>&target=/dashboard&onerror=/register-error
  • From v4.1 scripting is enabled in two templates: CONFIRM_REGISTRATION_TEXT_BODY and CONFIRM_REGISTRATION_TEXT_BODY. The script is being run in the context of the user (me keyword points to the user).
  • In any version prior to 4.1 scripting can not be used and simple text replacement is done

Registration Resource

The self-registration should be done via the registration resource. It is available under /structr/rest/registration.

An un-authenticated user can issue a HTTP POST to that resource to begin the registration process. The accepted input attributes are configured in the configuration registration.customuserattributes. eMail is always supported and often used as a single attribute for registration.

The registration is then started by the user by making a HTTP POST request (via a signup form) to /structr/rest/registration with the following body:

fetch("http://localhost:8082/structr/rest/registration", {
  method: "POST",
  body: JSON.stringify({
    eMail: "user.name@mail.com"
  })
})

The self-registration process would then send a mail using the above templates.

Notes:

Password Reset

To allow users to regain access to their account when they forgot their password we need to enable them to reset their password.

Note: The Mail Configuration has to be done for password retrieval mails to be sent.

Name Used as Default
 RESET_PASSWORD_SENDER_ADDRESS Sender address structr-mail-daemon@localhost
 RESET_PASSWORD_SENDER_NAME Sender name Structr Mail Daemon
 RESET_PASSWORD_SUBJECT Subject line Request to reset your Structr password
 RESET_PASSWORD_TEXT_BODY Plaintext mail body Go to ${link} to reset your password.
 RESET_PASSWORD_HTML_BODY HTML mail body <div>Click <a href='${link}'>here</a> to reset your password.</div>
 RESET_PASSWORD_BASE_URL Used to build the link variable ${base_url}
 RESET_PASSWORD_TARGET_PAGE target parameter value in the link variable. Specifies the redirect page after successful login. /reset-password

Notes:

  • The visibility flags of these MailTemplates are ignored because the self-registration mail is created as a privileged user.
  • A special link variable is provided for the TEXT_BODY and HTML_BODY templates and can be output with the usual syntax: ${link}
    • Example link: https://support.structr.com/reset-password?key=<PASSWORD-RESET-KEY>&target=/reset-password
  • From v4.1 scripting is two templates: RESET_PASSWORD_TEXT_BODY and RESET_PASSWORD_HTML_BODY. The script is being run in the context of the user (me keyword points to the user).
  • In any version prior to 4.1 scripting can not be used and simple text replacement is done.

Password Reset Resource

The reset password process should be done via the reset password resource. It is available under /structr/rest/reset-password.

An un-authenticated user can issue a HTTP POST to that resource to begin the registration process. The accepted input attributes are configured in the configuration registration.customuserattributes. eMail is always supported and often used as a single attribute for registration.

The reset password process is then started by the user by making a HTTP POST request to /structr/rest/reset-password with the following body:

fetch("http://localhost:8082/structr/rest/reset-password", {
  method: "POST",
  body: JSON.stringify({
    eMail: "user.name@mail.com"
  })
})

The reset password process would then send a mail using the above templates.

Notes:

  • A resource access grant must be configured for public users to allow the POST method to the grant with signature _resetPassword
  • the configuration setting JsonRestServlet.user.autologin must be set to true to enable auto-login with the link in the email
  • the link in the mail is only valid once

Authentication

Once users have been created or signed-up, they may be able to login to a Structr application, or if they have been granted administrative permissions, to Structr’s admin UI. In the early stages of development of an app, you might

Authentication - JSON Web Tokens

Structr provides authentication and authorization with JSON Web Tokens (JWTs). You can get more information about how to work with JWT here

Structr currently supports signing and verifying JWTs with either a secret key or a private/public keypair stored in a Java KeyStore file.

JWT - With Secret Key

To use JWTs with a secret key you have to edit the follow Structr configuration settings:

keyvalue
security.jwt.secrettype secret
security.jwt.secret [your secret key with at least 32 characters]
JWT - With Java KeyStore

When you want to sign and verify your JWTs with a private-public keypair you first have to create a Java KeyStore file that contains your keys.

You can create a new Keypair in a new KeyStore file with the following example keytool command:

keytool -genkey -alias jwtkey -keyalg RSA -keystore server.jks -storepass jkspassword

The KeyStore file has to be stored beside the structr.conf file in the installation directory of your Structr instance.

To use JWTs with a KeyStore file you have to edit the following Structr configuration settings:

keyvalue
security.jwt.secrettype keypair
security.jwt.keystore [The name of your KeyStore file]
security.jwt.keystore.password [The password to your KeyStore file]
security.jwt.key.alias [The alias of the key in the KeyStore file]
JWT - Create Token

Structr creates JWT access tokens with a simple request to it’s token resource. With each access token a new refresh token is created aswell, that can be used to obtain further access tokens without the need to send the actual user credentials as authentication.

The tokens are provided in the response body of the request to the token resource and they are stored as HttpOnly cookies in the browser.

The expiration time of the access- and the refresh-token and the issuer field of the JWTs can be adjusted in the configuration settings.

keyvalue
security.jwt.jwtissuer Defaults to ‘structr’
security.jwt.expirationtime Defaults to 60 minutes
security.jwt.refreshtoken.expirationtime Defaults to 1440 minutes

An example would look like this

fetch("http://localhost:8082/structr/rest/token", {
method: "POST",
body: JSON.stringify({
name: "admin",
password: "admin"
})
})

For this request to work a resource access grant with the signature _token has to exist and must be configure to allow POST requests for all users.

will return the data:

{
"result": {
"access_token": "[THE ACCESS TOKEN THAT CAN BE USED FOR AUTHENTICATION]",
"refresh_token": "[THE REFRESH TOKEN THAT CAN BE USED FOR FURTHER AUTHORIZATION]",
"expiration_date": "1597923368582",
"token_type": "Bearer"
},
"result_count": 1,
"page_count": 1,
"result_count_time": "0.000041704",
"serialization_time": "0.000166971"
}

To create new access tokens you can either send the request above with the usercredentials or you can send the refresh token in the request header refresh_token. An example request would look like this:

fetch("http://localhost:8082/structr/rest/token", {
method: "POST",
headers: {
"refresh_token": "REFRESH TOKEN"
}
})

Token Lifetime

The created access_token is valid until:
  • The expirationtime is exceeded.
  • The token itself is revoked.
  • The refresh_token that was created with the token is revoked.
  • A new token is created.
The created refresh_token is valid until:
  • The expirationtime is exceeded.
  • The token is revoked.
JWT - Authenticate with JWT

To authenticate a request to any Structr ressource with a token you have two options:

  • Send the access_token cookies stored by Structr (will be sent automatically by the browser)
  • Send the access token in the HTTP request header as Bearer token

An example request with the Authorization request header would look like this:

fetch("http://localhost:8082/structr/rest/User", {
method: "GET",
headers: {
"authorization": "Bearer [ACCESS TOKEN]"
}
})

Authenticating - JWKS Provider

Structr also supports JWT validation with tokens issued by other authentication systems than Structr like e.g Keycloak or Auth0 via the open .well-known JWKS endpoints of those services.

To activate this feature, the configuration entry ‘security.jwks.provider’ has to be configured with the endpoint of the service. After this, Structr will verify a send token in the Authentication Header of the requests against the configured service.

Authentication - Login

A user can log into the application with an HTTP POST request to the REST interface of Structr. In response Structr will return a cookie with key JSESSIONID and a new session id as value. A browser will send this session id automatically in subsequent requests to Structr where it can be used to run the request in the context of the logged in user.

The URL for the request

http[s]://domain[:port]/structr/rest/login

with payload

{
"eMail": "username",
"password": "password"
}

A sample curl request will look like this

curl --request POST \
--url http://localhost:8082/structr/rest/login \
--header 'content-type: application/json' \
--data '{
"eMail": "admin",
"password": "admin"
}'

For this request to work a resource access grant with the signature _login has to exist and must be configure to allow POST requests for public users.

Authentication - Logout

To be logged out of the system it is sufficient to make an HTTP POST request without payload to the URL:

http[s]://domain[:port]/structr/rest/logout

For this request to work a resource access grant with the signature _logout has to exist and must be configure to allow POST requests for authenticated users.

Authentication - Request Headers

As an alternative to obtaining a sessionId or a JWT, the username and password of a user can be sent to Structr in every request with two separate request headers.

This poses a potential security risk and should only be used over secure connections - either in a VPN or via HTTPS.

x-user: 'username'
x-password: 'password'

A request will look like this:

curl --request POST \
--url http://localhost:8082/structr/rest/User \
--header 'x-password: admin' \
--header 'x-user: admin'

OAuth

Additionally to the built in authentication system, Structr also supports OAuth authentication through various providers.

  • Google
  • Facebook
  • Twitter
  • Github
  • LinkedIn
  • Auth0

For more information about the logic behind OAuth, the following link can give a good overview how the implementation is done.

Global Settings

The following description will give an overview over the settings, that have to be entered in the structr.conf file via Structr’s configuration servlet. The description is given for the Auth0 specific settings, however they’re also valid for any other OAuth providers.

Triggering the Authentication

KeyDescription
oauth.auth0.client_idClientId at provider.
oauth.auth0.client_secretClient Secret at provider.
oauth.auth0.authorization_locationRedirect URI for the authentication process.
oauth.auth0.token_locationToken URI of provider, called by Structr to optain access_token.
oauth.auth0.redirect_uriCalled by provider on Structr application after successfull authentication. Triggers Structr to load userdata.
oauth.auth0.user_details_resource_uriURI of Oauth provider for user details e.g. username, eMail etc.
oauth.auth0.error_uriError URI within Structr app.
oauth.auth0.return_uriSuccess URI called after successfull login. The resource of this URI usally is a landing page within your Structr application.
jsonrestservlet.user.autocreateHas to be set to enabled, so Structr can create usernode if they doesn’t exist yet.

The authentication with the configured provider can be triggered by redirecting the user to the link /oauth/<provider>/login. For Auth0 the link would be /oauth/auth0/login.

To redirect the user to this location, the simplest way is to add an anchor HTML tag to your webapplication with the href attribute set to the location.

<a href="/oauth/auth0/login">Login with Auth0</a>