Skip to content

Conversation

ishanjogi89
Copy link

Pull Request Template

Thank you for your contribution to the Serverless Workflow Catalog! To help us review and merge your pull request, please provide the following information:

Description

Briefly describe the changes made in this pull request:

This PR adds a new JWT token parsing function to the SonataFlow functions catalog. The function enables workflows to parse JWT tokens and extract user claims for personalized workflow responses, supporting the implementation of apache/incubator-kie-issues#1899.

Related Issues

Link to related issues or tasks:

Type of Change

Please check the type of change your pull request introduces:

  • Bug fix
  • New function
  • Enhancement to existing function
  • Documentation update
  • Other (please describe)

Function/Version Affected

Specify the function and version affected by this pull request (if applicable):

  • Function Name: jwt-parser
  • Function Version: 1.0.0

Implementation Details

Provide a summary of the implementation details:

  • New Features:

    • JWT token parsing function with three operations: parse, extractUser, extractClaim
    • Support for extracting complete JWT payload as JSON
    • Support for extracting standard user claims (sub, preferred_username, email, etc.)
    • Support for extracting specific claims by name
    • Automatic handling of "Bearer " token prefix
    • Integration with SonataFlow workflow headers via $WORKFLOW.headers
  • Bug Fixes: N/A

  • Changes to Existing Functions: N/A

  • Dependencies Added:

    • Function calls the jwt-parser custom function type in SonataFlow runtime
    • No external dependencies for the catalog entry itself

Additional Information

Provide any additional information or context related to this pull request:

This function specification supports the exact use case described in apache/incubator-kie-issues#1899, where workflows need to extract user information from JWT tokens for personalized responses.

Example usage from the issue:

{
  "functions": [
    {
      "name": "extractUser",
      "type": "custom",
      "operation": "jwt-parser:extractUser"
    }
  ],
  "states": [
    {
      "name": "extractUserName",
      "actions": [
        {
          "functionRef": {
            "refName": "extractUser",
            "arguments": {
              "token": "${ $WORKFLOW.headers.\"X-Authorization-acme_financial_auth\" }"
            }
          }
        }
      ]
    }
  ]
}

The function is implemented as a Quarkus addon in the SonataFlow runtime and this catalog entry provides the standard specification for its usage.

Checklist

Please ensure your pull request meets the following criteria:

  • Code follows the project's coding style and guidelines
  • Changes are thoroughly tested
  • Documentation is updated (if applicable)

Thank you for contributing to the Serverless Workflow Catalog! Your efforts are greatly appreciated.

@cdavernas
Copy link
Member

@ishanjogi89 The function catalog applies to Serverless Workflow 1.x.x and above, but it looks like you’re mixing versions in your function. Also, the function should be calling a task internally, whereas yours is calling itself—which obviously won’t work.

To fix this, your function should actually be a set task that assigns a claims property using a jq expression to extract the claims from the token provided as input.

@ishanjogi89
Copy link
Author

Thank you for the feedback, @cdavernas ! You're absolutely right about the version mismatch and recursive call issue. I've updated the function specification to:

  1. Use Serverless Workflow 1.x syntax with proper YAML format and dsl: 1.0.0-alpha1
  2. Replace the recursive call with a proper set task using jq expressions
  3. Implement JWT decoding with jq: The function now uses split(".")[1] | @base64d | fromjson to decode the JWT payload
  4. Add optional claim extraction via claimPath parameter using jq path navigation

The function now properly decodes JWT tokens using pure jq expressions and can extract specific claims as requested.

… `dsl: 1.0.0-alpha1`

2. **Replace the recursive call** with a proper `set` task using jq expressions
3. **Implement JWT decoding with jq**: The function now uses `split(".")[1] | @base64d | fromjson` to decode the JWT payload
4. **Add optional claim extraction** via `claimPath` parameter using jq path navigation

Signed-off-by: Ishan Jogi <[email protected]>
Signed-off-by: Ishan Jogi <[email protected]>
Signed-off-by: Ishan Jogi <[email protected]>

Signed-off-by: Ishan Jogi <[email protected]>
Copy link
Member

@cdavernas cdavernas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's still some minor fixes to be made, but thank you for your awesome work! ❤️

version: 1.0.0
do:
- decodeJWT:
use: jwt-parser
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should actually be call 😉

version: 1.0.0
do:
- extractSubject:
use: jwt-parser
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be call, too.

claimPath: ".sub"
# Returns: { claims: {...}, result: "user-id-123" }
- extractNestedClaim:
use: jwt-parser
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be call, too.

version: 1.0.0
do:
- parseRawToken:
use: jwt-parser
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be call, too.

with:
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.signature"
- parseBearerToken:
use: jwt-parser
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be call, too.

document:
type: object
description: The parsed JWT payload or extracted claim as a JSON object
use: set
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use is not part of SW 1.0.0, in that context. You can remove it 😉

@cdavernas
Copy link
Member

cdavernas commented Aug 16, 2025

@ishanjogi89 Don't you think it would be better if the function returned either an array containing the extracted claims, when claimPath has NOT been set, or the value of the retrieved claim, when claimPath has been set? It would be, IMHO, a bit leaner and more intuitive, but that's just my opinion 😉

@cdavernas
Copy link
Member

@JBBianchi @ricardozanini would you be so kind to review the proposal?

Copy link
Member

@ricardozanini ricardozanini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ishanjogi89 Thanks for the contribution. This is interesting.

I think a JWT parser can find some useful use cases to many implementations out there.

You mentioned SonataFlow in your PR description. I'm a maintainer of this project, and we are not currently working on upgrading the runtime engine to SWF 1.0.0.

I don't think this function will help you achieve what you need on the implementation side. Unfortunately, version 0.8 has many limitations - one of the reasons why we upgraded the spec.

However, you can add an extension as a custom function to the SonataFlow engine here: https://github.com/apache/incubator-kie-kogito-runtimes/tree/main/kogito-serverless-workflow.

Regarding the PR, once @cdavernas' comments are handled, it should be fine. Great addition, thanks again!

@ishanjogi89
Copy link
Author

ishanjogi89 commented Aug 25, 2025

@ishanjogi89 Thanks for the contribution. This is interesting.

I think a JWT parser can find some useful use cases to many implementations out there.

You mentioned SonataFlow in your PR description. I'm a maintainer of this project, and we are not currently working on upgrading the runtime engine to SWF 1.0.0.

I don't think this function will help you achieve what you need on the implementation side. Unfortunately, version 0.8 has many limitations - one of the reasons why we upgraded the spec.

However, you can add an extension as a custom function to the SonataFlow engine here: https://github.com/apache/incubator-kie-kogito-runtimes/tree/main/kogito-serverless-workflow.

Regarding the PR, once @cdavernas' comments are handled, it should be fine. Great addition, thanks again!

Thanks @ricardozanini for the clarification! You're absolutely right about SonataFlow's current SW 0.8 status.

We actually built this with a dual approach:

  1. Immediate SonataFlow support: Custom function extension in kogito-runtimes (SW 0.8 compatible)
  2. Future ecosystem support: This catalog entry for SW 1.x implementations

The catalog entry serves the broader Serverless Workflow community and will be ready when SonataFlow eventually upgrades to SW 1.x. Thanks for the guidance on the custom extension approach - that's exactly what we implemented here : apache/incubator-kie-kogito-runtimes#4021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants