Link Search Menu Expand Document
Start for Free

OAuth 2.0 Integration

This page discusses Stardog’s support for OAuth 2.0 JWT Tokens as a means for authenticating users.

Page Contents
  1. Overview
  2. Configuring Stardog
    1. Example
  3. Usage
  4. User Management
    1. Role Mapping
      1. Mechanism 1: allowedGroupIdentifiers (and optionally rolesField)
      2. Mechanism 2: rolesClaimPath
      3. Reading Groups From Microsoft Graph
    2. Client Credentials For Stardog Server
    3. Configuring Superuser
    4. Username Templates
    5. Expiring Auto-Created Users
  5. OAuth 2.0 Identity Providers
    1. Azure Active Directory
      1. Configure Azure AD Stardog Server Application
      2. Configure Azure AD Client Application
      3. Azure Authentication and Token Creation
      4. Configure Stardog Server

Overview

Stardog can use OAuth 2.0 JWT Tokens for authentication and authorization. These tokens are normally obtained from an Identity Provider (IdP) by a web application or an authentication proxy. Stardog can also be configured to generate tokens for a user that has already authenticated with a username and password (basic authentication). This document describes the configuration changes that are needed to allow Stardog to issue JWT Tokens for users and optionally trust tokens issued by a given IdP.

Stardog expects the JWT access token to be in the Authorization HTTP header with the format bearer <token>.

Configuring Stardog

By default, starting in version 7.8.0, Stardog is configured to issue authentication tokens. In order to provide customization and to increase the security of authenticating with these tokens through the use of secrets, you will need to include the following property in stardog.properties:

Property Updatable Description
jwt.conf No Absolute path to a valid jwt.yaml file

The jwt.conf property must point to a valid YAML file with the following schema:

confVersion: string # (Optional) The version of the configuration file; currently `1.0`.
deploymentName: string # (Optional) Name for this deployment.
autoDeleteUsersSchedule: string # (Optional) Cron schedule for removing auto-created users (e.g., "0 0/30 * * * ?" for every 30 minutes)

# Signer allows Stardog to sign the tokens that it issues.
signer:
  algorithm: [ HS256 | HS384 | HS512 | RS256 | RS384 | RS512 ] # Algorithm type to sign with.
  audience: string # (Optional) Audience to include as aud field, default "stardog".
  issuer: string # This is the name of the local issuer and will be automatically added to issuers.
  secret: string # (Required for HMAC only) secret key used to sign tokens.
  publicKey: string # (Required for RSA only) Absolute path to an RSA public key.
  privateKey: string # (Required for RSA only) Absolute path to an RSA private key.
  tokenTTL: string # (Optional) ISO-8601 duration format (https://en.wikipedia.org/wiki/ISO_8601), default "P7D".

# Issuers are used to configure external identity providers. There should be an entry for each issuer that is trusted.
issuers:
  [ url ]: # The URL of the IdP to trust. Should match the iss claim in the token. Example https://url-of-idp-to-trust.
    audience: string # The client id of the Stardog server. Limits trust to tokens with a matching aud claim.
    # Use usernameField OR usernameTemplates to override the default username claim (sub).
    usernameField: string  # (Optional) The claim to use as the username, defaults to sub claim.
    usernameTemplates: array # (Optional) List of claims templates to use for mapping username. e.g. [ "user_{sub}", "app_{azp}" ]
    autoCreateUsers: boolean # (Optional) true will create new users in Stardog, defaults to false.
    roleMappingSource: string # [ token | azure_groups ] Source for mapping Stardog roles. Defaults to token.
    groupPrefix: string # (Optional) Used when roleMappingSource is azure_groups. Azure group prefix to remove during role mapping. Defaults no prefix.
    allowedGroupIdentifiers: array # (Optional) The groups that are allowed to be mapped to Stardog roles.
    rolesField: string # (Optional) The roles claim; used together with allowedGroupIdentifiers.
    rolesClaimPath: string # (Optional) The path to the roles claim; used instead of rolesField/allowedGroupIdentifiers.
    superuserGroup: string # (Optional) The OAuth group to map to the superuser designation.

    # The following 4 properties apply when roleMappingSource is set to azure_groups and when using pass-through authentication.
    azureGraphPermission: string: # [ User.Read, User.Read.All, GroupMember.Read.All, Group.Read.All, Directory.Read.All, Directory.ReadWrite.All ]
                                  # The permission to request when obtaining an access token for Microsoft Graph. Defaults to Directory.Read.All.
    # When roleMappingSource is set to azure_groups, clientSecret or both clientCertificatePath and clientCertificatePassword are required.
    clientSecret: string # The client secret for the Azure-registered application for the Stardog server.
    clientCertificatePath: string # The client certificate for the Azure-registered application for the Stardog server.
    clientCertificatePassword: string # Password for the certificate file pointed to by clientCertificatePath.

    # algorithms object is optional. By default Stardog will use the URL of the issuer to query the
    # issuer's public key information at the address <issuer URL>/.well-known/jwks.json.
    algorithms:
      [ HS256 | HS384 | HS512 ]: # Valid HMAC encryption types, see the signer fields.
        secret: string # (Required) Secret key used to sign tokens.
      [ RS256 | RS384 | RS512 ]: # Valid RSA encryption types.
        # Either keyUrl or publicKey must be provided but not both.
        keyUrl: string # URL to fetch jwks signing information from.
        publicKey: string # Absolute path to an RSA public key.
        privateKey: string # Absolute path to an RSA private key.

