Authentication

Overview

Gentics Mesh provides multiple ways of authentication:

  • Authentication via login

  • Authentication via API token

  • Authentication via OAuth2

  • No authentication - Access via anonymous user

Currently, all data including media assets such as images, videos, and documents are secured and need authentication to be retrieved.
Sending user credentials as base64 encoded string, or as plaintext is highly insecure to be used on an open network. This method MUST not be used in scenarios other than debugging and development when the connection between server and client is trusted.

Authentication Configuration

Gentics Mesh uses JWT (JSON Web Token) to handle authentication. It is thus required to create a cryptograph key to sign and verify the generated JWT’s. Typically, if no keystore file has been provided, Gentics Mesh will create one on the basis of the configuration details in mesh.yml (see Configuration & Settings). If the keystorePassword property is omitted, a password will be generated randomly and stored in the configuration file.

security:
  tokenExpirationTime: 3600
  keystorePassword: "secret"
  keystorePath: "keystore.jceks"
  algorithm: "HS256"

Alternatively, you can use the Java keytool to create a new keystore. Here is an example on how to create a keystore which contains a HMacSHA256 key:

keytool -genseckey -keystore keystore.jceks -storetype jceks -storepass secret -keyalg HMacSHA256 -keysize 2048 -alias HS256 -keypass secret

After creating the keystore, you need to set the keystore password, the path to the keystore file, and the used algorithm in the mesh.yml configuration file (see Configuration & Settings).

JWT

In order to be able to store and retrieve content, a Gentics Mesh user needs to authenticate (username:password).

Each way will store a JWT in a cookie which is used to authenticate the user for succeeding requests. The token only lasts a certain amount of time (which can be configured in the mesh.yml file, see setting tokenExpirationTime in the Configuration & Settings section), so it might be necessary to refresh the token. The JWT will be automatically renewed with every request on the Gentics Mesh API.

Login

A user can be logged in via a basic authentication request to GET /api/v1/auth/login.

Basic Authentication Header

In basic authentication, when a client requests a URL that requires authentication, the server requests the client to authenticate itself by sending a 401-Not Authorized code. The client, in return, answers with login credentials sent in the authorization header:

authorization: Basic {base64_encode(username:password)}

In Gentics Mesh, a user can be authenticated by invoking a regular GET request to the /api/v1/auth/login endpoint including a basic authentication HTTP header.

Example:

curl -v -X GET   http://localhost:8080/api/v1/auth/login   -H 'authorization: Basic YWRtaW46YWRtaW4='

The response will be a valid JWT as well as set a cookie with the token.

{
  "token" : "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyVXVpZCI6IjNjYjY2YzU0MmFlMzRiMDFiNjZjNTQyYWUzY2IwMWRiIiwiaWF0IjoxNDkxNzczMDYzLCJleHAiOjE0OTE3NzY2NjN9.8iG3I0Pe1M7J43pwbsBXiBOd6p0sn9dRxO3NfazVbOk="
}

POST JSON Data

Alternatively, the user can POST his or her credentials to the /api/v1/auth/login endpoint in order to retrieve a token. The JSON object must contain the following fields:

  • username: The username of the user

  • password: The password of the user

If authentication has been successful, the server will respond with a JSON object containing a single property:

  • token: The token to be sent on every subsequent request.

Additionally, the token will also be provided in a cookie.

Example:

