JSON Web Tokens

Okera can use JSON Web Tokens (JWT) for authentication. These tokens can either be generated externally and provided to ODAS, or else ODAS can be configured to work with an external service (via REST) to acquire and validate JWTs. If only JWTs are used for authentication, ODAS also requires that a system token be generated for use in authentication with internal services. This is typically a token with okera as the subject.

Okera supports the standard JWT claims including:

  • sub
  • exp
  • nbf

Okera requires that JWTs have a sub claim. For specifying groups that the token subject is a member of, Okera suggests using the claim groups and storing the associated value as a list of strings.

Example JWT payload:

{
  "sub": "John Doe",
  "iss": "okera.com",
  "groups": [
    "web_user",
    "philatelist",
    "cat_person"
  ],
  "exp": 1590510807
}

ODAS can be configured for JWT support via two approaches:

  1. Providing services with both the public key used to verify the tokens and the algorithm that was used (RSA256, RSA512, etc.).
  2. Configuring an endpoint for validating tokens.

For either of these approaches, if you are using JWT, you will need to provide a system token that ODAS uses internally for inter-service communication.

Configuration Settings

The following configuration settings are used to configure JWT support:

  • ENABLE_JWT
  • JWT_ALGORITHM
  • JWT_PUBLIC_KEY
  • SYSTEM_TOKEN
  • JWT_AUTHENTICATION_SERVER_URL

Defaults with okctl

If the ENABLE_JWT value is set to true in the configuration file and no other JWT configuration value is used, okctl will generate a private/public key and system token (using RS512 algorithm) in the current directory:

  • .auth/id_rsa - the JWT private key
  • .auth/id_rsa.pub - the JWT public key
  • .auth/system.token - the system token (a JWT with sub of okera and groups of root).

It will then set the following values automatically when updating the cluster configuration:

JWT_PUBLIC_KEY: file:///path/to/current/dir/.auth/id_rsa.pub
JWT_ALGORITHM: "RSA512"
SYSTEM_TOKEN: file:///path/to/current/dir/.auth/system.token

You can disable this behavior by removing the ENABLE_JWT setting or specifying your own values for these settings.

Public Key Validation

To configure the public key approach for validation, the setting JWT_PUBLIC_KEY, should be a full path to the public key.

Note: This key must be in OpenSSL PKCS#8 format.

To configure the algorithm, the setting JWT_ALGORITHM must be set to a string indicating the algorithm used. Currently, supported algorithms are RSA256 and RSA512.

For example, set the following settings in the configuration file:

JWT_PUBLIC_KEY: file:///etc/id_rsa.512.pub
JWT_ALGORITHM: RSA512

ODAS supports configuring multiple keys to use for validating JWTs passed in by users. This is accomplished by specifying the keys in a comma-delimited list. When a token is passed in, each key will be used to attempt to validate the token, with the token considered valid as soon as one of the specified keys matches.

Note: There must be the same number of algorithms specified as keys and the algorithm order must correspond to the key order

For example:

JWT_PUBLIC_KEY: file:///etc/id_rsa.512.pub,file:///etc/external_vendor.256.pub
JWT_ALGORITHM: RSA512,RSA256

Remote Endpoint Validation

To configure the remote endpoint approach for validation, configure an endpoint for validating tokens remotely by way of the JWT_AUTHENTICATION_SERVER_URL setting.

For example:

JWT_AUTHENTICATION_SERVER_URL: http://10.1.10.1:8000/idp/userinfo.openid

The call from Okera to the REST endpoint is a POST request that passes the JWT to validate as a bearer token and expects JSON as the return value. As a REST call, it looks like this:

curl -X POST -H 'Accept: application/json' -H 'Authorization: Bearer <token>' http://<ip>:<port>/<endpoint>

The return value must contain the key "sub" and the value must be a string that contains the username that corresponds to the passed token. Example:

{
    "sub": "santa@okera.com"
}

Using Both Approaches for JWT Validation

If you have the requirement to support both approaches, configure the settings for both, and each is instantiated. The external endpoint is used first. If the JWT is not validated by that service, it is passed to the public-key authenticator for validation.

System Token

To configure ODAS to be able to do inter-service communication when JWT authentication is enabled, the setting SYSTEM_TOKEN must be set to the full path of the token to use.

For example:

SYSTEM_TOKEN: file:///path/to/system.token

This token should have a sub value of okera.

Using okctl