The license UUID is used as part of the signing key; therefore, the same license must be used on every node in the cluster. If the license uuid is different on the nodes, the token will only work against the node that generated it.

Example

Here’s an example stardog.properties file:

jwt.conf = /var/opt/stardog/jwt.yaml

This properties file points to a valid YAML file specified by the jwt.conf property. Here is an example:

---
confVersion: "1.0"
deploymentName: stardog-server

# This allows Stardog to issue a token for authentication against itself.
signer:
  algorithm: HS256
  audience: my-stardog
  secret: "this-should-be-randomly-generated-secret-key"
  issuer: http://my-domain.com
  tokenTTL: "P30D"

issuers:
  # An example of Azure auth that requires a special `keyUrl`
  https://login.microsoftonline.com/<azure-tenant-id>/v2.0:
    usernameField: email
    audience: <azure-client-id>
    algorithms:
      RS256:
        keyUrl: https://login.microsoftonline.com/<azure-tenant-id>/discovery/v2.0/keys

  # An example using apps.stardog.com
  https://apps.stardog.com:
    usernameField: username
    audience: https://fqdn.of.stardog:5820

  # An example of an IdP that supports the '.well-known' URLs
  https://my-domain.auth0.com/:
    audience: <auth0-client-id>
    usernameField: email

Usage

Stardog will issue a token if you provide a valid username and password with basic auth.

$ curl -u anonymous:anonymous https://express.stardog.cloud:5820/admin/token
{"token": "..."}

Once you have obtained a valid token, you can call a properly configured Stardog via the HTTP API:

$ export BEARER_TOKEN=<insert valid token here>
$ curl -H "Authorization: bearer ${BEARER_TOKEN}" https://express.stardog.cloud:5820/admin/users
{"users": ["anonymous"]}

User Management

For a user to connect via an external Identity Provider (IdP) OAuth Token, either that user should already exist in the Stardog user system, or the autoCreateUsers property should be set to true. Existing usernames should match what is being returned in the claim specified by the usernameField property for the Issuer.

When autoCreateUsers is set to true, Stardog will check for an existing user with the username taken from the value of the claim specified by the usernameField field. If the user does not exist, the token must include at least one role for the user and that role must already exist in Stardog. If there are matching roles, Stardog will create the new user. If a new user does not have an existing role, the user will not be created and authentication will fail. See Expiring Auto-Created Users for setting up a schedule for removing auto-created users.

Note that auto-created users cannot be assigned roles within Stardog, even by a superuser. Their roles will always be managed by the role mapping process described above. This is to ensure there is a single source for managing the roles of a user and that the administrators do not need to update multiple places to manage a user’s role.

See Managing Users and Roles for more information.

Role Mapping

Stardog achieves authorization through OAuth by mapping groups from the IdP to Stardog roles. These IdP groups can be sourced from the JWT token or, in the case of Azure, directly from the IdP through an additional callback to the Microsoft Graph API.