curl -v -X POST \
  http://localhost:8080/api/v1/auth/login \
  -H 'content-type: application/json' \
  -d '{
  "username" : "admin",
  "password" : "admin"
}'
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /api/v1/auth/login HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.50.3
> Accept: */*
> content-type: application/json
> Content-Length: 50
>
* upload completely sent off: 50 out of 50 bytes
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Cache-Control: no-cache
< Content-Length: 208
< Set-Cookie: mesh.token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyVXVpZCI6IjNjYjY2YzU0MmFlMzRiMDFiNjZjNTQyYWUzY2IwMWRiIiwiaWF0IjoxNDkxNzczODU0LCJleHAiOjE0OTE3Nzc0NTR9._qt3Eufi7-3jnvgQ8lfe_KwJbd5ePwx5jOFrCK9w76A=; Max-Age=3600; Expires=Sun, 9 Apr 2017 22:37:34 GMT; Path=/
<
{
  "token" : "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyVXVpZCI6IjNjYjY2YzU0MmFlMzRiMDFiNjZjNTQyYWUzY2IwMWRiIiwiaWF0IjoxNDkxNzczODU0LCJleHAiOjE0OTE3Nzc0NTR9._qt3Eufi7-3jnvgQ8lfe_KwJbd5ePwx5jOFrCK9w76A="
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact
}

Both login methods will yield a JSON web token.

For further requests, the JWT can be provided in two ways. By default it is passed along with a cookie value. E.g., this is useful for embedding binary image nodes directly in HTML, since the browser will automatically handle authentication on the basis of the cookie. Alternatively, the token can be passed along within the Authorization header which includes the regular JWT Bearer <Token>, where <Token> is the token you received from the login/cookie.

curl -X GET \
  http://localhost:8080/api/v1/demo/nodes \
  -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyVXVpZCI6IjNjYjY2YzU0MmFlMzRiMDFiNjZjNTQyYWUzY2IwMWRiIiwiaWF0IjoxNDkxNzY1NDEzLCJleHAiOjE0OTE3NjkwMTN9.UY8OgjiK5qyZobAWt6X1Vd1Z-zg68BeJgGZKbW4Ucj0=' \

API Token

An API token will never expire. This is different from regular tokens which will be issued when calling /api/v1/auth/login.

Leaking an API token is potentially dangerous and thus the API token should only be used in combination with a secure connection.

Typical use cases for API tokens are backend implementations which constantly communicate with Gentics Mesh using a secure or local connection.

The token can be issued per user with POST /api/v1/users/:userUuid/token.

Creating a new API token will automatically invalidate a previously issued token.

Since the token is just a regular JWT you just need to add it to your request Authorization header field.

curl -X GET \
  http://localhost:8080/api/v1/demo/nodes \
  -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyVXVpZCI6IjNjYjY2YzU0MmFlMzRiMDFiNjZjNTQyYWUzY2IwMWRiIiwiaWF0IjoxNDkxNzY1NDEzLCJleHAiOjE0OTE3NjkwMTN9.UY8OgjiK5qyZobAWt6X1Vd1Z-zg68BeJgGZKbW4Ucj0=' \

It is possible to manually revoke a previously issued token via DELETE /api/v1/users/:userUuid/token. Once the token is invalidated it can no longer be used for authentication.

Anonymous Access

Gentics Mesh first and foremost keeps your content safe - all data including media assets such as images, videos, and documents are secured and need authentication to be retrieved. However, sometimes it may be desirable to serve public content with Gentics Mesh.

That is why Gentics Mesh instances ship with an included anonymous user/role/group set. If no authentication details are provided Gentics Mesh will automatically try to authenticate with the user anonymous.

Try our Gentics Mesh demo instance without authenticating yourself: https://demo.getmesh.io/api/v1/auth/me. This API endpoint shows the currently authenticated user - which is anonymous.

You can assign readPublished permissions to the anonymous role for all elements you want to be publicly available.

Assigning further permissions would of course allow for other operations to be granted.

Anonymous access can be configured in the mesh.yml configuration file (see Configuration & Settings):

security:
   enableAnonymousAccess: true
Recreating a previously deleted anonymous user would automatically re-enable the feature if the configuration setting enableAnonymousAccess is set to true.

OAuth2

Since Gentics Mesh 0.20.0 it is also possible to use OAuth2 authentication.

The OAuth2 authentication can be enabled via the security.oauth2.enabled flag.

Gentics Mesh will just utilize provided access tokens. The needed OAuth2 sign-in and token refresh handling must be done by the client.

The provided OAuth2 user information will automatically be kept in sync with the user that is present in Gentics Mesh. The synchronization process will also take care of creating new users and even roles and groups.

The Gentics Mesh UI is currently not Keycloak aware. The UI will thus not redirect you to the Keycloak login page. This functionality will be part of a future release of the Gentics Mesh UI.

Configuration

The authentication provider server must be configured within the security.oauth2.config section.

You can use the Keycloak OIDC JSON as a source for the needed properties. You can get the JSON via:

  • ClientsInstallationFormat: Keycloak OIDC JSON

security:
  oauth2:
    enabled: false
    mapperScriptPath: "config/mymapper.js"
    mapperScriptDevMode: false
    config:
      realm: "master"
      authServerUrl: "http://localhost:3000/auth"
      sslRequired: "external"
      resource: "mesh"
      credentials:
        secret: "9b65c378-5b4c-4e25-b5a1-a53a381b5fb4"
      confidentialPort: 0

Mapping

The access token properties will be used to synchronize the user data with Gentics Mesh.

By default the authenticated user will automatically be created within Gentics Mesh.

Currently the following fields will be kept in sync with Gentics Mesh:

Table 1. Mapped Fields
Token Field Gentics Mesh

email

User email

given_name

User firstname

family_name

User lastname

preferred_username

User username

The preferred_username field is the main id property which will be used to locate a user.

If the preferred_username changes a new user will be created in Gentics Mesh.

Mapping Script

By default groups and roles will not be handled by the synchronization process. It is however possible to provide a custom mapper script which can extract role and group information from the access token infromation. This way groups and roles can be directly created.

The security.oauth2.mapperScriptDevMode flag can be used to ease the development of mapper scripts. When enabled the mapper script will be read from disk for each mapper call. Additionally the input and output information will be printed to the log.

The synchronization process will however only be invoked if the access token changes. Remember that you need to issue a new access token if you change the mapping in keycloak. The old token may still contain the old information.

Make sure to disable this flag in production.

Example script:

function extractGroups(principle) {
	var groups = [];
	groups.push("group1");
	groups.push("group2");
	return groups;
}

function extractRoles(principle) {
	var roles = [];
	roles.push("role1");
	roles.push("role2");
	return roles;
}

All returned groups will automatically be created if not present in Gentics Mesh. This also applies to roles.

In addition to this the user will also automatically be assigned to the returned groups. The user will be removed from any other group to keep the data in sync even if the user was removed from a group in the authentication system.

No automatic assignment for roles will be executed. Roles will just be created if not present.

Supported Providers

Currently only the Keycloak Authentication Server is tested and supported.