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:
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
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 .
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.
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.
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.
ReadToken
Below is how to configure ReadToken for the most common scenarios and how this fits into the ODC JWT validation pattern.
From your token issuer / IdP you need to know:
Signing algorithm and key type
HS256
RS256
ES256
Issuer and audience
iss
https://idp.mycompany.com
aud
my-odc-api
Whether the token includes kid in the header
kid
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.
exp
nbf
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....
Authorization
Bearer
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9....
VerifySignature: True You do want to validate the signature.
True
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:
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:
ShowDebugInformation:
False
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).
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:
https://idp.mycompany.com/.well-known/jwks.json
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.
SignatureKeyId
Not mandatory in JWTCore itself. You can successfully validate a token if:
VerifySignature = True
SignatureKey
It becomes important when you have multiple keys (rotation / multi-tenant):
If your IdP manages rotation via JWKS, typical flow is:
SignatureKey = selectedPublicKey
This depends on how JWTCore is implemented, but conceptually:
For HMAC:
"super-long-random-secret"
For RSA / EC:
-----BEGIN PUBLIC KEY----- ...
{"kty":"RSA","n":"...","e":"AQAB",...}
n
e
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.
In ODC, for exposed REST APIs, you plug this validation into the request pipeline:
OnAuthentication (recommended for exposed REST APIs):
401
403
Response_SetStatusCode
OnBeforeRequest (for consumed REST APIs):
OnBeforeRequest
Authorization: Bearer <token>
Given your wording (“validate the token in ODC API logic”), what you probably want is:
OnAuthentication
Align with the platform patterns described in the docs:
Store keys securely
Always validate at least:
VerifyLifetime = True
VerifyIssuer = True
Issuer = expectedIssuer
VerifyAudience = True
Audience = expectedAudience
Keep tokens and keys out of logs
ShowDebugInformation = True
Short-lived tokens only
Pseudologic:
In OnAuthentication:
HeaderValue = GetRequestHeader("Authorization")
Token = Replace(HeaderValue, "Bearer ", "")
ReadToken configuration:
EncodedToken = Token
SignatureKey = Secrets.JWT_HMAC_Secret
SignatureKeyId = ""
Issuer = "https://idp.mycompany.com"
Audience = "my-odc-api"
ShowDebugInformation = False
If ReadToken returns invalid / raises an error:
If valid:
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.
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.
Because you’re validating tokens (not generating them) and using RS256:
Authorization: Bearer <jwt>
JWTCore.ReadToken
401/403
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.
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:
Parse the JWT header to get kid:
"."
alg
Fetch JWKS (once and cache it):
keys
Select the JWK with matching kid:
Key.kid = TokenHeader.kid
Convert JWK → public key format expected by JWTCore:
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)
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 ").
"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:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkq... -----END PUBLIC KEY-----
VerifyLifetime True — so exp and nbf are enforced.
VerifyIssuer True
Issuer The exact expected iss from your IdP, e.g. https://<idp-domain>/.
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
kid in the JWT header:
keys[i]
SignatureKeyId input of JWTCore:
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.
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)
VerifyIssuer
VerifyAudience
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).
You’re using:
In ODC, the validation pattern is:
Below is how to do it with RS256 + JWKS + JWTCore.ReadToken.
Pipeline gets token from ODC platform API (service account / app token).
Pipeline calls your custom API with:
Authorization: Bearer <tokenFromPlatformAPI>
In your custom API (exposed REST in ODC):
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.
Given you already have the JWKS URL (from the same issuer that generates the token):
Create a consumed REST in ODC to call the JWKS URL
It should return something like:
Model that as structures (JwksResponse, JwkKey).
JwksResponse
JwkKey
.
HeaderPart
PayloadPart
SignaturePart
Pick the right key:
Key.kid = Header.kid
Convert that JWK into the format JWTCore expects:
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)
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:
Issuer
Audience
If ReadToken throws or returns an “invalid” result, treat the token as not valid.
ValidateJwt(Token)
Response_SetStatusCode(401)
Then, any call from your pipeline using the ODC platform token will be validated as “valid or not” automatically on every request.
If your scenario is:
In OnBeforeRequest of that consumed REST:
Authorization = "Bearer " + Token
The same JWT validation logic (JWKS + ReadToken) is reused; only the place in the pipeline changes.
“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:
ValidateJwt
SignatureKey = public key
Issuer = <platform token issuer>
Audience = <your API audience>
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.