okctl comes with a few utility commands to help with token management and creation.

  1. okctl tokens init can be used to create a new public/private key pair and the system token:

    $ okctl tokens init
    2019/09/01 06:15:03 Private Key generated
    2019/09/01 06:15:03 Public key generated
    2019/09/01 06:15:03 Key saved to: .auth/id_rsa.pub
    2019/09/01 06:15:03 Key saved to: .auth/id_rsa
    2019/09/01 06:15:03 System token saved to: .auth/system.token
    
  2. okctl tokens create <username> [<groups>...] can be used to create a new token with a particular username and groups, using the public/private key pair in .auth/:

    $ okctl tokens create analyst analyst_group
    2019/09/01 06:17:06 Token saved to: .auth/analyst.token
    2019/09/01 06:17:06 Token: eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbmFseXN0IiwiaXNzIjoiMTkyLjE2OC4xMC44IiwiZ3JvdXBzIjpbImFuYWx5c3RfZ3JvdXAiXSwiZXhwIjoxNTc1OTgzODI2fQ.uvUSihlSfFbs4AbiU8Mldr9THG_QLuha9VJJ6LUTzznLaKNqUbsDIZWIjMPnKFc0vXrlM5VLc0onQLg8ICbquZ-Kq4O9tA91UlaOAdzLaxkUUZKYaHA85ikPBDNw-TeIy9OAQFTsATrIECPIH6EoaJ5VevyMBXXhOJ6cmSUiSIA3ozFF2qxjDr6ZHb4ciazwRyNdTKmumO5iQXU_FwUmGZc0UeaGHkXMvYcQh5p7DI0V8T8DRz8xg1mi4fkbcXEo8EFN9b3vP82xd5HaTlAt-2IZYE7NQU0UFMsSKxeLZswGT_sKkbb1DLYUwGiu28dXEQWrpfhDugHBu5FeVBVNRkBjtwEsAaycBYnEALUvxRWO77Sz-VPn2CucJ6hC_YoMQr54IVtBx7n6B67j03TrUyGwnZJjqndESnNQQ7ig8U_Ah-moNzQEzRjWT26xrj9FyF7nbQH7m3-FQMMIFreHGl99ykxxUj5lCvd4KQOqTxIxn0wxxzz7deCdcK73uH6FQ1xI8xvjrlTUHzGeJcvDPU_jEc48OhNRGpApEY_ee0Kkkt1XzwRc-MQrnW8HKsPUEJgyTWi9AAkzUXpzttvgLWmsenMbj2jmkpo0cD2ym25R7ckjqcPmuqq9Zpn7wbLFwLBYah29aRd9qtUQNr24f48ERfP0OhvpjiuMBGV3piE
    

    This token will be saved in .auth/<username>.token.

  3. okctl tokens show <username> can be used to show a token created using okctl tokens create:

    $ okctl tokens show analyst
    2019/09/01 06:18:17 Token: eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbmFseXN0IiwiaXNzIjoiMTkyLjE2OC4xMC44IiwiZ3JvdXBzIjpbImFuYWx5c3RfZ3JvdXAiXSwiZXhwIjoxNTc1OTgzODI2fQ.uvUSihlSfFbs4AbiU8Mldr9THG_QLuha9VJJ6LUTzznLaKNqUbsDIZWIjMPnKFc0vXrlM5VLc0onQLg8ICbquZ-Kq4O9tA91UlaOAdzLaxkUUZKYaHA85ikPBDNw-TeIy9OAQFTsATrIECPIH6EoaJ5VevyMBXXhOJ6cmSUiSIA3ozFF2qxjDr6ZHb4ciazwRyNdTKmumO5iQXU_FwUmGZc0UeaGHkXMvYcQh5p7DI0V8T8DRz8xg1mi4fkbcXEo8EFN9b3vP82xd5HaTlAt-2IZYE7NQU0UFMsSKxeLZswGT_sKkbb1DLYUwGiu28dXEQWrpfhDugHBu5FeVBVNRkBjtwEsAaycBYnEALUvxRWO77Sz-VPn2CucJ6hC_YoMQr54IVtBx7n6B67j03TrUyGwnZJjqndESnNQQ7ig8U_Ah-moNzQEzRjWT26xrj9FyF7nbQH7m3-FQMMIFreHGl99ykxxUj5lCvd4KQOqTxIxn0wxxzz7deCdcK73uH6FQ1xI8xvjrlTUHzGeJcvDPU_jEc48OhNRGpApEY_ee0Kkkt1XzwRc-MQrnW8HKsPUEJgyTWi9AAkzUXpzttvgLWmsenMbj2jmkpo0cD2ym25R7ckjqcPmuqq9Zpn7wbLFwLBYah29aRd9qtUQNr24f48ERfP0OhvpjiuMBGV3piE
    

Note

If you have your own pre-existing public/private key pair and would like to use okctl to create tokens, you can put those in .auth/id_rsa and .auth/id_rsa.pub for the private and public keys respectively, and okctl will use them when creating tokens.

Group Resolution when using JWTs

When a request is authenticated with JWTs, the following sequence is used to determine what groups this request will use for the authenticated user:

  1. If the JWT contains a groups field, then the value of this field will be used as the set of groups.
  2. If an AD/LDAP group resolver is defined, then the sub field of the JWT will be used as the user passed to the resolver.
  3. If an endpoint-based group resolver is defined, then the sub field of the JWT will be used as the user passed to the resolver.