How is your experience with the OutSystems Community?
30
Views
8
Comments
JWT token validation in ODC

Hi everyone, 

I’m working on JWT token validation in OutSystems ODC for an API Authentication in the OnBeforeRequest, and I need some guidance on the correct way to validate the token using the JWTCore Forge component. 

My use case 

I receive a JWT token via YAML/configuration and I’m trying to validate it inside my ODC API logic using the ReadToken action from JWTCore. The action exposes input parameters like: 

  • EncodedToken 
  • VerifySignature 
  • SignatureKey 
  • SignatureKeyId 
  • VerifyLifetime 
  • VerifyIssuer 
  • Issuer 
  • VerifyAudience 
  • Audience 
  • ShowDebugInformation 

I have the token from API header and I have mapped it to "EncodedToken" Input. But I have no idea on what to pass for other inputs. 

If anyone has implemented JWT validation for ODC APIs in ODC environment using JWTCore, I’d really appreciate: 

a working example of ReadToken configuration, 

the expected format of SignatureKey, 

whether kid / SignatureKeyId is mandatory in some cases, 

and any best practices for validating JWT tokens in ODC APIs. 

Thanks in advance!

Gowtham

2026-01-28 16-57-48
Mihai Melencu
Champion

Hi @Gowtham ,

That component is based on it's O11 version: JWT - Documentation (O11) | OutSystems  .You have there a more detailed documentation with a guide on how to properly read a token.

Also you have a DEMO application you can check: JWT Demo .


2020-09-15 13-07-23
Kilian Hekhuis
 
MVP

Hi Gowtham,

I find it strange that your JWT is coming from a configuration file. JWTs are typically issued via a token provider, like when using OAuth2, and are short-lived. If you need to verify a JWT, you must also be the issuer of the JWT, and checking whether it is valid is done via checking the attribute values.

2023-10-30 06-03-17
Gowtham

Hi @Kilian Hekhuis ,

My use case is that I'm using the ODC API's to generate build of applications via YAML for devsecops. I have built a testing API to do the automation testing through YAML.

2023-12-26 10-35-28
OutSystems Neo
Staff
AI Generated

You’re on the right track using ReadToken for validation. The key point is that JWTCore doesn’t “know” your issuer or keys; you must pass exactly the same signing key (or public key) and expected claims that your identity provider uses.

Below is how to configure ReadToken for the most common scenarios and how this fits into the ODC JWT validation pattern.


1. What you must obtain before calling ReadToken

From your token issuer / IdP you need to know:

  1. Signing algorithm and key type

    • Symmetric (HMAC, e.g. HS256): you need the shared secret.
    • Asymmetric (RSA/EC, e.g. RS256 / ES256): you need the public key that corresponds to the issuer’s private key. Typically obtained from a JWKS endpoint.
  2. Issuer and audience

    • iss (issuer) – for example: https://idp.mycompany.com
    • aud (audience) – usually the identifier for your ODC API, e.g. my-odc-api or some URL
  3. Whether the token includes kid in the header

    • If your IdP rotates keys and publishes multiple JWKs in a JWKS endpoint, you’ll probably have a kid header and must map it to the correct key.

These are exactly the things the ODC pattern expects you to validate: signature (via key), iss, aud, and exp/nbf Token-based authentication for exposed REST APIs.


2. Typical ReadToken configuration (symmetric vs asymmetric)

Case A – Symmetric signing (HMAC, e.g. HS256)

This is the simpler case: same secret is used to sign and validate.

  • EncodedToken:
    The full JWT string you got from the Authorization header (without Bearer prefix).
    Example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9....

  • VerifySignature: True
    You do want to validate the signature.

  • SignatureKey:
    The exact same secret used by the issuer to sign the token (string or binary, depending on JWTCore’s expected type).
    In ODC you’ll typically:

  • SignatureKeyId:

    • Optional if you have only one key.
    • Leave empty unless:
      • your issuer uses multiple symmetric keys and you use kid to select which secret to use.
  • VerifyLifetime: True
    Let JWTCore check exp / nbf.

  • VerifyIssuer: True

  • Issuer:
    Exact value the token’s iss claim should have, e.g., https://idp.mycompany.com.

  • VerifyAudience: True

  • Audience:

    • The audience your API expects, often a string like my-odc-api or an URL.
    • Must match aud in the token (or one of them if aud is an array).
  • ShowDebugInformation:

    • False in production.
    • True only while troubleshooting – but never log full tokens in production.