For Azure, it is recommended to map roles from Azure’s App Roles because these roles are returned in the token in human-readable format (whereas directory groups are returned as UUIDs, by default). When mapping roles from Azure AD groups, configure Stardog to callback to Microsoft Graph by setting roleMappingSource: azure_groups in the yaml file. See Reading Groups From Microsoft Graph for details on configuring this option.

When mapping roles from a groups or roles claim in a JWT token, Stardog provides two mechanisms for specifying how it should read the roles claim that an IdP embeds in its tokens. The first method is to define the allowedGroupIdentifiers property (and optionally the rolesField property); the second method is to define the rolesClaimPath property.

If both the allowedGroupIdentifiers and rolesClaimPath properties are specified, then the rolesClaimPath is used, and the allowedGroupIdentifiers and rolesField properties are ignored.

Mechanism 1: allowedGroupIdentifiers (and optionally rolesField)

The rolesField property specifies the name of the claim in the token that contains roles to be mapped to Stardog roles. If the rolesField property is not specified in the issuer definition, a default value of "stardogRoles" is used.

If the value associated with the rolesField claim is a string array, Stardog will look at each string in the array and include it in the set of requested Stardog roles (if that string is listed in the allowedGroupIdentifiers list).

If the value associated with the rolesField is a map, Stardog requires the keys in the map be strings and the value for each key be an array of strings. For each key (the group identifier) that is included in allowedGroupIdentifiers, Stardog includes the strings from its value array in the set of requested Stardog roles.

If no roles match any of the strings specified in the string arrays for each allowedGroupIdentifier, the associated user will not be assigned any permissions in Stardog.

In the following example, only the AD groups readers and writers will be allowed to match Stardog roles.

allowedGroupIdentifiers: [ readers,writers ]

Mechanism 2: rolesClaimPath

The rolesClaimPath property specifies a JSON path to the roles being claimed. This is based on the format Keycloak uses for specifying a claim it adds to a JWT:

Name of the claim to insert into the token. This can be a fully qualified name like address.street. In this case, a nested JSON object will be created. To prevent nesting and use the dot character literally, escape the dot with a backslash. (See the Keycloak server admin documentation for more information.)

For example, setting rolesClaimPath: the.best.roles, Stardog expects a JWT from the IdP to look something like:

{
  "iss": "https://my.idp.server",
  "the": {
    "best": {
      "roles": [ "reader", "writer"]
    },
  },
  <more claims>
}

and Stardog would add reader and writer to the requested Stardog roles.

It is possible to embed a period (.) in the JSON path by escaping it with a backslash. For example, with rolesClaimPath: stardog\.com.great\.roles, Stardog would expect the JWT from the IdP to look something like:

{
  "iss": "https://my.idp.server",
  "stardog.com": {
    "great.roles": [ "reader", "writer"]
  },
  <more claims>
}

Similarly to the previous example, Stardog would add reader and writer to the requested Stardog roles.

Reading Groups From Microsoft Graph

When mapping to administrative groups in Azure, if the groups are formatted as UUIDs in the JWT, you can configure Stardog to call back into Microsoft Graph to obtain the human-readable name of the groups. To enable this, set roleMappingSource: azure_groups in the yaml file.

Calling Microsoft Graph requires client credentials for the Stardog server. See below for configuration instructions.

By default, the user must be granted Directory.Read.All in order to call the Graph API. This can be overridden by setting azureGraphPermission to one of User.Read, User.Read.All, GroupMember.Read.All, Group.Read.All, Directory.Read.All, Directory.ReadWrite.All, depending on the privileges of the user.

Client Credentials For Stardog Server

Stardog uses Microsoft’s on-behalf-of flow to implement OAuth token exchange when accessing secured resources on the user’s behalf. This is done when calling Microsoft Graph to obtain group membership or when using pass-through authentication to access virtual resources.

To configure on-behalf-flow, a client credential, in the form of a client secret or a client certificate, must be configured for the Stardog server. To configure a client secret, set the clientSecret property to the value of the client secret. To configure a certificate, set the clientCertificatePath to the location to a server-accessible certificate file and set the clientCertificatePassword to the password for that certificate file.

Configuring Superuser

