Authentication and Authorization

Overview

By default, the Platform does not use authentication, authorization, or RBACs.

To secure it, consider the following configuration and set-up steps:

  • Configure and enable the Platform’s Authentication and identity service (FusionAuth)
  • Configure and enable the Platform’s API gateway (Kong)
  • Configure and enable Semantic Objects Role-Based Access Controls
  • Configure and enable data layer authorization (GraphDB)

Quick Start

The Platform provides a CLI tool that quickly and simply provisions:

  • FusionAuth: JWT signing keys, tenants, applications, users, and roles

Note

The tool will create the following default FusionAuth administration account:

admin:
  email: system@example.com
  password: 123456789
  firstName: System
  lastName: Admin

The OPCTL CLI tool (short for Ontotext Platform control) reads a configuration YAML file that describes the components necessary to provision the Platform FusionAuth (identity and authentication) service. The address should be resolvable by the CLI, otherwise it will not be able to provision FusionAuth and any other configured components.

Once you have a configured YAML, you can initiate the provisioning process by invoking:

docker run -it -v $(pwd)/config/:/etc/opctl/ ontotext/opctl provision security -c /etc/opctl/opctl.yaml

Where $(pwd) is the current directory containing a config folder with the opctl configuration YAML named opctl.yaml.

In this case, the opctl.yaml should be configured with addresses that are reachable outside of Docker’s network.

If the Platform services are not exposed, you can attach to an existing Docker network where the services are reachable. For example, if the network is called platform_network, you can run the CLI as follows:

docker run -it -v $(pwd)/config/:/etc/opctl/ --network=platform_network ontotext/opctl provision security -c /etc/opctl/config.yaml

See the official Docker CLI documentation for more information.

A successful provision will produce output such as:

../_images/cli-security-provision.png

OPCTL Installation

Docker Pull OPCTL

Get the latest OPCTL Docker image:

docker pull ontotext/opctl3.4.0-RC3

To test if OPCTL is working correctly and see the available commands and options, use:

docker run -it ontotext/opctl --help

Hint

See the OPCTL documentation for more information about command line arguments, CLI configuration, and what services can be provisioned.

OPCTL Configuration

This is a minimal opctl.yaml configuration example for provisioning Platform FusionAuth (identity and authentication).

Provisioning of users and roles can also be achieved by including them in the YAML configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
platform:
  fusion:
    address: 'http://fusionauth:9011'
    provision: true
  kong:
    provision: false
security:
  # JSON web tokens (HMAC only)
  jwt:
    secret: 78zabV4MFtspweovcC5D1dirQ5rnju67GJlSqGyuTAI=
    # In seconds (Default: 5 minutes)
    token-ttl: 1200
  # Fusion Auth specific options
  fusion:
    tenant:
      uuid: 340ba0db-90f5-4a7e-9cb5-7e26670f1717
    # The platform application
    application:
      # This is an UUID that can be provided to authentication requests to the login API
      uuid: 0afceebe-cfc6-4ddf-81b9-a7fd658b30d4
      oauth:
        clientSecret: Q0xyxiI1fN1w-Q1yj6nbLpaa-uzWFTxDXapGKGEIKB4
        redirect_urls:
          # OTP Workbench
          - 'http://localhost:8000/workbench/'
  roles:
    - name: ReadOnly
      superRole: false
      default: false
    - name: WriteOnly
      superRole: false
      default: false
    - name: DeleteOnly
      superRole: false
      default: false
  users:
    - username: ReadOnlyUser
      email: ReadOnlyUser@example.com
      password: 1234567890
      roles:
        - ReadOnly
    - username: WriteOnlyUser
      email: WriteOnlyUser@example.com
      password: 1234567890
      roles:
        - WriteOnly
    - username: DeleteOnlyUser
      email: DeleteOnlyUser@example.com
      password: 1234567890
      roles:
        - DeleteOnly

Hint

It is not mandatory for all configurations to be given in the configuration file. The tool has a default YAML with sensible defaults. For a complete set of configuration options, see the default.yaml in the tool source.

Note

Make sure the services addresses are correctly specified in the YAML configuration, otherwise the OPCTL CLI will not be able to provision them.

Limitations

Currently, OPCTL can only provision clean installations of FusionAuth and GraphDB. It does not support modifications of existing applications, users, or roles.

Authentication and Identity

FusionAuth provides several ways to authenticate.

This document analyses two options:

  • FusionAuth REST API
  • OAuth and login pages

Login API

FusionAuth exposes a REST endpoint /api/login that produces JWT access and refresh tokens when the login data in the request body is correct.

Example request body:

{
  "loginId": "admin@example.com",
  "password": "admin123",
  "applicationId": "10000000-0000-0002-0000-000000000001"
}

A request header X-FusionAuth-TenantId is also expected during the login request.

This type of login is suitable for use by other applications and services or by custom login forms.

Warning

Not providing the X-FusionAuth-TenantId header will cause FusionAuth to reject the request.

Note

Not providing applicationId in the request body is accepted. However, it will not trigger the JWT lambda, thus no application roles will be assigned in the JWT token.

See FusionAuth Login API for more information.

OAuth and Login Forms

This type of login is suitable when securing existing applications without having to implement custom logging forms. The implementation requirement is to handle the session, keep it in a cookie or in the local storage, and redirect to FusionAuth’s login when needed.

Example implicit flow:

  1. Upon loading, the application checks the presence of an access token in the URL or in the local storage.
  2. If present, it uses it as Authorization header.
  3. If not present, it performs a redirection to FusionAuth’s logging form.
  4. If the user credentials are correct, FusionAuth redirects back to the application with an access token in the URL.

Example redirect URL to FusionAuth:

http://example.com:9011/oauth2/authorize?client_id=<client-id>&redirect_uri=<redirect-uri>&response_type=token&tenantId=<tenant-id>

Where:

  • tenantId is the tenant ID
  • client_id is the application ID in which we are logging
  • redirect_url is the URL to which FusionAuth will redirect upon successful authentication

Note

The redirect_url should be one of the configured in the application’s OAuth settings. Otherwise, FusionAuth will reject the request.

Hint

The client_id corresponds to the application ID.

See FusionAuth OAuth for more information about OAuth in FusionAuth.

See FusionAuth login authentication workflows for more details on the different kinds of authentication flows.

Authorization

Platform Gateway

The Platform’s Kong API gateway must only authorize HTTP requests that include a valid JWT token. When security is enabled, only those requests that include a valid Authorization: Bearer {JWT} token header (signed with the configured signing key) are granted access. All other requests will be unauthorized.

See the Platform Gateway documentation for more information about configuring and deploying Kong.

Consumer JWT Token Authorization

To enable security, the API GW must authorize all HTTP requests by using the JWT plugin.

The Platform consumer should be set to use the JWT plugin with the same signing key used by the authentication/identity server FusionAuth. This is defined in the following section of Kong’s declarative configuration:

consumers:
  - username: ontotext-platform-consumer
    custom_id: ontotext-platform-consumer

jwt_secrets:
  - consumer: ontotext-platform-consumer
    key: "localhost"
    secret: "XXXXXXXXX"
    algorithm: HS256

Where:

  • jwt_secrets[0].key is the issuer, i.e., the domain. It will be validated for each JWT iss claim, and it should match the issuer in FusionAuth.
  • jwt_secrets[0].secret is the token key that is configured in FusionAuth and is used to sign and validate JWTs.

See Kong Create a JWT credential for more information.

Service JWT Token Authorization

After adding services and paths for the Platform, some of them need to be secured. For example, to secure all of SOaaS routes, you can active the JWT plugin like:

plugins:
  - name: jwt
    service: semantic-objects
    config:
      claims_to_verify: ["exp"]
      key_claim_name: iss

