# JSON Web Tokens (JWT) Authentication

Slurm provides a RFC7519 compliant implementation of JSON Web Tokens (JWT). This authentication can be used as an AuthAltType, usually alongside auth/munge as the AuthType. The only supported communication direction is from a client connecting to slurmctld and slurmdbd. This means that certain scenarios (specifically interactive jobs using srun) are currently not supported for clients with auth/jwt enabled (or that have SLURM_JWT in their environment).

## Prerequisites

JWT requires libjwt. Both the library and the development headers must be available when Slurm is compiled.

## Setup

1. Configure and build Slurm for JWT support
2. Add JWT key to controller in StateSaveLocation: Here is an example with StateSaveLocation=/var/spool/slurm/statesave/

       dd if=/dev/random of=/var/spool/slurm/statesave/jwt_hs256.key bs=32 count=1
       chown slurm:slurm /etc/slurm/jwt_hs256.key
       chmod 0600 /etc/slurm/jwt_hs256.key
       chown root:root /etc/slurm
       chmod 0755 /etc/slurm

3. Add JWT as an alternative authentication in slurm.conf and slurmdbd.conf:

       AuthAltTypes=auth/jwt
       AuthAltParameters=jwt_key=/etc/slurm/jwt_hs256.key

4. Restart slurmctld
5. Create tokens for users as desired:

       scontrol token username=$USER

   An optional lifespan=$LIFESPAN option can be used to change the token lifespan from the default 1800 seconds. The root account, or SlurmUser account can be used to generate tokens for any user. Alternatively, a user may use the command to generate tokens for themselves by simply calling

       scontrol token

   Note that administrators can prevent users from generating tokens by setting the following parameter in slurm.conf:

       AuthAltParameters=disable_token_creation

   This functionality is provided to allow sites to control when and how users are provided tokens along with controlling the token lifespans.
6. Export the SLURM_JWT environment variable before calling any Slurm command.

## Compatibility

Slurm uses libjwt to view and verify RFC7519 JWT tokens. Compliant tokens generated by another solution can be used as long as the following requirements are met:

1. Required tokens for Slurm are present:
   - iat: Unix timestamp of creation date.
   - exp: Unix timestamp of expiration date.
   - sun: Slurm UserName ( POSIX.1-2017 User Name ).
2. Tokens are signed with HS256 algorithm compliant to RFC7518. No other algorithms are currently supported by Slurm.
3. Signing key is provided to slurmctld and slurmdbd to allow decryption of the tokens. Slurm currently only supports a single signing key.

The following scripts require the installation of the JWT Python module. This script can serve as an example of what you might do to generate a jwt key for use with Slurm.

    #!/usr/bin/env python3
    import sys
    import os
    import pprint
    import json
    import time
    from datetime import datetime, timedelta, timezone

    from jwt import JWT
    from jwt.jwa import HS256
    from jwt.jwk import jwk_from_dict
    from jwt.utils import b64decode,b64encode

    if len(sys.argv) != 3:
        sys.exit("gen_jwt.py [user name] [expiration time (seconds)]");

    with open("/etc/slurm/jwt.key", "rb") as f:
        priv_key = f.read()

    signing_key = jwk_from_dict({
        'kty': 'oct',
        'k': b64encode(priv_key)
    })

    message = {
        "exp": int(time.time() + int(sys.argv[2])),
        "iat": int(time.time()),
        "sun": sys.argv[1]
    }

    a = JWT()
    compact_jws = a.encode(message, signing_key, alg='HS256')
    print("SLURM_JWT={}".format(compact_jws))

Similarly, the following script can be used as an example of how you might verify that a jwt key is valid for use with Slurm.

    #!/usr/bin/env python3
    import sys
    import os
    import pprint
    import json
    import time
    from datetime import datetime, timedelta, timezone

    from jwt import JWT
    from jwt.jwa import HS256
    from jwt.jwk import jwk_from_dict
    from jwt.utils import b64decode,b64encode

    if len(sys.argv) != 2:
        sys.exit("verify_jwt.py [JWT Token]");

    with open("/etc/slurm/jwt.key", "rb") as f:
        priv_key = f.read()

    signing_key = jwk_from_dict({
        'kty': 'oct',
        'k': b64encode(priv_key)
    })

    a = JWT()
    b = a.decode(sys.argv[1], signing_key, algorithms=["HS256"])
    print(b)

Last modified 8 June 2021