Skip to content

Tokens and Claims

Obtaining a Token

The Kubauth companion CLI application kc provides an embedded OIDC client. Beyond testing the installation, its primary purpose is to fetch access tokens or ID tokens for use in any application.

Launch the following command after adjusting the issuer URL:

kc token --issuerURL https://kubauth.mycluster.mycompany.com --clientId public

Or, if you want to test the private client defined in previous chapter:

kc token --issuerURL https://kubauth.mycluster.mycompany.com --clientId private --clientSecret secret1

Adjust the issuerURL to the value set previously in Kubauth configuration

Tip

If you encounter an error like tls: failed to verify certificate: x509:..., the CA associated with your ClusterIssuer is not recognized on your local workstation.

  • Add the --insecureSkipVerify option to the kc token command. You will also need to configure your browser to accept the certificate.
  • Add the CA as a trusted certificate on your local workstation. You can extract it with:
    kubectl -n kubauth get secret kubauth-oidc-server-cert \
      -o=jsonpath='{.data.ca\.crt}' | base64 -d >./ca.crt 
    
  • Add the --caFile ./ca.crt option to the kc token command.

Your browser should open to the Kubauth login page:

login

Log in using jim/jim123. You should land on a page similar to the following:

tokens

From this page, you can copy the provided tokens.

These tokens are also displayed in the CLI response:

Access token: ory_at_xLUfAhEGpFVWpMLdNEDZAj94hHFrHWjgOYB5g0Leh_k.0rgIzRGFOiIeGsMKnIZ74QL4Ve5vVOuEZyhA0402u8Y
Refresh token: ory_rt_nU9NBZs4NtKTxVYVko1aqlJkAMF5MLBYjfiZbhVt9aE.THwsnTlqzIsWo5O1NAf1EbDhz7HdaqVHHwSTkWxrkqY
ID token: eyJhbGciOiJSUzI1NiIsImtpZCI6ImY0Y2NkNDU0LWYzYTgtNDQ3Zi1hN2MzLTY3ZmY5MzUxMzZiMSIsInR5cCI6IkpXVCJ9.eyJhdF9oYXNoIjoiaGNBY2dtdmdBekJlSGgyODlkWHF3USIsImF1ZCI6WyJwdWJsaWMiXSwiYXV0aF90aW1lIjoxNzYxMzI2MDg2LCJhenAiOiJwdWJsaWMiLCJleHAiOjE3NjEzMjk2ODYsImlhdCI6MTc2MTMyNjA4NiwiaXNzIjoiaHR0cHM6Ly9rdWJhdXRoLmluZ3Jlc3Mua3VibzYubWJwIiwianRpIjoiZDZhYjkwODMtYTEzMi00YTNiLTlmMWItMzM2NWFhOTQ5MjQ2IiwicmF0IjoxNzYxMzI2MDg2LCJzdWIiOiJqaW0ifQ.Q8ZkF33jsUJDqLH98uqRgrFa2nwioRP1TO9n6QjX9XFr-1WmsKk9nEeHGAiASb1brQ3cSAmK8ta7fX3lBLBlszxmeVZRzq5Qvg0N8nqvlV3C4CAiv6lEl6_-y6wBoQOWN9OhNhYU6wFjpNNDTx_RW0329i9TYVxaygw58wJGCX_1F5-PY0NG74n_1sdZxYop7s5GnZ0_9S9-DEI-LNR2MMx-oVH4lpGjV5dhGRvZS0l4tMm2C7J6Yx_JoTQoZfWwPI0GGf2smZZ-C2ieB5Wj0b19fgrafuexHW9yeejI51j6WZs_eDqUwvCIf52_yAvokA4SiW4PW8Eod9fX-JuwJQ
Expire in: 59m59s

Let's try another variant of the command:

kc token --issuerURL https://kubauth.mycluster.mycompany.com --clientId public --onlyIdToken | kc jwt
  • The --onlyIdToken option instructs the command to output only the base64-encoded ID token, useful for batch processing.
  • The kc jwt command decodes the JWT token.

The response should look like:

JWT Header:
{
  "alg": "RS256",
  "kid": "f4ccd454-f3a8-447f-a7c3-67ff935136b1",
  "typ": "JWT"
}

JWT Payload:
{
  "at_hash": "_GWrC20juEb4Zh39S0ly5w",
  "aud": [
    "public"
  ],
  "auth_time": 1761564624,
  "auth_time_human": "2025-10-27 11:30:24 UTC",
  "azp": "public",
  "exp": 1761568224,
  "exp_human": "2025-10-27 12:30:24 UTC",
  "iat": 1761564624,
  "iat_human": "2025-10-27 11:30:24 UTC",
  "iss": "https://kubauth.mycluster.mycompany.com",
  "jti": "be30eeb2-153f-4dec-97b8-c75d23035f81",
  "rat": 1761564624,
  "rat_human": "2025-10-27 11:30:24 UTC",
  "sub": "jim"
}