services:
  - name: semantic-objects

Where:

  • plugins[0].service corresponds to services[0].name.
  • plugins[0].config.key_claim_name configures the plugin to validate each JWT iss against jwt_secrets[0].key.

Note

FusionAuth is not issuing the nbf claim, so only exp is verified.

See Kong’s documentation for Enabling the plugin on a Service for more information.

Semantic Objects RBAC

Schema RBAC

The Semantic Objects Service manages a collection of Semantic Object schemas. It also manages access to these schemas using Role-Based Access Controls.

This section of the documentation does not discuss the SOML language and syntax, rather the Role-Based Access Controls that constrain access to the schemas.

RBACs are applied to the collection of schemas. The controls ensure those roles that can (Create/Update/Delete or Bind a particular Schema). RBACs are managed by using the Semantics Objects /soml-rbac REST API.

The Schema Storage & Management documentation explains the RBAC schema model and the REST API used to apply the RBACs.

Semantic Objects Schema with RBAC

The SOML RBAC documentation describes how you can declare Semantic Object and property Role-Based Access Controls.

Once the RBAC is declared and bound to a security-enabled Semantic Objects Service, GraphQL queries and mutation requests are authorized based on the request’s Authorization JWT token role claims.

Those requests that do not satisfy the RBAC are returned as unauthorized.

Tutorial

You can find more details how to use Semantic Objects RBAC in the RBAC Tutorial.

Managing Schemas

You can find more details on how to create/read/update/delete & bind schemas that contain RBACs in the Schema Storage & Management documentation.

Semantic Objects

RBACs can be enabled and disabled.

One configuration property controls if RBACs are turned on or off:

  • security.enabled to true or false

Another sets the JWT signing key that will be used to decode ‘Authorization: Bearer {JWT TOKEN}’ HTTP headers into role and username claims.

  • security.secret to the Platforms JWT signing key (FusionAuth and Kong)

Configuration can be applied by updating the Semantic Objects Service application.properties file. It can be provided to the Semantic Objects Service by using an environment variable.

Once the SOaaS is running with security enabled, all requests must include an Authorization HTTP header that includes a JWT token provided by the authentication flow.

The header should look like this:

"Authorization": "Bearer token"

Ontotext Platform Workbench

The Ontotext Platform Workbench is secured using an authorization code grant flow with JWTs and refresh tokens.

It manages JWT access and refresh tokens in the local storage under the workbench_access_token and workbench_refresh_token keys.

Note

When configuring the /oauth2 endpoint, make sure to not miss the “2” in the URL.

Note

See the Workbench documentation for more information about configurations and deploying.

GraphDB

GraphDB is secured separately from the rest of the Platform.

You can find instructions for securing GraphDB in its user documentation.

GraphDB repositories that are secured with a username and password can be easily accessed by the service. This is done by setting two configuration parameters. The combination of username and password will then be sent to the SPARQL endpoint as part of an authentication header.

sparql.endpoint.username: "username"
sparql.endpoint.credentials: "password"

This approach has been tested to work with RDF4J endpoints.

Administration

Docker Containers

This docker-compose.yaml configuration starts FusionAuth and Kong to enable authentication, authorization, and RBACs.

This .env file customizes the container environment.

And this Kong declarative configuration specifies services, routes, and JWT validation.

Note

Before deploying, check if the Kong configuration matches your services addresses.

Note

Notice the mounting of ./config/kong.yaml in the Kong service. This file should be present in that location, or the Docker Compose file have to be updated with the correct location of Kong’s declarative configuration.

To deploy the Docker Compose, use:

docker-compose up -d

Within about a minute, FusionAuth will be up and running behind the Kong API Gateway. You can access it on http://localhost:8000/admin.

You can also deploy the OPTCL CLI together with the security components to automate the provisioning instead of doing it manually.

Here are the minimal example opctl.yaml configuration and the example docker-compose-cli.yaml.