This aligns with the ODC “symmetric (HMAC)” guidance: one shared secret, kept server-side, used for both signing and validation Key management and JSON Web Keys (JWK).


Case B – Asymmetric signing (RSA/EC, e.g. RS256)

Here the issuer signs with a private key and you validate with a public key.

  • EncodedToken: same as above.

  • VerifySignature: True.

  • SignatureKey:
    The public key used to verify the signature. This usually comes from:

    • a JWKS endpoint (e.g. https://idp.mycompany.com/.well-known/jwks.json), from which you pick the correct JWK and convert to the format JWTCore expects, or
    • a configuration/secret where you store the public key (e.g. PEM).
  • SignatureKeyId:

    • Usually: the kid from the JWT header, or some internal identifier for which key you used.
    • If you always use a single public key and don’t rely on kid, you can leave this empty.
  • VerifyLifetime / VerifyIssuer / Issuer / VerifyAudience / Audience / ShowDebugInformation:
    Same as in Case A.

This matches the recommended pattern where APIs use public JWKs for verification, enabling key rotation without redeploying all services Token-based authentication for exposed REST APIs.


3. Is SignatureKeyId (kid) mandatory?

  • Not mandatory in JWTCore itself. You can successfully validate a token if:

    • VerifySignature = True, and
    • SignatureKey is the correct key.
  • It becomes important when you have multiple keys (rotation / multi-tenant):

    • If tokens include a kid header, you should:
      1. Read kid from the JWT header (or from your configuration).
      2. Fetch the corresponding JWK/public key.
      3. Pass that key as SignatureKey (and optionally set SignatureKeyId if JWTCore uses it).

If your IdP manages rotation via JWKS, typical flow is:

  1. Decode the token header (no signature validation yet) to read kid.
  2. Use kid to pick the correct key from the cached JWKS.
  3. Call ReadToken with SignatureKey = selectedPublicKey.

4. Expected format of SignatureKey

This depends on how JWTCore is implemented, but conceptually:

  • For HMAC:

    • Raw secret string (e.g. "super-long-random-secret").
    • If your IdP gives you a base64-encoded secret, decode it if JWTCore expects raw bytes.
  • For RSA / EC:

    • Often a public key in PEM format (e.g. -----BEGIN PUBLIC KEY----- ...).
    • If your IdP exposes a JWKS ({"kty":"RSA","n":"...","e":"AQAB",...}), you typically:
      • parse JWKS,
      • build a PEM or whatever JWTCore expects from n and e,
      • pass that as SignatureKey.

Because you can’t change the Forge code here, test with a known-good token and key from your IdP to confirm exactly which format JWTCore expects; start with the PEM public key string if available.


5. Where to call ReadToken in ODC

In ODC, for exposed REST APIs, you plug this validation into the request pipeline:

  1. OnAuthentication (recommended for exposed REST APIs):

    • Get token from Authorization header (strip Bearer ).
    • Call ReadToken with the configuration above.
    • When validation fails:
    • When it succeeds:
      • use the decoded claims for authorization (roles/scopes/tenant).
  2. OnBeforeRequest (for consumed REST APIs):

    • That callback is usually used to attach a token when you call an external API, not to validate one.
    • If your scenario is “ODC app consumes an external API and needs to attach a JWT”:

Given your wording (“validate the token in ODC API logic”), what you probably want is:

  • Exposed REST API → OnAuthentication callback → call ReadToken.

6. Best practices specific to ODC + JWTCore

Align with the platform patterns described in the docs:

  1. Store keys securely

  2. Always validate at least:

    • Signature (VerifySignature = True)
    • exp / nbf (VerifyLifetime = True)
    • iss (VerifyIssuer = True, Issuer = expectedIssuer)
    • aud (VerifyAudience = True, Audience = expectedAudience)
  3. Keep tokens and keys out of logs

    • If ShowDebugInformation = True, never log entire tokens or keys in production.
  4. Short-lived tokens only


Minimal working example (HMAC, ODC exposed API, OnAuthentication)

Pseudologic:

  1. In OnAuthentication:

    • HeaderValue = GetRequestHeader("Authorization")
    • Token = Replace(HeaderValue, "Bearer ", "")
  2. ReadToken configuration:

    • EncodedToken = Token
    • VerifySignature = True
    • SignatureKey = Secrets.JWT_HMAC_Secret
    • SignatureKeyId = "" (if only one secret)
    • VerifyLifetime = True
    • VerifyIssuer = True
    • Issuer = "https://idp.mycompany.com"
    • VerifyAudience = True
    • Audience = "my-odc-api"
    • ShowDebugInformation = False
  3. If ReadToken returns invalid / raises an error:

    • Set status code 401 and stop request.
  4. If valid:

    • Use claims (e.g. scopes/roles) for authorization.

If you share which algorithm your issuer uses (HS256 vs RS256) and whether you have a JWKS URL, I can tailor the exact SignatureKey handling for that scenario.

This answer was AI-generated. Please read it carefully and use the forums for clarifications
2023-10-30 06-03-17
Gowtham
We use RS256 algorithm and I have the JWKS URL
2023-12-26 10-35-28
OutSystems Neo
Staff
AI Generated

Since you’re on RS256 and already have a JWKS URL, you’re in the “asymmetric signing + JWK” scenario that ODC is designed for. Key management and JSON Web Keys (JWK)

Below is a concrete way to wire this with JWTCore’s ReadToken in ODC.


1. Overall flow in ODC

Because you’re validating tokens (not generating them) and using RS256:

  1. Client calls your API with Authorization: Bearer <jwt>.
  2. In your OnAuthentication of the exposed REST API (recommended place), or in a common server action called from there:
    • Extract the token string.
    • Resolve the correct public key from your JWKS URL (using kid).
    • Call JWTCore.ReadToken with the JWT and that public key.
    • Enforce iss, aud, and lifetime checks.
  3. If validation fails, return 401/403 and stop the request. Token-based authentication for exposed REST APIs

You can technically call this from OnBeforeRequest of a consumed API if your use case really is “validate a token we read from config/YAML before sending it out”, but structurally the logic is the same.


2. Getting the public key from JWKS (RS256)

Your IdP exposes a JWKS endpoint like:

https://<idp>/.well-known/jwks.json

Example structure:

{
  "keys": [
    {
      "kid": "abcd1234",
      "kty": "RSA",
      "alg": "RS256",
      "use": "sig",
      "n": "base64url-modulus...",
      "e": "AQAB"
    }
  ]
}

Implementation pattern in ODC:

  1. Parse the JWT header to get kid:

    • Split JWT by "." → Header, Payload, Signature.
    • Base64url‑decode the header.
    • JSON‑deserialize into a structure with at least alg and kid.
    • Use kid to pick the correct JWK from the JWKS.
  2. Fetch JWKS (once and cache it):

    • Create a consumed REST API that calls your JWKS URL and returns the keys array.
    • Cache the response at application level (e.g., in a server action with a timer-backed cache or just in-memory + short TTL, depending on requirements). Key management and JSON Web Keys (JWK)
  3. Select the JWK with matching kid:

    • Filter the keys list by Key.kid = TokenHeader.kid.
    • If not found, reject the token.
  4. Convert JWK → public key format expected by JWTCore:

    • For RS256, you’ll have n and e.
    • JWTCore normally expects either:
      • a PEM public key string (-----BEGIN PUBLIC KEY----- ...), or
      • some internal key format if the component supports JWK directly.
    • If JWTCore has helper actions for JWK/JWKS, use those and pass their output to SignatureKey. If not, you can:
      • Add a small helper (in .NET or JS inside the component, depending on what JWTCore exposes) to convert n + e into a PEM; or
      • Get the raw PEM from your IdP instead of constructing it from JWK.

From the ODC point of view, the “right” way is: store keys as JWK, get them from JWKS and rotate through that, exactly as described in the docs. Key management and JSON Web Keys (JWK)


3. ReadToken configuration for your RS256 + JWKS case

Once you have the correct public key string (or object) for the JWT’s kid, configure ReadToken like this:

  • EncodedToken
    The raw JWT string (without "Bearer ").

  • VerifySignature
    True — you definitely want to verify the signature.

  • SignatureKey
    The public key that matches the token’s kid, in the format JWTCore expects.
    Examples:

    • A PEM public key from your IdP:
      -----BEGIN PUBLIC KEY-----
      MIIBIjANBgkq...
      -----END PUBLIC KEY-----
      
    • Or a value previously derived from the JWK.
  • SignatureKeyId

    • Optional. JWTCore doesn’t require it for validation.
    • Set only if JWTCore’s internal logic uses it for logging or key lookup.
    • Since you already matched the JWK using kid, you can safely leave this empty.
  • VerifyLifetime
    True — so exp and nbf are enforced.

  • VerifyIssuer
    True

  • Issuer
    The exact expected iss from your IdP, e.g. https://<idp-domain>/.

  • VerifyAudience
    True

  • Audience
    The audience your API expects (the one configured in your IdP for this client/API).

  • ShowDebugInformation
    False in production; True only for troubleshooting (and even then, don’t log entire tokens or keys).

This matches the “asymmetric signing with RSA + JWK” approach recommended for ODC REST APIs. Token-based authentication for exposed REST APIs


4. Is kid / SignatureKeyId mandatory?

  • kid in the JWT header:

    • Not strictly mandatory per spec, but very important when your IdP rotates keys (multiple JWKs).
    • Since you have JWKS, you should use kid to pick the proper keys[i] entry.
  • SignatureKeyId input of JWTCore:

    • Not required for validation itself.
    • You can leave it blank as long as:
      • VerifySignature = True, and
      • SignatureKey is the correct public key for that token.

So in your case: use the JWT header kid only as a selector against JWKS; SignatureKeyId can remain empty unless the Forge component specifically needs it for some internal logic.


5. Best-practice checklist for your scenario

All of these are consistent with the official ODC JWT guidance. Token-based authentication for exposed REST APIs Key management and JSON Web Keys (JWK)

  1. Use JWKS + kid for key selection; cache the JWKS.
  2. Validate all:
    • Signature (VerifySignature = True).
    • Lifetime (VerifyLifetime = True).
    • Issuer and audience (VerifyIssuer, VerifyAudience).
  3. Do not log tokens or keys.
  4. Short-lived access tokens, with refresh managed by the IdP (not by your ODC API).
  5. Centralize validation in a single server action (called from OnAuthentication or OnBeforeRequest) so all APIs follow the same rules.

If you want, describe briefly how your JWKS JSON looks (fields and names), and I can outline the exact data model and logic (steps) to pick the key and pass it into ReadToken in ODC terms (structures + actions).

This answer was AI-generated. Please read it carefully and use the forums for clarifications
2023-10-30 06-03-17
Gowtham
I'm using the token generated by the ODC platform API's in the devsecops pipeline and using the same token to invoke an custom built API through YAML. How do I validate this token is valid or not?
2023-12-26 10-35-28
OutSystems Neo
Staff
AI Generated

You’re using:

  • ODC platform APIs (Service Account token) to get a JWT in your DevSecOps pipeline
  • The same token to call your own custom API (exposed REST in ODC) via YAML
  • You want to validate that token in your custom API (or before sending it, in OnBeforeRequest)

In ODC, the validation pattern is:

Below is how to do it with RS256 + JWKS + JWTCore.ReadToken.


1. High‑level validation flow

  1. Pipeline gets token from ODC platform API (service account / app token).

  2. Pipeline calls your custom API with:

    Authorization: Bearer <tokenFromPlatformAPI>

  3. In your custom API (exposed REST in ODC):

    • In OnAuthentication (recommended) or in a shared server action:
      1. Read the Authorization header.
      2. Extract the raw JWT string.
      3. Resolve the correct public key from your JWKS URL using kid.
      4. Call JWTCore.ReadToken:
        • Verify signature (RS256) using the public key
        • Verify iss, aud, exp/nbf
      5. If validation fails ⇒ return 401/403 and stop.
        If it passes ⇒ continue to your API logic.
        This follows the ODC pattern for token-based auth using JWTs. Token-based authentication for exposed REST APIs

You can also validate in OnBeforeRequest of a consumed REST API if your API is a client to another service, but the logic is the same.


2. Getting the public key from JWKS (RS256)

Given you already have the JWKS URL (from the same issuer that generates the token):

  1. Create a consumed REST in ODC to call the JWKS URL

    • It should return something like:

      {
        "keys": [
          {
            "kid": "abcd1234",
            "kty": "RSA",
            "alg": "RS256",
            "use": "sig",
            "n": "base64url-modulus...",
            "e": "AQAB"
          }
        ]
      }
      
    • Model that as structures (JwksResponse, JwkKey).

  2. Parse the JWT header to get kid:

    • Split token by . ⇒ HeaderPart, PayloadPart, SignaturePart.
    • Base64url-decode HeaderPart.
    • JSON-deserialize into a structure with at least alg, kid.
  3. Pick the right key:

    • Call your JWKS REST (preferably cached).
    • Filter keys where Key.kid = Header.kid.
    • If none found ⇒ token invalid.
  4. Convert that JWK into the format JWTCore expects:

    • For RS256 you need a public key:
      • Either:
        • Use a PEM public key the IdP also exposes
        • Or use helper logic (if available in JWTCore / other Forge) to convert n + e into PEM
    • Use that PEM (or key object) as SignatureKey.

This is exactly the ODC guidance: retrieve verification keys from JWKS and rotate via JWKs, not via hard‑coded secrets. Key management and JSON Web Keys (JWK)


3. Concrete ReadToken configuration (RS256 + JWKS)

Once you have the token and the public key (from JWKS):

EncodedToken        = <raw JWT from Authorization header, without "Bearer ">
VerifySignature     = True
SignatureKey        = <public key from JWKS, e.g. PEM string>
SignatureKeyId      = ""   // Optional, not required for validation
VerifyLifetime      = True
VerifyIssuer        = True
Issuer              = "<expected iss from platform API token>"
VerifyAudience      = True
Audience            = "<your custom API's audience>"
ShowDebugInformation= False (True only during debugging, never log full token/key)

Key points:

  • SignatureKey: public key that corresponds to the token’s RS256 private key.
  • SignatureKeyId: not mandatory; leave blank unless JWTCore specifically uses it for something internal.
  • Issuer: must match the iss in the token your ODC platform APIs generate.
  • Audience: whatever you configured as audience for that API / token (for service account tokens, usually a client or API identifier). Token-based authentication for exposed REST APIs

If ReadToken throws or returns an “invalid” result, treat the token as not valid.


4. Where exactly to plug this in

  • Expose a REST API in ODC.
  • Set authentication to custom via OnAuthentication.
  • In OnAuthentication:
    1. HeaderValue = GetRequestHeader("Authorization")
    2. Token = Replace(HeaderValue, "Bearer ", "")
    3. Call a shared action ValidateJwt(Token) that:
      • Resolves public key from JWKS
      • Calls JWTCore.ReadToken as above
    4. If validation fails:

Then, any call from your pipeline using the ODC platform token will be validated as “valid or not” automatically on every request.

B. To validate before sending a request (OnBeforeRequest, consumed REST)

If your scenario is:

  • You have a consumed REST (you are a client) and
  • You want to check a pre-configured token in YAML before attaching it:

In OnBeforeRequest of that consumed REST:

  1. Read token (from Site/Secret/parameter).
  2. Optionally validate it with the exact same ValidateJwt(Token) action.
  3. If valid:
    • Set the request header: Authorization = "Bearer " + Token
  4. If invalid:
    • Decide: fail immediately or fetch a new token.

The same JWT validation logic (JWKS + ReadToken) is reused; only the place in the pipeline changes.


5. How do you answer your original question?

“I’m using the token generated by the ODC platform API’s in the devsecops pipeline and using the same token to invoke a custom built API through YAML. How do I validate this token is valid or not?”

Answer:

  • Configure your custom API’s OnAuthentication (or a shared ValidateJwt action called from there) to:
    • Get the JWT from Authorization header.
    • Look up the public JWK from the platform’s JWKS URL using kid. Key management and JSON Web Keys (JWK)
    • Call JWTCore.ReadToken with:
      • VerifySignature = True, SignatureKey = public key
      • VerifyLifetime = True
      • VerifyIssuer = True, Issuer = <platform token issuer>
      • VerifyAudience = True, Audience = <your API audience>
  • If ReadToken succeeds ⇒ token is valid and request proceeds.
  • If it fails ⇒ respond with 401/403; token is not valid for that API. Token-based authentication for exposed REST APIs

If you share the exact iss and aud shape of the platform token (or a sample payload with names redacted), I can suggest precise string values for Issuer and Audience in your ReadToken call.

This answer was AI-generated. Please read it carefully and use the forums for clarifications
Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.