When mapping OAuth groups or roles to Stardog roles, you can identify a particular OAuth group/role that indicates that the user is a superuser. To do this, set the superuserGroup property to the desired group/role.

Username Templates

The usernameField property of the jwt.yaml file directly maps the value of a single claim to a Stardog username. Only one claim can be specified per issuer. There are some use cases where this is not flexible enough. The ability to include a prefix or suffix can be useful in the case where there are multiple issuers. By prefixing the claim value with a unique string, it’s possible to guarantee the usernames from multiple issuers do not clash. Alternatively, in the case where a single issuer can present claims with different schemas (as can happen with different client types - web application, native app, SPA, etc.), it’s possible no one claim is present in all tokens.

For these use cases, the usernameTemplates property can be used in place of the usernameField property. The usernameTemplates property is an array of templates, where each template defines a username format. Stardog will attempt to resolve each template in turn until a template is found where all its referenced claims are present in the token.

The format of a template is a string containing one or more claim references enclosed in braces, e.g. "abc_{myclaim1}_{myclaim2}_xyz".

A complete example is: usernameTemplates: [ "user_{sub}", "app_{azp}" ]. For this property and the following token, the username will be user_a_user, because all the claims referenced in the first template are present in the token.

{
  "iss": "https://my.idp.server",
  "sub": "a_user",
  "azp": "a_service",
  <more claims>
}

Expiring Auto-Created Users

As described in User Management, when autoCreateUsers is set to true, Stardog automatically creates user accounts for users that are authenticated by the identity provider and do not already exist in the Stardog system. By default, these users will remain in the Stardog system permanently, even if they are removed from the identity provider. Auto-created users cannot be authenticated with Stardog basic security, so once they cannot be authenticated by OAuth, they will not be able to access Stardog. However, by default, auto-created users will appear in the list of users until they are manually removed.

Auto-created users can be configured to be removed from Stardog according to a schedule by setting the autoDeleteUsersSchedule property in the yaml config file. This property has a Quartz cron format, as described here. When configured, all auto-created users will be removed from the system. They will be automatically recreated the next time they authenticate.

Note, Stardog does not allow assigning auto-created users to Stardog security groups, but it does permit granting explicit permissions to them. These permissions will be lost when the user is removed. Therefore, when using the auto-created user remover, only assign explicit permissions to manually created users.

OAuth 2.0 Identity Providers

Stardog supports OAuth 2.0 authentication using tokens from supported identity providers. This section provides information about configuring and using them.

Azure Active Directory

Stardog can use OAuth 2.0 JWT Tokens generated by Azure AD for authentication against existing users or optionally create new users. There are several ways, known as flows, that can be used to obtain tokens. This documentation explains how to set up AD authentication using authorization code flow and configure role-based access using a token with app roles.

You can find more information on Azure Active Directory and the Microsoft identity platform here.

Configure Azure AD Stardog Server Application

Register an application for the Stardog server.

  • In your Azure portal go to Home→App Registrations and click New Registration to add a new application.
  • Take note of the Application (client) ID and the Directory (tenant) ID.
  • Add any necessary client credentials and generate a client secret.
  • Under Authentication, add a Mobile and Desktop platform configuration.
  • Add a redirect URL of http://localhost.
  • If you will be implementing virtual graph credentials pass through, click API permissions and add user_impersonation scope for AzureDatabricks.
  • If you will be looking up roles via Microsoft Graph (roleMappingSource: azure_groups yaml entry), click API permissions and add Directory.Read.All scope for Microsoft Graph.
  • For any API permissions granted to the server, consider granting admin consent on behalf of users. Omitting this step will require each user to grant consent using an interactive flow, e.g., this method.
  • Click Expose an API, add a scope, any name will do (user_login for this example).

If you will be mapping Stardog roles from Azure App Roles (recommended):

  • Click on Token configuration, click Add groups claim, check Groups assigned to the application, click Add
  • From the portal go to Home→Azure Active Directory→Enterprise Applications and confirm your application is there, add it if it is not.
  • Click your application and then Users and Groups, then Add user/group and add the user/role pairings as needed.

Configure Azure AD Client Application