Note

Notice the mounting of the ./config/ folder. It should exist and contain the CLI configuration YAML, in this example named config.yaml, or the Docker Compose file have to be updated with the actual directory location.

You can deploy the two compose files together by using the following shell command:

docker-compose -f docker-compose.yaml -f docker-compose-cli.yaml up -d

To stop and remove all services, use:

# Without removing persisted data
docker-compose down

# With removing persisted data
docker-compose down --volumes

# In case the provisioning was deployed as well
docker-compose -f docker-compose.yaml -f docker-compose-cli.yaml down --volumes

Note

For installing and deploying the full Ontotext Platform, including security and monitoring, see the Installation section for available deployment scenarios.

Fusion Auth

Note

To configure FusionAuth automatically, follow the steps above. The steps described below cover the manual setup and configuration.

FusionAuth is an authentication and authorization provider. In the Ontotext Platform, it is used for user management, OAuth authentication, and JWT token issuer.

You can find the official installation requirements and tutorial here.

Setup wizard

After installing FusionAuth, you are redirected to a setup wizard page where a system administrator for FusionAuth is created. This system administrator will be able to configure tenants, applications, roles, and users.

../_images/fusion-setup-wizard.png

See the official documentation for a complete tutorial.

JWT Key Management

After completing the set-up wizard and having a system administrator, a JWT secret key should be generated (or imported) along with a JWT lambda for populating custom fields in the issued token.

Configuring a JWT Signing Key
  1. Go to System ‣ Key master.
  2. Generate new HMAC with the required level of encryption OR import the existing one.
  3. Get the secret text and save it for later.

This key will be used later for the tenant and application configuration, and the secret text to verify JWT tokens in the API gateway and in the SOaaS service.

Configuring JWT Lambda

FusionAuth lambdas are a technique to modify JWT tokens before issuing them. Ontotext Platform’s SOaaS expects to find a role claim in the JWT token.

  1. Go to System ‣ Lambdas.
  2. Create new JWT Populate lambda with the following content.
function populate(jwt, user, registration) {
   jwt.roles = registration.roles || [];
}

This lambda will be used when creating an application in FusionAuth.

Note

Lambdas are invoked only when application ID is provided during authentication. If skipped, they do not trigger.

See the FusionAuth documentation for more details on JWT populate lambda.

Tenant and application management

This is the main step in configuring security with FusionAuth.

Tenants are organizational units in which applications reside. FusionAuth by default has its own tenant and application after completing the setup wizard. However, for the purposes of the Ontotext Platform, you need to create a new tenant and application.

Creating a Tenant
  1. Go to System ‣ Tenants ‣ Create new tenant.

  2. Insert the tenant name. The ID can also be specified but it should be a UUID.

  3. In the General tab, select the issuer. This should be the domain where the Platform is deployed.

  4. In the JWT tab:

    • Specify the access and refresh token durations. Normally, the access token should be short-lived, e.g., 300 seconds.
    • For signing keys, select the key that was created earlier.

Examples:

  • JWT tab
../_images/creating-tenant.png
Creating an Application
  1. Go to Applications and start creating a new one.

  2. Enter the application name and select the tenant to which the application will belong. The ID can also be specified but it should be a UUID.

  3. In the Roles tab, you can specify a default set of roles:

    • Create an admin super role
    • Create a user default role
  4. In the OAuth tab:

    • Configure the authorized redirect URLs. This is mandatory, and only requests with the specified values will be allowed to log in.
    • Configure the enabled grants: Authorization Code, Implicit, and Refresh Token.
  5. In the JWT tab:

    • Specify the access and refresh token durations. Normally, the access token should be short-lived, e.g., 300 seconds.
    • For signing keys, select the key that was created earlier.
    • Select the lambda that was created earlier to enable token decoration.
  6. In the Security tab:

    • Deselect API key unless you plan to provide an API key with each request for authentication.
    • Allow refresh tokens.

