JSON Web Tokens (JWT)

JSON Web Tokens (JWTs) are an open standard for securely sharing user information in the form of JSON objects. JWTs are digitally signed using a secret, so the information can be verified and trusted.

Cloudflare Access uses that JWT, and its contents, to confirm a user identity before allowing or denying access to sensitive resources. Cloudflare securely creates these through the OAUTH or SAML integration between Cloudflare Access and the configured identity provider. Each JWT consists of three Base64-URL strings: the header, the payload, and the signature.

Cloduflare Access signs JWTs for user sessions and uses these tokens to authenticate requests. The content in the JWT is available for teams to validate independently, as well.

JWT contents

JWTs contain these three segments, separated by dots:

  • Header

  • Payload

  • Signature

A typical JWT looks like this:

eyJhbGciOiJSUzI1NiIsImtpZCI6IjkzMzhhYmUxYmFmMmZlNDkyZjY0.eyJhdWQiOlsiOTdlMmFhZ TEyMDEyMWY5MDJkZjhiYzk5ZmMzNDU5MTNh.zLYsHmLEginAQUXdygQo08gLTExWNXsN4jBc6PKdB

JWTs generated by Access are available in a request header as Cf-Access-Jwt-Assertion and as cookies as CF_Authorization. When not using Argo Tunnel, the tokens must be validated by the application to ensure the authenticity of the token and the security of the origin. Validation of the header alone is not sufficient. The JWT and signature must be confirmed to avoid identity spoofing.

Cloudflare uses the RSA Signature with SHA-256 (RS256) to sign the JWT using a public and private key pair. RS256 follows an asymmetric algorithm; a private key signs the JWTs and a separate public key verifies the signature. When you configure Access, the public certificates are available under: https://<Your Authentication Domain>/cdn-cgi/access/certs For example, if the application URL is example.com, then the certificate URL is: https://example.<strong>cloudflareaccess</strong>.com/cdn-cgi/access/certs.

{
    "alg": "RS256",
    "kid": "9338abe1baf2fe492f646a736f25afbf7b025e35c627be4f60c414d4c73069b8",
    "typ": "JWT"
}

The header contains the encoding algorithm. kid identifies the key used to sign tokens. Typ designates the token format.

Payload

{
    "aud": ["97e2aae120121f902df8bc99fc345913ab186d174f3079ea729236766b2e7c4a"],
    "email": "[email protected]",
    "exp": 1519418214,
    "iat": 1519331815,
    "iss": "https://drawbridge.cloudflareaccess.com",
    "nonce": "1d8083f708a47982296f2d9896d70f207a27938f026540c392b903e5fdf4d6e9",
    "sub": "ca639bb9-26ab-42e5-b9bf-3aea27b331fd"
}

The payload contains the actual claim and user information to pass to the application.

  • aud identifies the application to which the JWT is issued. Our example uses test.example.com.
  • email contains the email address of the authenticated user.
  • sub contains the identifier of the authenticated user.
  • iss the issuer is the application’s Cloudflare Access Domain URL.
  • iat and exp are the issuance and expiration timestamps.
  • nonce is the session identifier.

Signature

To generate the signature, the encoded header, encoded payload, and the algorithm specified in the header are signed using the Cloudflare Access private key. Users validate the token using the public key.

Cloudflare includes the JWT with all authenticated requests in two places:

  • The response header Cf-Access-Jwt-Assertion

  • The cookie CF_Authorization

Visit jwt.io for more information on JWTs.

User identity

After a visitor authenticates to Cloudflare Access, all subsequent requests to the application server contain a Cf-Access-Authenticated-User-Email header with the authenticated user. Our example uses [email protected]

This allows you to identify the user currently logged in. It is critical to ensure that only Cloudflare can send requests to the origin when relying on this header. Even so, validating the header alone is not sufficient. JWTs and signatures must be confirmed to avoid identity spoofing.

Based on security requirements, you can allow users to have longer or shorter sessions than the default. The longer the user session, the less frequently they need to log in, but long sessions remain valid if the user doesn’t log out.

You can set the Session Duration on the Settings page of the Edit Access Policy dialog box in the Access app on your Cloudflare dashboard.

Session Duration

Click Revoke Existing Tokens to revoke JWTs associated with the selected policy.

Groups within a JWT

The JWT created by Cloudflare Access contains the user identity and also a mechanism for your application to identify the user’s SSO group membership. For example, your application can validate that a given user is a member of an Okta or AzureAD group like Finance-Team or Eng.

Requests sent to the origin contain the JWT in a header, Cf-Access-Jwt-Assertion, as well as a cookie in the user’s browser titled CF_Authorization. If your application retrieves that cookie, it can then make a request to https://<authdomain>.cloudflareaccess.com/cdn-cgi/access-get-identity, where the authdomain is your account’s authentication domain. The request should be structured as follows:

curl -H 'cookie: CF_Authorization=<users token>' https://<authdomain>.cloudflareaccess.com/cdn-cgi/access/get-identity

The response will be structured as JSON:

{
  "groups": [
    {
      "id": "02fk6b3p3majl10",
      "email": "[email protected]",
      "name": "FinanceTeam"
    },
    {
      "id": "04k668n318e7vu5",
      "email": "[email protected]",
      "name": "Eng"
    }
  ]
}