Note

The auth_time_human, exp_human, iat_human, and rat_human fields are not actual claims but human-readable values added by the decoder to aid interpretation of the corresponding timestamp values.

There is also a shortcut (-d) for this command:

kc token --issuerURL https://kubauth.mycluster.mycompany.com --clientId public -d

Note: This option skips the JWT header.

Claims

A set of 'system' claims are provided by the OIDC server. You can find a description of most standard claims here.

An important claim is sub, which stands for 'subject' and represents the user's login.

Now, run the previous command again, but use john/john123 when prompted for login:

JWT Payload:
{
  "at_hash": "fdg2po7ht7lBaFFvgXg14A",
  "aud": [
    "public"
  ],
  "auth_time": 1761575699,
  "auth_time_human": "2025-10-27 14:34:59 UTC",
  "azp": "public",
  "email": "johnd@mycompany.com",
  "emails": [
    "johnd@mycompany.com"
  ],
  "exp": 1761579299,
  "exp_human": "2025-10-27 15:34:59 UTC",
  "iat": 1761575699,
  "iat_human": "2025-10-27 14:34:59 UTC",
  "iss": "https://kubauth.mycluster.mycompany.com",
  "jti": "822ed082-e615-4153-ad7e-d623df491253",
  "name": "John DOE",
  "office": "208G",
  "rat": 1761575699,
  "rat_human": "2025-10-27 14:34:59 UTC",
  "sub": "john"
}

Kubauth has added several new claims derived from the User resource definition:

  • name: The spec.name property, containing the user's full name.
  • emails: The spec.emails list.
  • email: The first email from the emails list.
  • office: Content from the spec.claims property, which can contain any valid map values.

The resulting claim set is the result of merging:

  • An initial set of system claims (aud, azp, exp, iss, ...)
  • Claims added by Kubauth from the user CRD definition:
    • name from spec.name
    • emails from spec.emails
    • groups described in a following chapter
  • The contents of the user's spec.claims

Warning

In the current version, claims are not filtered by scope. In other words, all user claims are included in the ID token.

JWT Access Token

In OAuth 2.0, the Access Token grants access to a protected resource. However, the specification does not prescribe a specific format for it. This flexibility allows two main architectural styles: Opaque tokens and JWT (JSON Web Token).

This "Access Token" is different from the OIDC JWT token we just described above.

Opaque Tokens

An opaque token is a random string that carries no information on its own and is meaningless to anyone who inspects it.

When an application receives an opaque token, it has no knowledge of the user's identity or permissions. It must send the token back to the OAuth server (Kubauth) to validate it.

Advantages:

  • Privacy: No user data is embedded in the token string.
  • Instant Revocation: Deleting the token from the server invalidates it immediately on the next validation check.
  • Security: Since the token contains no data, there is nothing for an attacker to decode.

JWT Access Token

A JWT Access Token is a self-contained, structured string. Like an OIDC ID token, it contains claims and is digitally signed by the OAuth server (Kubauth).

The resource server can validate the token locally by checking its digital signature against a public key. If the signature is valid and the token has not expired, the application trusts the embedded data without contacting Kubauth.

Advantages:

  • Performance: No additional network call (introspection) is required, resulting in faster API responses.
  • Scalability: The authorization server does not need to validate every request, eliminating it as a potential bottleneck.
  • Standardization: JWTs follow a well-defined structure, making them easy to use across different programming languages and frameworks.

Configuration

By default, Kubauth is configured to generate Opaque Access Tokens.

This can be changed by setting a Helm chart configuration value:

values.yaml
oidc:
  issuer: https://kubauth.mycluster.mycompany.com
  postLogoutURL: https://kubauth.mycluster.mycompany.com/index
  jwtAccessToken: true

......

Redeploy Kubauth:

helm -n kubauth upgrade -i kubauth --values ./values.yaml oci://quay.io/kubauth/charts/kubauth --version 0.2.1 --create-namespace --wait

You can now test, still using the public client:

kc token --issuerURL https://kubauth.mycluster.mycompany.com --clientId public

Log in using jim/jim123.

tokens

Notice that the Access Token is significantly longer than an opaque token.

The same applies to the CLI response:

Access token: eyJhbGciOiJSUzI1NiIsImtpZCI6Ijk1ODhlNWIyLTIwY2QtNGM3Mi04MGIwLTU0OGJjZDdjNDg0OCIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicHVibGljIl0sImF6cCI6InB1YmxpYyIsImV4cCI6MTc3Mzg1NDQyMSwiaWF0IjoxNzczODUwODIxLCJpc3MiOiJodHRwczovL2t1YmF1dGguaW5ncmVzcy5rdWJvMi5tYnAiLCJqdGkiOiJhNjk2ZDdlMC1iYmJkLTRkNDQtOTY2Ny04NWI4NThmY2I1ZWYiLCJzY3AiOlsib3BlbmlkIiwicHJvZmlsZSIsIm9mZmxpbmUiLCJncm91cHMiXSwic3ViIjoiamltIn0.mQ0Z_aQhAqkdA3fQTo8yNSyl1WLNbpPfJZOUT0J-zyU2BRkaAT_7hcD5TOAmHRH088HGrjWWSOhh8oO1fAzJ_lY50-uLGBGOvtFCFqWspcVLohzsJbbf5Uj0ir4IuOAVMdbW-G341FrCJzD7DiFFw4xHHJ_yc0GDS9JMZUlWgdUbxPtNF-Dt90j_SaOj6dsnZMJ8W08JwKKcTlOGgeQzze_hkPBWbb1HR9f6PShfAVGd1UVmT7fvZDwLs_3RthMR7ui3rX5P7kCR3ZxgKHoQjlbkARfcJ8ggxPxl_tHC7wp570MRslABA25x-c_zTuG5stTkzL3oEgcl8TPxr---Qw
Refresh token: ory_rt_jvYjlVuq4zRnsXwl3LFXj8pZ1HTj4C7qOZ0ZO-l1UbQ.lawnhz9iMrxQ4dVhwl0JqjSxplbFqr-EVJYWu_TJCgM
ID token: eyJhbGciOiJSUzI1NiIsImtpZCI6Ijk1ODhlNWIyLTIwY2QtNGM3Mi04MGIwLTU0OGJjZDdjNDg0OCIsInR5cCI6IkpXVCJ9.eyJhdF9oYXNoIjoiM1NfTnRXWVVCRHhjN3JaeHBwTnBtUSIsImF1ZCI6WyJwdWJsaWMiXSwiYXV0aF90aW1lIjoxNzczODUwODIxLCJhenAiOiJwdWJsaWMiLCJleHAiOjE3NzM4NTQ0MjEsImlhdCI6MTc3Mzg1MDgyMSwiaXNzIjoiaHR0cHM6Ly9rdWJhdXRoLmluZ3Jlc3Mua3VibzIubWJwIiwianRpIjoiZjM1NDhkNmItYmU5OC00ZWI1LTk3NzktMDAzMmRmYjllYjNiIiwicmF0IjoxNzczODUwODIxLCJzdWIiOiJqaW0ifQ.U-j8bDWbprqTZW1OlLwjo7Y_RlXxJr3tazYukHO5uQ3xMFHKnBNxqJ3GyWrUpsY3NvBD_5xQIX1M67Nz54pV5Mhel2AqTNk1mm8GQcrdTUfCRZd6U3hmJ3LtpeyU5qCh2d2zbf0eZFGh-NtTVFj4zxoaiUWMzMEPD1VY0YV4ByH0oR6VZ22HKCgD3Ehqxdktwy5x9eckoVL1_b5K6hpfFc2O144PiU_c0qb0SCx9NGkHMEbS9Q9YdrkeMBPDt8ytB1L7GAMTS3Ij_Gtjc6wpFCH6AqYCahS_e9541coNOI07jZzsy5lCAGRVHYnfGa5-Ivbus5XkYd9UnI1wIlQpPQ
Expire in: 59m59s

Now, try the following:

kc token --issuerURL https://kubauth.mycluster.mycompany.com --clientId public --onlyAccessToken | kc jwt
  • The --onlyAccessToken option instructs the command to output only the Access Token, useful for piping to other commands.
  • The kc jwt command decodes the JWT Access Token.

The response should look like:

Token: JWT Header:
{
  "alg": "RS256",
  "kid": "9588e5b2-20cd-4c72-80b0-548bcd7c4848",
  "typ": "JWT"
}

Token: JWT Payload:
{
  "aud": [
    "public"
  ],
  "azp": "public",
  "exp": 1773854789,
  "exp_human": "2026-03-18 17:26:29 UTC",
  "iat": 1773851189,
  "iat_human": "2026-03-18 16:26:29 UTC",
  "iss": "https://kubauth.mycluster.mycompany.com",
  "jti": "3b7cf9b9-f70a-42bc-9c98-f113a03b104a",
  "scp": [
    "openid",
    "profile",
    "offline",
    "groups"
  ],
  "sub": "jim"
}

There is also a shortcut for decoding the Access Token:

kc token --issuerURL https://kubauth.mycluster.mycompany.com --clientId public  -a