Examples:

  • Roles
../_images/creating-application-1.png
  • OAuth
../_images/creating-application-2.png
  • JWT
../_images/creating-application-3.png
  • Security
../_images/creating-application-4.png

Information about creating an application can be found in the FusionAuth documentation.

User and Role management

After configuring a tenant and application for the Ontotext Platform, it is time to create roles, users, and registrations.

Application Roles

If default roles have not already been configured during application creation, you can still create them through the Manage roles button on the specific application dashboard.

Creating Users

Users are created per tenant.

  1. Go to Users ‣ Add user.
  2. Select the tenant. This should be the previously created tenant for the Ontotext Platform.
  3. Enter user data: username, email, and password. Save it.

You can create as many users as needed.

Creating User Registrations (Roles)

After users have been created, each one of them must be registered in a specific application:

  1. Go to Manage ‣ Registrations ‣ Add registration.
  2. Select the username for the registration. It can be the same username.
  3. Choose the application for which this registration will be performed (the Ontotext Platform application).
  4. Select the user’s roles for the application.

After completing this, the users can authenticate and the JWT lambda will be able to decorate tokens with application roles.

Theme management

  1. Go to System ‣ Themes ‣ Create new theme.
  2. Override the required FTL templates.
  3. Go to Applications ‣ Ontotext Platform.
  4. In the General tab, select the newly created theme.

The new theme will now be visible after loading the login screen for the application.

See the FusionAuth documentation for more information.

Monitoring

Health Checks

The Platform has an aggregate health check that checks all deployed services for their health status.

The __health endpoint can be accessed at http://{soaas_host}:{soaas_port}/__health.

An example response is as follows:

{
  "status": "OK",
  "healthChecks": [
    {
      "status": "OK",
      "id": "1200",
      "name": "SPARQL checks",
      "type": "sparql",
      "impact": "SPARQL Endpoint operating normally, writable and populated with data.",
      "troubleshooting": "http://localhost:9995/__trouble",
      "description": "SPARQL Endpoint checks.",
      "message": "SPARQL Endpoint operating normally, writable and populated with data."
    },
    {
      "status": "OK",
      "id": "1300",
      "name": "SOML Checks",
      "type": "soml",
      "impact": "SOML bound, service operating normally.",
      "troubleshooting": "http://localhost:9995/__trouble",
      "description": "SOML checks.",
      "message": "SOML bound, service operating normally."
    },
    {
      "status": "OK",
      "id": "1350",
      "type": "soml-rbac",
      "impact": "Security is disabled. SOML RBAC healthcheck is inactive.",
      "troubleshooting": "http://localhost:9995/__trouble",
      "description": "SOML RBAC checks.",
      "message": "Security is disabled. SOML RBAC healthcheck is inactive."
    },
    {
      "status": "OK",
      "id": "1400",
      "name": "Query service",
      "type": "queryService",
      "impact": "Query service operating normally.",
      "troubleshooting": "http://localhost:9995/__trouble",
      "description": "Query service checks.",
      "message": "Query service operating normally."
    },
    {
      "status": "OK",
      "id": "1500",
      "name": "Mutations Service",
      "type": "mutationService",
      "impact": "Mutation Service operating normally.",
      "troubleshooting": "http://localhost:9995/__trouble",
      "description": "Mutation Service checks.",
      "message": "Mutation Service operating normally."
    }
  ]
}

Good to Go

Platform has an aggregate good to go check that checks all configured services for good to go status.

The __gtg endpoint can be accessed at http://{soaashost}:{soaas_port}/__gtg.

An example response is as follows:

{
    "gtg": "OK"
}

Troubleshooting

FusionAuth Search Virtual Memory

Due to limitations in different Linux distributions, you might get the following error message when trying to run FusionAuth:

"max virtual memory areas vm.max_map_count [65530] is too low"

See how to resolve the issue here.