# Token Signing Built-ins

| Function | Description | Meta |
| --- | --- | --- |
| `io.jwt.encode_sign` | `output := io.jwt.encode_sign(headers, payload, key)`  Encodes and optionally signs a JSON Web Token. Inputs are taken as objects, not encoded strings (see `io.jwt.encode_sign_raw`).  **Arguments:**  `headers` (object\[string: any\])  JWS Protected Header  `payload` (object\[string: any\])  JWS Payload  `key` (object\[string: any\])  JSON Web Key (RFC7517)  **Returns:**  `output` (string)  signed JWT | SDK-dependent |
| `io.jwt.encode_sign_raw` | `output := io.jwt.encode_sign_raw(headers, payload, key)`  Encodes and optionally signs a JSON Web Token.  **Arguments:**  `headers` (string)  JWS Protected Header  `payload` (string)  JWS Payload  `key` (string)  JSON Web Key (RFC7517)  **Returns:**  `output` (string)  signed JWT | SDK-dependent |

OPA provides two builtins that implement JSON Web Signature [RFC7515](https://datatracker.ietf.org/doc/html/rfc7515) functionality.

`io.jwt.encode_sign_raw()` takes three JSON Objects (strings) as parameters and returns their JWS Compact Serialization. This builtin should be used by those that want maximum control over the signing and serialization procedure. It is important to remember that StringOrURI values are compared as case-sensitive strings with no transformations or canonicalizations applied. Therefore, line breaks and whitespaces are significant.

`io.jwt.encode_sign()` takes three Rego Objects as parameters and returns their JWS Compact Serialization. This builtin should be used by those that want to use rego objects for signing during policy evaluation.

info

Note that with `io.jwt.encode_sign` the Rego objects are serialized to JSON with standard formatting applied whereas the `io.jwt.encode_sign_raw` built-in will **not** affect whitespace of the strings passed in. This will mean that the final encoded token may have different string values, but the decoded and parsed JSON will match.

The following algorithms are supported:

*   `ES256`: ECDSA using P-256 and SHA-256
*   `ES384`: ECDSA using P-384 and SHA-384
*   `ES512`: ECDSA using P-521 and SHA-512
*   `HS256`: HMAC using SHA-256
*   `HS384`: HMAC using SHA-384
*   `HS512`: HMAC using SHA-512
*   `PS256`: RSASSA-PSS using SHA256 and MGF1-SHA256
*   `PS384`: RSASSA-PSS using SHA384 and MGF1-SHA384
*   `PS512`: RSASSA-PSS using SHA512 and MGF1-SHA512
*   `RS256`: RSASSA-PKCS-v1.5 using SHA-256
*   `RS384`: RSASSA-PKCS-v1.5 using SHA-384
*   `RS512`: RSASSA-PKCS-v1.5 using SHA-512

info

Note that the key's provided should be base64 URL encoded (without padding) as per the specification ([RFC7517](https://datatracker.ietf.org/doc/html/rfc7517)). This differs from the plain text secrets provided with the algorithm specific verify built-ins described below.

## Examples

### `encode_sign`

Sign and Verify

This one demonstrates how to encode the and sign the same token contents as in the example above but with `io.jwt.encode_sign` instead of the `raw` variant.

data.json

```
{}
```

input.json

```
{}
```

```
package jwtresult_hs256 := io.jwt.encode_sign(    {        "alg":"HS256",        "typ":"JWT"    },    {},    {        "kty":"oct",        "k":"Zm9v"    })# Important! - Use the un-encoded plain text secret to verify and decoderesult_parts_hs256 := io.jwt.decode_verify(result_hs256, {"secret": "foo"})result_valid_hs256 := io.jwt.verify_hs256(result_hs256, "foo")
```

Output

{
  "result\_hs256": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.Duw7jWmGY54yEu6kcqd2w1TKp1EspzboBnx8EeMc-z0",
  "result\_parts\_hs256": \[
    true,
    {
      "alg": "HS256",
      "typ": "JWT"
    },
    {}
  \],
  "result\_valid\_hs256": true
}

Symmetric Key (HMAC with SHA-256)

data.json

```
{}
```

input.json

```
{}
```

```
package jwtresult := io.jwt.encode_sign({    "typ": "JWT",    "alg": "HS256"}, {    "iss": "joe",    "exp": 1300819380,    "aud": ["bob", "saul"],    "http://example.com/is_root": true,    "privateParams": {        "private_one": "one",        "private_two": "two"    }}, {    "kty": "oct",    "k": "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow"})
```

Output

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiYm9iIiwic2F1bCJdLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UiLCJwcml2YXRlUGFyYW1zIjp7InByaXZhdGVfb25lIjoib25lIiwicHJpdmF0ZV90d28iOiJ0d28ifX0.-Or2eol8bzly-Ztb0v7\_7UkcKBkN\_aNNpK33HK0MeOY"

Symmetric Key with empty JSON payload

data.json

```
{}
```

input.json

```
{}
```

```
package jwtresult := io.jwt.encode_sign({    "typ": "JWT",    "alg": "HS256"},    {}, {    "kty": "oct",    "k": "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow"})
```

Output

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.6cvao8lnOu6FAdK68jQFcDMXOmaWNwWiYhCgijd-AD8"

RSA Key (RSA Signature with SHA-256)

data.json

```
{}
```

input.json

```
{}
```

```
package jwtresult := io.jwt.encode_sign({    "alg": "RS256"}, {    "iss": "joe",    "exp": 1300819380,    "aud": ["bob", "saul"],    "http://example.com/is_root": true,    "privateParams": {        "private_one": "one",        "private_two": "two"    }},{    "kty": "RSA",    "n": "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddxHmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMsD1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSHSXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ",    "e": "AQAB",    "d": "Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97IjlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYTCBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLhBOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ",    "p": "4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdiYrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPGBY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc",    "q": "uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxaewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc",    "dp": "BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3QCLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0",    "dq": "h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-kyNlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU",    "qi": "IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2oy26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLUW0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U"})
```

Output

"eyJhbGciOiJSUzI1NiJ9.eyJhdWQiOlsiYm9iIiwic2F1bCJdLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UiLCJwcml2YXRlUGFyYW1zIjp7InByaXZhdGVfb25lIjoib25lIiwicHJpdmF0ZV90d28iOiJ0d28ifX0.kvCjo2z80h4YO3umCn3iayUXEnBGgw-Nk4-cYNPWagW4SAg34nZSonUt9Kpnc5h0s6LpJAnam1xuEezk-2VRPnu05foQdWTDKJAze-9vZ0wr0L\_KyXLZaW0vVfehdGpPgJj\_FqVfgnc-hXdL0RADfrKjApsrO7oHpv-Ii3u7oKwauzq5oQ2AXt4cp6ahu8VhOBGQiPXtV98Yw3U3NBetMX-I\_qR6-UGsN6Z0pRO0bsdk1ANvMiHT6Y04x8nh4kzk5pfv71ACgnxrs1zxwg7YfYzm2tQXGceu7fwI9sqO\_jz2c8RvMsg4u8q0js58F-gR1SVjmTyipnXv0tAGzpZnhg"

### `encode_sign_raw`

Sign and Verify Raw

This example demonstrates how to do this using the `io.jwt.encode_sign_raw` built-in:

data.json

```
{}
```

input.json

```
{}
```

```
package jwtraw_result_hs256 := io.jwt.encode_sign_raw(    `{"alg":"HS256","typ":"JWT"}`,    `{}`,    `{"kty":"oct","k":"Zm9v"}`  	# "Zm9v" == base64url.encode_no_pad("foo"))# Important! - Use the un-encoded plain text secret to verify and decoderaw_result_valid_hs256 := io.jwt.verify_hs256(raw_result_hs256, "foo")raw_result_parts_hs256 := io.jwt.decode_verify(raw_result_hs256, {"secret": "foo"})
```

Output

{
  "raw\_result\_hs256": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.Duw7jWmGY54yEu6kcqd2w1TKp1EspzboBnx8EeMc-z0",
  "raw\_result\_parts\_hs256": \[
    true,
    {
      "alg": "HS256",
      "typ": "JWT"
    },
    {}
  \],
  "raw\_result\_valid\_hs256": true
}