Register an application for the client that will be accessing Stardog. If you have an existing Azure application you can skip these steps.

  • In your Azure portal go to Home→App Registrations and click New Registration to add a new application.
  • Take note of the Application (client) ID and the Directory (tenant) ID.
  • Under Authentication, add a platform configuration (Web app, or Mobile and Desktop app).
  • Add any necessary client credentials and generate a client secret.
  • Add a redirect URL of http://localhost.
  • Under API Permissions, add a permission for the Stardog server, including the scope defined in the last step (user_login, if you are following the example). Also, add scopes under Microsoft Graph for openid, email, and profile. If you configured Stardog to lookup roles using Microsoft Graph (roleMappingSource: azure_groups yaml entry), add a Microsoft Graph scope for Directory.Read.All. If you will be using Virtual Graph pass-through authentication, add a scope under Azure Databricks for user_impersonation.

Azure Authentication and Token Creation

The following steps illustrate the steps that your application would take in order to obtain a bearer (access) token for Stardog.

  • Use your browser to navigate to the authorization endpoint URL that you noted above, filling in your tenant and client ids and sign in using your application credentials. The state value can be any random string. The nonce value is also a random string and is optional.
https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/authorize?client_id=<client client_id>&redirect_uri=http%3A%2F%2Flocalhost&response_type=code&scope=openid%20api%3A%2F%2F<stardog client_id>%2Fuser_login&nonce=<nonce value>&state=<state value>
URL Parameter Value
<tenant_id> The directory/tenant ID for your Azure account
client client_id The application/client ID for your client application
redirect_uri http://localhost URL encoded
response_type id_token
scope openid api://<stardog client id>/<Stardog exposed scope>, all URL encoded
state A random string, used to ensure the response from the IdP is genuine
nonce Another random string, used to bind your client to the returned token

The Microsoft authorize endpoint will prompt the user to log in and if this is the first time the user has requested access to this resource (Stardog), they will be presented with a one-time consent form to grant your client access to Stardog. Once completed, the Microsoft site will redirect your browser to the redirect URL for your client (http://localhost), which will appear to be not found, which is expected. The useful information will be included in the query parameters of the redirect URL:

http://localhost/?code=0.ARcAZsok_6q7...shortened...oUhaHYbr-ti6mHG&state=<your state value>&session_state=9b34f81b-2663-4fe0-ac55-44eb2b09969a#

The two important query parameters are the state and the code. For security purposes, verify that the returned state matches the state in the request. Then copy the code into the following curl POST request for exchanging the authorization code for your tokens:

curl -s -X POST -H 'Content-Type: application/x-www-form-urlencoded' \
https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/token \
-d 'client_id=<client client_id>' \
-d 'scope=api%3A%2F%2F<Stardog client_id>%2Fuser_login' \
-d 'redirect_uri=http%3A%2F%2Flocalhost' \
-d 'code=0.ARcAZsok_6q7...shortened...oUhaHYbr-ti6mHG' \
-d 'grant_type=authorization_code' \
--data-urlencode 'client_secret=<client client secret>' | jq

Note that the client_secret may be required depending upon the application type of your client. If it is a web application, the client secret will be assumed to be private and so will be required. For single page applications, or native or mobile applications, it will not be required.

The response will contain two tokens. The id_token can be used by the client application to authenticate the user’s identity. The access_token should be used when authenticating with Stardog. Note, while an id token can be used with Stardog in some scenarios, the access token is designed for this purpose, and is required for use cases that rely on token exchange using the On-Behalf-Of flow such as virtual graph credentials pass through and role discovery using Microsoft Graph.

Each of these tokens can be decoded and validated using an online JWT debugger such as https://jwt.io/.

Configure Stardog Server

This example JWT config expects to find existing Stardog usernames in the preferred_username token claim and an array of roles in the roles claim.

confVersion: "1.0"
deploymentName: stardog-server

issuers:
  https://login.microsoftonline.com/<azure-tenant-id>/v2.0:
    audience: <Stardog client-id>
    usernameField: preferred_username
    rolesField: roles
    algorithms:
      RS256:
        keyUrl: https://login.microsoftonline.com/<azure-tenant-id>/discovery/v2.0/keys

Fill in <azure-tenant-id> and <Stardog client-id> with the values noted from above. Restart Stardog and authenticate using the token as described above.