Give us feedback
jwt
Service icon

JWT

Stable version 4.1.1 (Compatible with OutSystems 11)
Other versions available for 10
Uploaded on 3 Jul (13 days ago) by 
4.5
 (17 ratings)
jwt

JWT

Documentation
4.1.1

JWT


Introduction


JWT is a service application that provides a set of actions to handle JSON Web Tokens, both for creating tokens and parsing existing ones, exposed via server and service actions on the JWT module, so it can be consumed in an Outsystems application. The actions provided are meant to handle different cryptographic algorithms and key formats, but they can be divided into three groups and most likely only one action per usage scenario might be needed:

  • Create/sign tokens - allows to fill the data for a token and encode it.
  • Decode/validate tokens - allows to decode and existing token, decode its information and perform validations
  • Key Helpers - provide helper actions to handle some types of keys


To learn more about JWT usage and its structure, consult the JWT introduction.

It is recommended to consult the component demo to obtain implementation examples.


Supported cryptographic features


Supported algorithm types

  • Symmetric (same key is used to sign and validate the token)

    • HS256 - HMAC using SHA-256
    • HS384 - HMAC using SHA-384
    • HS512 - HMAC using SHA-512
  • Asymmetric (private key is used to sign and public key to validate the token)

    • RS256 - RSA Signature with SHA-256
    • RS384 - RSA Signature with SHA-384
    • RS512 - RSA Signature with SHA-512


Supported key formats


PEM format

PEM format is a text file with the delimited key encoded in base64

Private keys
PKCS#5

-----BEGIN RSA PRIVATE KEY-----

Proc-Type: 4,ENCRYPTED

KEY_ENCODED_IN_BASE64

-----END RSA PRIVATE KEY-----

PKCS#8

-----BEGIN PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

----END PRIVATE KEY-----

PKCS#8 Encrypted

-----BEGIN ENCRYPTED PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

-----END ENCRYPTED PRIVATE KEY-----

Public keys
Public key from key pair

-----BEGIN PUBLIC KEY----

KEY_ENCODED_IN_BASE64

-----END PUBLIC KEY-----

X509 certificate

-----BEGIN CERTIFICATE-----

KEY_ENCODED_IN_BASE64

-----END CERTIFICATE-----

JSON format

These are text file with the key encoded in a JSON structure, equivalent to PEM but less prone to formatting errors

JSON Web Key

Represents a single key, can contain the private or public key

{

"use": "sig",

"kty": "RSA",

"kid": "key_id",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}


JSON Web Key Set

A set of multiple JSON Web Keys

{

"keys": [

{

"use": "sig",

"kty": "RSA",

"kid": "key_id_1",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

},

{

"use": "sig",

"kty": "RSA",

            "kid": "key_id_2",

"alg": "RS512",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}

]

}


Usage


Generate a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

A JWT can be generated, in two different ways. The difference is in the token Signature definition, related to the JWT security. On one hand, a JWT can be generated using either a secret plain key (for secret key) or a private key (generating a PEM file). On the other hand, a JWT can be generated using a JSON Web Key (JWK), as a private key. This key is a JSON object.


a) Generate it using a secret plain / PEM key

──────────────────────────────────────────────────────────────────

To generate a JWT using a private key (for asymmetric algorithms), a PEM file must be generated to obtain a private and public key. Consult the Google documentation to generate these keys.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

  • Choose an algorithm using an entity identifier:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use the SymmetricAlgorithm static entity to choose a symmetric algorithm.

Use the AsymmetricAlgorithm static entity to choose an Asymmetric algorithm.

  • Choose a key identifier (key id). This key indicates which key was used to secure the signature, assigned when adding the existing key in REST service configuration. However, the key id IS NOT a signature key.


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

 

Signature configuration

  • Provide either a secret plain text key or a private key from a generated PEM file:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use a secret plain text key. It is recommended to use a long and complex secret key, because this same key is used to decrypt the generated JWT when reading it.

Use a private key from a generated PEM file. The corresponding public key must also be generated in another PEM file. Consult the Google documentation to generate these keys.

 

  • Only for Asymmetric algorithms: A passphrase can also be provided. This passphrase represents a private password that protects the specified private key.


Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).

  • Drag the corresponding action in the canvas of GenerateJWT action:

For Symmetric algorithms (using secret plain text key)

Use CreateSignedSymmetricTokenService action and fill it with values specified in the previous step for the Header, Payload and Signature.

 

 

For Asymmetric algorithms (using a private key from a PEM file)

Use CreateSignedAsymmetricTokenWithPemKeyService action and fill it with the values specified in the previous step, for the Header, Payload and Signature parts.

 

 

Step 3 - Validate the generated token

Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.





b) Generate it using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

A JSON Web Key (JWK) must be generated to obtain a private and public keypair. Consult https://mkjwk.org/ to generate all necessary keys, for testing purposes the online generator can be used but for Production is highly recommended to generate them locally or use the one from your authentication provider.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

When generating a token using a JWK as signature, the Header cannot be configured. The related JWT must use an asymmetric algorithm, and both algorithm and key id parameters are defined when generating the JSON Web Key (JWK).


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

Signature configuration

The signature must be a generated JSON Web Key (JWK). Consult https://mkjwk.org/ to generate all necessary keys.

The public and private keypair must be used to encode the JWT. The related public key (another key generated at the same time) will be used to validate the generated token.

Public and private keypair sample.

 

 

Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).
  • Drag and drop the CreateSignedAsymmetricTokenService action inside the canvas of GenerateJWT action and fill it with the values specified in the previous step, for the Header, Payload and Signature.


Step 3 - Validate the generated token


Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.


 

 

Read a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

Two types of JWT can be decoded, using the related validation method. On one hand, a JWT generated using a Plain / PEM key, can only be decoded using either the same secret plain key, or the public key related to a private PEM key. On the other hand, a JWT generated using a JSON Web Key can only be decoded using the related public key (or the generated keypair).


a) Read a JWT generated using a plain secret / PEM key

──────────────────────────────────────────────────────────────────

To verify the signature of an asymmetric generated token (token generated using a private key in a PEM file), the public key related to the private one (when generating the PEM file) is necessary.

──────────────────────────────────────────────────────────────────

Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, either the secret plain text key or public key related to the private one, must be provided.


Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.


Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.

  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.


Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent. 

 

b) Read a JWT generated using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

To verify the signature of the generated token, the public key (or keypair) related to the private one (when generating the JWK) is necessary.

──────────────────────────────────────────────────────────────────


Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, the public key related to the keypair (JWK) must be provided.

Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.

 

Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.
  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.



Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent.


* New in 4.1.0

- Custom claims now allows for complex (nested JSON objects), along with simple objects:

Just set the boolean and you can put an entire JSON object as a text inside of the Claim Body



Considerations when implementing a REST authentication using JSON Web Tokens

Although the action for reading tokens is the same for all signing scenarios (no separation between algorithms) and its invocation is easier that the Create Token actions, using JWT for authentication will require some preparation prior to the first call. If when creating a token for authentication in a REST service the rules to fill its payload are defined by the third-party service, now when we're implementing authentication on our service we must define the all the additional rules consumers should follow.

Should I use JSON Web Tokens?

JSON Web Tokens is just one of the authentication options for REST APIs, it works really well for scenarios where different servers need to connect, as it can provide authentication between two or even more entities. It can also be used on client-to-server implementations where there's no human involved, but whenever there's human involved in that flow an authentication based in OAuth makes much more sense.

Asymmetric or symmetric?

Assuming generated tokens will always be signed (which should be) there's the decision whether to use asymmetric or symmetric algorithm. The rule of thumb is simple:

  • Symmetric algorithms are better suited when there's a high trust between entities and the need to identify who's making the call isn't as important, so that a common secret can be shared between all parties. If that's the case a symmetric algorithm is easier to implement, and that shared secret can work in both ways of the communication. Examples:

    • Different APIs from the same suite of applications
    • Mobile calls from an app to its server, when there's no user involved
    • Different applications from the same organization
  • Asymmetric algorithms should always be used when the API is meant to be called publicly or from outside the domain of the organization, as it provides stronger identification of parties.

JSON Web Tokens aren't encrypted!

It's very important to never forget that these tokens are signed but not encrypted. It's encouraged that some additional claims are added to the tokens, like additional identifiers, but no sensitive information should ever be saved inside it.

JSON Web Tokens aren't session tokens!

It's tempting to use JSON Web Tokens as an application's session token, its custom claims can hold lots of data in a single structure that can be added throughout the session. But a JSON Web Token has a higher footprint than other simpler session containers (like plain old session variables) and with a cryptographic signature involved in each call that will take a toll in the performance. JSON Web Tokens are well suited for authentication and identification.

Further reading

Introduction to JSON Web Tokens

Authentication in REST services using JSON Web Tokens with Outsystems


External Libraries Licenses


4.1.0

- Custom claims now allows for complex (nested JSON objects), along with simple objects:

Just set the boolean and you can put an entire JSON object as a text inside of the Claim Body


4.0.8

JWT


Introduction


JWT is a service application that provides a set of actions to handle JSON Web Tokens, both for creating tokens and parsing existing ones, exposed via server and service actions on the JWT module, so it can be consumed in an Outsystems application. The actions provided are meant to handle different cryptographic algorithms and key formats, but they can be divided into three groups and most likely only one action per usage scenario might be needed:

  • Create/sign tokens - allows to fill the data for a token and encode it.
  • Decode/validate tokens - allows to decode and existing token, decode its information and perform validations
  • Key Helpers - provide helper actions to handle some types of keys


To learn more about JWT usage and its structure, consult the JWT introduction.

It is recommended to consult the component demo to obtain implementation examples.


Supported cryptographic features


Supported algorithm types

  • Symmetric (same key is used to sign and validate the token)

    • HS256 - HMAC using SHA-256
    • HS384 - HMAC using SHA-384
    • HS512 - HMAC using SHA-512
  • Asymmetric (private key is used to sign and public key to validate the token)

    • RS256 - RSA Signature with SHA-256
    • RS384 - RSA Signature with SHA-384
    • RS512 - RSA Signature with SHA-512


Supported key formats


PEM format

PEM format is a text file with the delimited key encoded in base64

Private keys
PKCS#5

-----BEGIN RSA PRIVATE KEY-----

Proc-Type: 4,ENCRYPTED

KEY_ENCODED_IN_BASE64

-----END RSA PRIVATE KEY-----

PKCS#8

-----BEGIN PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

----END PRIVATE KEY-----

PKCS#8 Encrypted

-----BEGIN ENCRYPTED PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

-----END ENCRYPTED PRIVATE KEY-----

Public keys
Public key from key pair

-----BEGIN PUBLIC KEY----

KEY_ENCODED_IN_BASE64

-----END PUBLIC KEY-----

X509 certificate

-----BEGIN CERTIFICATE-----

KEY_ENCODED_IN_BASE64

-----END CERTIFICATE-----

JSON format

These are text file with the key encoded in a JSON structure, equivalent to PEM but less prone to formatting errors

JSON Web Key

Represents a single key, can contain the private or public key

{

"use": "sig",

"kty": "RSA",

"kid": "key_id",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}


JSON Web Key Set

A set of multiple JSON Web Keys

{

"keys": [

{

"use": "sig",

"kty": "RSA",

"kid": "key_id_1",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

},

{

"use": "sig",

"kty": "RSA",

            "kid": "key_id_2",

"alg": "RS512",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}

]

}


Usage


Generate a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

A JWT can be generated, in two different ways. The difference is in the token Signature definition, related to the JWT security. On one hand, a JWT can be generated using either a secret plain key (for secret key) or a private key (generating a PEM file). On the other hand, a JWT can be generated using a JSON Web Key (JWK), as a private key. This key is a JSON object.


a) Generate it using a secret plain / PEM key

──────────────────────────────────────────────────────────────────

To generate a JWT using a private key (for asymmetric algorithms), a PEM file must be generated to obtain a private and public key. Consult the Google documentation to generate these keys.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

  • Choose an algorithm using an entity identifier:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use the SymmetricAlgorithm static entity to choose a symmetric algorithm.

Use the AsymmetricAlgorithm static entity to choose an Asymmetric algorithm.

  • Choose a key identifier (key id). This key indicates which key was used to secure the signature, assigned when adding the existing key in REST service configuration. However, the key id IS NOT a signature key.


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

 

Signature configuration

  • Provide either a secret plain text key or a private key from a generated PEM file:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use a secret plain text key. It is recommended to use a long and complex secret key, because this same key is used to decrypt the generated JWT when reading it.

Use a private key from a generated PEM file. The corresponding public key must also be generated in another PEM file. Consult the Google documentation to generate these keys.

 

  • Only for Asymmetric algorithms: A passphrase can also be provided. This passphrase represents a private password that protects the specified private key.


Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).

  • Drag the corresponding action in the canvas of GenerateJWT action:

For Symmetric algorithms (using secret plain text key)

Use CreateSignedSymmetricTokenService action and fill it with values specified in the previous step for the Header, Payload and Signature.

 

 

For Asymmetric algorithms (using a private key from a PEM file)

Use CreateSignedAsymmetricTokenWithPemKeyService action and fill it with the values specified in the previous step, for the Header, Payload and Signature parts.

 

 

Step 3 - Validate the generated token

Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.





b) Generate it using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

A JSON Web Key (JWK) must be generated to obtain a private and public keypair. Consult https://mkjwk.org/ to generate all necessary keys, for testing purposes the online generator can be used but for Production is highly recommended to generate them locally or use the one from your authentication provider.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

When generating a token using a JWK as signature, the Header cannot be configured. The related JWT must use an asymmetric algorithm, and both algorithm and key id parameters are defined when generating the JSON Web Key (JWK).


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

Signature configuration

The signature must be a generated JSON Web Key (JWK). Consult https://mkjwk.org/ to generate all necessary keys.

The public and private keypair must be used to encode the JWT. The related public key (another key generated at the same time) will be used to validate the generated token.

Public and private keypair sample.

 

 

Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).
  • Drag and drop the CreateSignedAsymmetricTokenService action inside the canvas of GenerateJWT action and fill it with the values specified in the previous step, for the Header, Payload and Signature.


Step 3 - Validate the generated token


Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.


 

 

Read a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

Two types of JWT can be decoded, using the related validation method. On one hand, a JWT generated using a Plain / PEM key, can only be decoded using either the same secret plain key, or the public key related to a private PEM key. On the other hand, a JWT generated using a JSON Web Key can only be decoded using the related public key (or the generated keypair).


a) Read a JWT generated using a plain secret / PEM key

──────────────────────────────────────────────────────────────────

To verify the signature of an asymmetric generated token (token generated using a private key in a PEM file), the public key related to the private one (when generating the PEM file) is necessary.

──────────────────────────────────────────────────────────────────

Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, either the secret plain text key or public key related to the private one, must be provided.


Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.


Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.

  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.


Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent. 

 

b) Read a JWT generated using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

To verify the signature of the generated token, the public key (or keypair) related to the private one (when generating the JWK) is necessary.

──────────────────────────────────────────────────────────────────


Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, the public key related to the keypair (JWK) must be provided.

Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.

 

Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.
  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.



Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent.





Considerations when implementing a REST authentication using JSON Web Tokens

Although the action for reading tokens is the same for all signing scenarios (no separation between algorithms) and its invocation is easier that the Create Token actions, using JWT for authentication will require some preparation prior to the first call. If when creating a token for authentication in a REST service the rules to fill its payload are defined by the third-party service, now when we're implementing authentication on our service we must define the all the additional rules consumers should follow.

Should I use JSON Web Tokens?

JSON Web Tokens is just one of the authentication options for REST APIs, it works really well for scenarios where different servers need to connect, as it can provide authentication between two or even more entities. It can also be used on client-to-server implementations where there's no human involved, but whenever there's human involved in that flow an authentication based in OAuth makes much more sense.

Asymmetric or symmetric?

Assuming generated tokens will always be signed (which should be) there's the decision whether to use asymmetric or symmetric algorithm. The rule of thumb is simple:

  • Symmetric algorithms are better suited when there's a high trust between entities and the need to identify who's making the call isn't as important, so that a common secret can be shared between all parties. If that's the case a symmetric algorithm is easier to implement, and that shared secret can work in both ways of the communication. Examples:

    • Different APIs from the same suite of applications
    • Mobile calls from an app to its server, when there's no user involved
    • Different applications from the same organization
  • Asymmetric algorithms should always be used when the API is meant to be called publicly or from outside the domain of the organization, as it provides stronger identification of parties.

JSON Web Tokens aren't encrypted!

It's very important to never forget that these tokens are signed but not encrypted. It's encouraged that some additional claims are added to the tokens, like additional identifiers, but no sensitive information should ever be saved inside it.

JSON Web Tokens aren't session tokens!

It's tempting to use JSON Web Tokens as an application's session token, its custom claims can hold lots of data in a single structure that can be added throughout the session. But a JSON Web Token has a higher footprint than other simpler session containers (like plain old session variables) and with a cryptographic signature involved in each call that will take a toll in the performance. JSON Web Tokens are well suited for authentication and identification.

Further reading

Introduction to JSON Web Tokens

Authentication in REST services using JSON Web Tokens with Outsystems


External Libraries Licenses


4.0.7

JWT


Introduction


JWT is a service application that provides a set of actions to handle JSON Web Tokens, both for creating tokens and parsing existing ones, exposed via server and service actions on the JWT module, so it can be consumed in an Outsystems application. The actions provided are meant to handle different cryptographic algorithms and key formats, but they can be divided into three groups and most likely only one action per usage scenario might be needed:

  • Create/sign tokens - allows to fill the data for a token and encode it.
  • Decode/validate tokens - allows to decode and existing token, decode its information and perform validations
  • Key Helpers - provide helper actions to handle some types of keys


To learn more about JWT usage and its structure, consult the JWT introduction.

It is recommended to consult the component demo to obtain implementation examples.


Supported cryptographic features


Supported algorithm types

  • Symmetric (same key is used to sign and validate the token)

    • HS256 - HMAC using SHA-256
    • HS384 - HMAC using SHA-384
    • HS512 - HMAC using SHA-512
  • Asymmetric (private key is used to sign and public key to validate the token)

    • RS256 - RSA Signature with SHA-256
    • RS384 - RSA Signature with SHA-384
    • RS512 - RSA Signature with SHA-512


Supported key formats


PEM format

PEM format is a text file with the delimited key encoded in base64

Private keys
PKCS#5

-----BEGIN RSA PRIVATE KEY-----

Proc-Type: 4,ENCRYPTED

KEY_ENCODED_IN_BASE64

-----END RSA PRIVATE KEY-----

PKCS#8

-----BEGIN PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

----END PRIVATE KEY-----

PKCS#8 Encrypted

-----BEGIN ENCRYPTED PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

-----END ENCRYPTED PRIVATE KEY-----

Public keys
Public key from key pair

-----BEGIN PUBLIC KEY----

KEY_ENCODED_IN_BASE64

-----END PUBLIC KEY-----

X509 certificate

-----BEGIN CERTIFICATE-----

KEY_ENCODED_IN_BASE64

-----END CERTIFICATE-----

JSON format

These are text file with the key encoded in a JSON structure, equivalent to PEM but less prone to formatting errors

JSON Web Key

Represents a single key, can contain the private or public key

{

"use": "sig",

"kty": "RSA",

"kid": "key_id",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}


JSON Web Key Set

A set of multiple JSON Web Keys

{

"keys": [

{

"use": "sig",

"kty": "RSA",

"kid": "key_id_1",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

},

{

"use": "sig",

"kty": "RSA",

            "kid": "key_id_2",

"alg": "RS512",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}

]

}


Usage


Generate a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

A JWT can be generated, in two different ways. The difference is in the token Signature definition, related to the JWT security. On one hand, a JWT can be generated using either a secret plain key (for secret key) or a private key (generating a PEM file). On the other hand, a JWT can be generated using a JSON Web Key (JWK), as a private key. This key is a JSON object.


a) Generate it using a secret plain / PEM key

──────────────────────────────────────────────────────────────────

To generate a JWT using a private key (for asymmetric algorithms), a PEM file must be generated to obtain a private and public key. Consult the Google documentation to generate these keys.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

  • Choose an algorithm using an entity identifier:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use the SymmetricAlgorithm static entity to choose a symmetric algorithm.

Use the AsymmetricAlgorithm static entity to choose an Asymmetric algorithm.

  • Choose a key identifier (key id). This key indicates which key was used to secure the signature, assigned when adding the existing key in REST service configuration. However, the key id IS NOT a signature key.


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

 

Signature configuration

  • Provide either a secret plain text key or a private key from a generated PEM file:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use a secret plain text key. It is recommended to use a long and complex secret key, because this same key is used to decrypt the generated JWT when reading it.

Use a private key from a generated PEM file. The corresponding public key must also be generated in another PEM file. Consult the Google documentation to generate these keys.

 

  • Only for Asymmetric algorithms: A passphrase can also be provided. This passphrase represents a private password that protects the specified private key.


Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).

  • Drag the corresponding action in the canvas of GenerateJWT action:

For Symmetric algorithms (using secret plain text key)

Use CreateSignedSymmetricTokenService action and fill it with values specified in the previous step for the Header, Payload and Signature.

 

 

For Asymmetric algorithms (using a private key from a PEM file)

Use CreateSignedAsymmetricTokenWithPemKeyService action and fill it with the values specified in the previous step, for the Header, Payload and Signature parts.

 

 

Step 3 - Validate the generated token

Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.





b) Generate it using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

A JSON Web Key (JWK) must be generated to obtain a private and public keypair. Consult https://mkjwk.org/ to generate all necessary keys, for testing purposes the online generator can be used but for Production is highly recommended to generate them locally or use the one from your authentication provider.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

When generating a token using a JWK as signature, the Header cannot be configured. The related JWT must use an asymmetric algorithm, and both algorithm and key id parameters are defined when generating the JSON Web Key (JWK).


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

Signature configuration

The signature must be a generated JSON Web Key (JWK). Consult https://mkjwk.org/ to generate all necessary keys.

The public and private keypair must be used to encode the JWT. The related public key (another key generated at the same time) will be used to validate the generated token.

Public and private keypair sample.

 

 

Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).
  • Drag and drop the CreateSignedAsymmetricTokenService action inside the canvas of GenerateJWT action and fill it with the values specified in the previous step, for the Header, Payload and Signature.


Step 3 - Validate the generated token


Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.


 

 

Read a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

Two types of JWT can be decoded, using the related validation method. On one hand, a JWT generated using a Plain / PEM key, can only be decoded using either the same secret plain key, or the public key related to a private PEM key. On the other hand, a JWT generated using a JSON Web Key can only be decoded using the related public key (or the generated keypair).


a) Read a JWT generated using a plain secret / PEM key

──────────────────────────────────────────────────────────────────

To verify the signature of an asymmetric generated token (token generated using a private key in a PEM file), the public key related to the private one (when generating the PEM file) is necessary.

──────────────────────────────────────────────────────────────────

Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, either the secret plain text key or public key related to the private one, must be provided.


Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.


Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.

  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.


Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent. 

 

b) Read a JWT generated using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

To verify the signature of the generated token, the public key (or keypair) related to the private one (when generating the JWK) is necessary.

──────────────────────────────────────────────────────────────────


Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, the public key related to the keypair (JWK) must be provided.

Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.

 

Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.
  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.



Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent.





Considerations when implementing a REST authentication using JSON Web Tokens

Although the action for reading tokens is the same for all signing scenarios (no separation between algorithms) and its invocation is easier that the Create Token actions, using JWT for authentication will require some preparation prior to the first call. If when creating a token for authentication in a REST service the rules to fill its payload are defined by the third-party service, now when we're implementing authentication on our service we must define the all the additional rules consumers should follow.

Should I use JSON Web Tokens?

JSON Web Tokens is just one of the authentication options for REST APIs, it works really well for scenarios where different servers need to connect, as it can provide authentication between two or even more entities. It can also be used on client-to-server implementations where there's no human involved, but whenever there's human involved in that flow an authentication based in OAuth makes much more sense.

Asymmetric or symmetric?

Assuming generated tokens will always be signed (which should be) there's the decision whether to use asymmetric or symmetric algorithm. The rule of thumb is simple:

  • Symmetric algorithms are better suited when there's a high trust between entities and the need to identify who's making the call isn't as important, so that a common secret can be shared between all parties. If that's the case a symmetric algorithm is easier to implement, and that shared secret can work in both ways of the communication. Examples:

    • Different APIs from the same suite of applications
    • Mobile calls from an app to its server, when there's no user involved
    • Different applications from the same organization
  • Asymmetric algorithms should always be used when the API is meant to be called publicly or from outside the domain of the organization, as it provides stronger identification of parties.

JSON Web Tokens aren't encrypted!

It's very important to never forget that these tokens are signed but not encrypted. It's encouraged that some additional claims are added to the tokens, like additional identifiers, but no sensitive information should ever be saved inside it.

JSON Web Tokens aren't session tokens!

It's tempting to use JSON Web Tokens as an application's session token, its custom claims can hold lots of data in a single structure that can be added throughout the session. But a JSON Web Token has a higher footprint than other simpler session containers (like plain old session variables) and with a cryptographic signature involved in each call that will take a toll in the performance. JSON Web Tokens are well suited for authentication and identification.

Further reading

Introduction to JSON Web Tokens

Authentication in REST services using JSON Web Tokens with Outsystems


External Libraries Licenses


4.0.6

JWT


Introduction


JWT is a service application that provides a set of actions to handle JSON Web Tokens, both for creating tokens and parsing existing ones, exposed via server and service actions on the JWT module, so it can be consumed in an Outsystems application. The actions provided are meant to handle different cryptographic algorithms and key formats, but they can be divided into three groups and most likely only one action per usage scenario might be needed:

  • Create/sign tokens - allows to fill the data for a token and encode it.
  • Decode/validate tokens - allows to decode and existing token, decode its information and perform validations
  • Key Helpers - provide helper actions to handle some types of keys


To learn more about JWT usage and its structure, consult the JWT introduction.

It is recommended to consult the component demo to obtain implementation examples.


Supported cryptographic features


Supported algorithm types

  • Symmetric (same key is used to sign and validate the token)

    • HS256 - HMAC using SHA-256
    • HS384 - HMAC using SHA-384
    • HS512 - HMAC using SHA-512
  • Asymmetric (private key is used to sign and public key to validate the token)

    • RS256 - RSA Signature with SHA-256
    • RS384 - RSA Signature with SHA-384
    • RS512 - RSA Signature with SHA-512


Supported key formats


PEM format

PEM format is a text file with the delimited key encoded in base64

Private keys
PKCS#5

-----BEGIN RSA PRIVATE KEY-----

Proc-Type: 4,ENCRYPTED

KEY_ENCODED_IN_BASE64

-----END RSA PRIVATE KEY-----

PKCS#8

-----BEGIN PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

----END PRIVATE KEY-----

PKCS#8 Encrypted

-----BEGIN ENCRYPTED PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

-----END ENCRYPTED PRIVATE KEY-----

Public keys
Public key from key pair

-----BEGIN PUBLIC KEY----

KEY_ENCODED_IN_BASE64

-----END PUBLIC KEY-----

X509 certificate

-----BEGIN CERTIFICATE-----

KEY_ENCODED_IN_BASE64

-----END CERTIFICATE-----

JSON format

These are text file with the key encoded in a JSON structure, equivalent to PEM but less prone to formatting errors

JSON Web Key

Represents a single key, can contain the private or public key

{

"use": "sig",

"kty": "RSA",

"kid": "key_id",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}


JSON Web Key Set

A set of multiple JSON Web Keys

{

"keys": [

{

"use": "sig",

"kty": "RSA",

"kid": "key_id_1",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

},

{

"use": "sig",

"kty": "RSA",

            "kid": "key_id_2",

"alg": "RS512",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}

]

}


Usage


Generate a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

A JWT can be generated, in two different ways. The difference is in the token Signature definition, related to the JWT security. On one hand, a JWT can be generated using either a secret plain key (for secret key) or a private key (generating a PEM file). On the other hand, a JWT can be generated using a JSON Web Key (JWK), as a private key. This key is a JSON object.


a) Generate it using a secret plain / PEM key

──────────────────────────────────────────────────────────────────

To generate a JWT using a private key (for asymmetric algorithms), a PEM file must be generated to obtain a private and public key. Consult the Google documentation to generate these keys.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

  • Choose an algorithm using an entity identifier:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use the SymmetricAlgorithm static entity to choose a symmetric algorithm.

Use the AsymmetricAlgorithm static entity to choose an Asymmetric algorithm.

  • Choose a key identifier (key id). This key indicates which key was used to secure the signature, assigned when adding the existing key in REST service configuration. However, the key id IS NOT a signature key.


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

 

Signature configuration

  • Provide either a secret plain text key or a private key from a generated PEM file:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use a secret plain text key. It is recommended to use a long and complex secret key, because this same key is used to decrypt the generated JWT when reading it.

Use a private key from a generated PEM file. The corresponding public key must also be generated in another PEM file. Consult the Google documentation to generate these keys.

 

  • Only for Asymmetric algorithms: A passphrase can also be provided. This passphrase represents a private password that protects the specified private key.


Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).

  • Drag the corresponding action in the canvas of GenerateJWT action:

For Symmetric algorithms (using secret plain text key)

Use CreateSignedSymmetricTokenService action and fill it with values specified in the previous step for the Header, Payload and Signature.

 

 

For Asymmetric algorithms (using a private key from a PEM file)

Use CreateSignedAsymmetricTokenWithPemKeyService action and fill it with the values specified in the previous step, for the Header, Payload and Signature parts.

 

 

Step 3 - Validate the generated token

Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.





b) Generate it using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

A JSON Web Key (JWK) must be generated to obtain a private and public keypair. Consult https://mkjwk.org/ to generate all necessary keys, for testing purposes the online generator can be used but for Production is highly recommended to generate them locally or use the one from your authentication provider.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

When generating a token using a JWK as signature, the Header cannot be configured. The related JWT must use an asymmetric algorithm, and both algorithm and key id parameters are defined when generating the JSON Web Key (JWK).


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

Signature configuration

The signature must be a generated JSON Web Key (JWK). Consult https://mkjwk.org/ to generate all necessary keys.

The public and private keypair must be used to encode the JWT. The related public key (another key generated at the same time) will be used to validate the generated token.

Public and private keypair sample.

 

 

Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).
  • Drag and drop the CreateSignedAsymmetricTokenService action inside the canvas of GenerateJWT action and fill it with the values specified in the previous step, for the Header, Payload and Signature.


Step 3 - Validate the generated token


Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.


 

 

Read a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

Two types of JWT can be decoded, using the related validation method. On one hand, a JWT generated using a Plain / PEM key, can only be decoded using either the same secret plain key, or the public key related to a private PEM key. On the other hand, a JWT generated using a JSON Web Key can only be decoded using the related public key (or the generated keypair).


a) Read a JWT generated using a plain secret / PEM key

──────────────────────────────────────────────────────────────────

To verify the signature of an asymmetric generated token (token generated using a private key in a PEM file), the public key related to the private one (when generating the PEM file) is necessary.

──────────────────────────────────────────────────────────────────

Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, either the secret plain text key or public key related to the private one, must be provided.


Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.


Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.

  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.


Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent. 

 

b) Read a JWT generated using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

To verify the signature of the generated token, the public key (or keypair) related to the private one (when generating the JWK) is necessary.

──────────────────────────────────────────────────────────────────


Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, the public key related to the keypair (JWK) must be provided.

Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.

 

Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.
  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.



Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent.





Considerations when implementing a REST authentication using JSON Web Tokens

Although the action for reading tokens is the same for all signing scenarios (no separation between algorithms) and its invocation is easier that the Create Token actions, using JWT for authentication will require some preparation prior to the first call. If when creating a token for authentication in a REST service the rules to fill its payload are defined by the third-party service, now when we're implementing authentication on our service we must define the all the additional rules consumers should follow.

Should I use JSON Web Tokens?

JSON Web Tokens is just one of the authentication options for REST APIs, it works really well for scenarios where different servers need to connect, as it can provide authentication between two or even more entities. It can also be used on client-to-server implementations where there's no human involved, but whenever there's human involved in that flow an authentication based in OAuth makes much more sense.

Asymmetric or symmetric?

Assuming generated tokens will always be signed (which should be) there's the decision whether to use asymmetric or symmetric algorithm. The rule of thumb is simple:

  • Symmetric algorithms are better suited when there's a high trust between entities and the need to identify who's making the call isn't as important, so that a common secret can be shared between all parties. If that's the case a symmetric algorithm is easier to implement, and that shared secret can work in both ways of the communication. Examples:

    • Different APIs from the same suite of applications
    • Mobile calls from an app to its server, when there's no user involved
    • Different applications from the same organization
  • Asymmetric algorithms should always be used when the API is meant to be called publicly or from outside the domain of the organization, as it provides stronger identification of parties.

JSON Web Tokens aren't encrypted!

It's very important to never forget that these tokens are signed but not encrypted. It's encouraged that some additional claims are added to the tokens, like additional identifiers, but no sensitive information should ever be saved inside it.

JSON Web Tokens aren't session tokens!

It's tempting to use JSON Web Tokens as an application's session token, its custom claims can hold lots of data in a single structure that can be added throughout the session. But a JSON Web Token has a higher footprint than other simpler session containers (like plain old session variables) and with a cryptographic signature involved in each call that will take a toll in the performance. JSON Web Tokens are well suited for authentication and identification.

Further reading

Introduction to JSON Web Tokens

Authentication in REST services using JSON Web Tokens with Outsystems


External Libraries Licenses


4.0.5

JWT


Introduction


JWT is a service application that provides a set of actions to handle JSON Web Tokens, both for creating tokens and parsing existing ones, exposed via server and service actions on the JWT module, so it can be consumed in an Outsystems application. The actions provided are meant to handle different cryptographic algorithms and key formats, but they can be divided into three groups and most likely only one action per usage scenario might be needed:

  • Create/sign tokens - allows to fill the data for a token and encode it.
  • Decode/validate tokens - allows to decode and existing token, decode its information and perform validations
  • Key Helpers - provide helper actions to handle some types of keys


To learn more about JWT usage and its structure, consult the JWT introduction.

It is recommended to consult the component demo to obtain implementation examples.


Supported cryptographic features


Supported algorithm types

  • Symmetric (same key is used to sign and validate the token)

    • HS256 - HMAC using SHA-256
    • HS384 - HMAC using SHA-384
    • HS512 - HMAC using SHA-512
  • Asymmetric (private key is used to sign and public key to validate the token)

    • RS256 - RSA Signature with SHA-256
    • RS384 - RSA Signature with SHA-384
    • RS512 - RSA Signature with SHA-512


Supported key formats


PEM format

PEM format is a text file with the delimited key encoded in base64

Private keys
PKCS#5

-----BEGIN RSA PRIVATE KEY-----

Proc-Type: 4,ENCRYPTED

KEY_ENCODED_IN_BASE64

-----END RSA PRIVATE KEY-----

PKCS#8

-----BEGIN PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

----END PRIVATE KEY-----

PKCS#8 Encrypted

-----BEGIN ENCRYPTED PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

-----END ENCRYPTED PRIVATE KEY-----

Public keys
Public key from key pair

-----BEGIN PUBLIC KEY----

KEY_ENCODED_IN_BASE64

-----END PUBLIC KEY-----

X509 certificate

-----BEGIN CERTIFICATE-----

KEY_ENCODED_IN_BASE64

-----END CERTIFICATE-----

JSON format

These are text file with the key encoded in a JSON structure, equivalent to PEM but less prone to formatting errors

JSON Web Key

Represents a single key, can contain the private or public key

{

"use": "sig",

"kty": "RSA",

"kid": "key_id",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}


JSON Web Key Set

A set of multiple JSON Web Keys

{

"keys": [

{

"use": "sig",

"kty": "RSA",

"kid": "key_id_1",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

},

{

"use": "sig",

"kty": "RSA",

            "kid": "key_id_2",

"alg": "RS512",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}

]

}


Usage


Generate a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

A JWT can be generated, in two different ways. The difference is in the token Signature definition, related to the JWT security. On one hand, a JWT can be generated using either a secret plain key (for secret key) or a private key (generating a PEM file). On the other hand, a JWT can be generated using a JSON Web Key (JWK), as a private key. This key is a JSON object.


a) Generate it using a secret plain / PEM key

──────────────────────────────────────────────────────────────────

To generate a JWT using a private key (for asymmetric algorithms), a PEM file must be generated to obtain a private and public key. Consult the Google documentation to generate these keys.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

  • Choose an algorithm using an entity identifier:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use the SymmetricAlgorithm static entity to choose a symmetric algorithm.

Use the AsymmetricAlgorithm static entity to choose an Asymmetric algorithm.

  • Choose a key identifier (key id). This key indicates which key was used to secure the signature, assigned when adding the existing key in REST service configuration. However, the key id IS NOT a signature key.


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

 

Signature configuration

  • Provide either a secret plain text key or a private key from a generated PEM file:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use a secret plain text key. It is recommended to use a long and complex secret key, because this same key is used to decrypt the generated JWT when reading it.

Use a private key from a generated PEM file. The corresponding public key must also be generated in another PEM file. Consult the Google documentation to generate these keys.

 

  • Only for Asymmetric algorithms: A passphrase can also be provided. This passphrase represents a private password that protects the specified private key.


Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).

  • Drag the corresponding action in the canvas of GenerateJWT action:

For Symmetric algorithms (using secret plain text key)

Use CreateSignedSymmetricTokenService action and fill it with values specified in the previous step for the Header, Payload and Signature.

 

 

For Asymmetric algorithms (using a private key from a PEM file)

Use CreateSignedAsymmetricTokenWithPemKeyService action and fill it with the values specified in the previous step, for the Header, Payload and Signature parts.

 

 

Step 3 - Validate the generated token

Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.





b) Generate it using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

A JSON Web Key (JWK) must be generated to obtain a private and public keypair. Consult https://mkjwk.org/ to generate all necessary keys, for testing purposes the online generator can be used but for Production is highly recommended to generate them locally or use the one from your authentication provider.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

When generating a token using a JWK as signature, the Header cannot be configured. The related JWT must use an asymmetric algorithm, and both algorithm and key id parameters are defined when generating the JSON Web Key (JWK).


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

Signature configuration

The signature must be a generated JSON Web Key (JWK). Consult https://mkjwk.org/ to generate all necessary keys.

The public and private keypair must be used to encode the JWT. The related public key (another key generated at the same time) will be used to validate the generated token.

Public and private keypair sample.

 

 

Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).
  • Drag and drop the CreateSignedAsymmetricTokenService action inside the canvas of GenerateJWT action and fill it with the values specified in the previous step, for the Header, Payload and Signature.


Step 3 -  Validate the generated token


Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.


 

 

Read a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

Two types of JWT can be decoded, using the related validation method. On one hand, a JWT generated using a Plain / PEM key, can only be decoded using either the same secret plain key, or the public key related to a private PEM key. On the other hand, a JWT generated using a JSON Web Key can only be decoded using the related public key (or the generated keypair).


a) Read a JWT generated using a plain secret / PEM key

──────────────────────────────────────────────────────────────────

To verify the signature of an asymmetric generated token (token generated using a private key in a PEM file), the public key related to the private one (when generating the PEM file) is necessary.

──────────────────────────────────────────────────────────────────

Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, either the secret plain text key or public key related to the private one, must be provided.


Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.


Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.

  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.


Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent. 

 

b) Read a JWT generated using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

To verify the signature of the generated token, the public key (or keypair) related to the private one (when generating the JWK) is necessary.

──────────────────────────────────────────────────────────────────


Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, the public key related to the keypair (JWK) must be provided.

Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.

 

Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.
  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.



Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent.





Considerations when implementing a REST authentication using JSON Web Tokens

Although the action for reading tokens is the same for all signing scenarios (no separation between algorithms) and its invocation is easier that the Create Token actions, using JWT for authentication will require some preparation prior to the first call. If when creating a token for authentication in a REST service the rules to fill its payload are defined by the third-party service, now when we're implementing authentication on our service we must define the all the additional rules consumers should follow.

Should I use JSON Web Tokens?

JSON Web Tokens is just one of the authentication options for REST APIs, it works really well for scenarios where different servers need to connect, as it can provide authentication between two or even more entities. It can also be used on client-to-server implementations where there's no human involved, but whenever there's human involved in that flow an authentication based in OAuth makes much more sense.

Asymmetric or symmetric?

Assuming generated tokens will always be signed (which should be) there's the decision whether to use asymmetric or symmetric algorithm. The rule of thumb is simple:

  • Symmetric algorithms are better suited when there's a high trust between entities and the need to identify who's making the call isn't as important, so that a common secret can be shared between all parties. If that's the case a symmetric algorithm is easier to implement, and that shared secret can work in both ways of the communication. Examples:

    • Different APIs from the same suite of applications
    • Mobile calls from an app to its server, when there's no user involved
    • Different applications from the same organization
  • Asymmetric algorithms should always be used when the API is meant to be called publicly or from outside the domain of the organization, as it provides stronger identification of parties.

JSON Web Tokens aren't encrypted!

It's very important to never forget that these tokens are signed but not encrypted. It's encouraged that some additional claims are added to the tokens, like additional identifiers, but no sensitive information should ever be saved inside it.

JSON Web Tokens aren't session tokens!

It's tempting to use JSON Web Tokens as an application's session token, its custom claims can hold lots of data in a single structure that can be added throughout the session. But a JSON Web Token has a higher footprint than other simpler session containers (like plain old session variables) and with a cryptographic signature involved in each call that will take a toll in the performance. JSON Web Tokens are well suited for authentication and identification.

Further reading

Introduction to JSON Web Tokens

Authentication in REST services using JSON Web Tokens with Outsystems



4.0.4

JWT


Introduction


JWT is a service application that provides a set of actions to handle JSON Web Tokens, both for creating tokens and parsing existing ones, exposed via server and service actions on the JWT module, so it can be consumed in an Outsystems application. The actions provided are meant to handle different cryptographic algorithms and key formats, but they can be divided into three groups and most likely only one action per usage scenario might be needed:

  • Create/sign tokens - allows to fill the data for a token and encode it.
  • Decode/validate tokens - allows to decode and existing token, decode its information and perform validations
  • Key Helpers - provide helper actions to handle some types of keys


To learn more about JWT usage and its structure, consult the JWT introduction.

It is recommended to consult the component demo to obtain implementation examples.


Supported cryptographic features


Supported algorithm types

  • Symmetric (same key is used to sign and validate the token)

    • HS256 - HMAC using SHA-256
    • HS384 - HMAC using SHA-384
    • HS512 - HMAC using SHA-512
  • Asymmetric (private key is used to sign and public key to validate the token)

    • RS256 - RSA Signature with SHA-256
    • RS384 - RSA Signature with SHA-384
    • RS512 - RSA Signature with SHA-512


Supported key formats


PEM format

PEM format is a text file with the delimited key encoded in base64

Private keys
PKCS#5

-----BEGIN RSA PRIVATE KEY-----

Proc-Type: 4,ENCRYPTED

KEY_ENCODED_IN_BASE64

-----END RSA PRIVATE KEY-----

PKCS#8

-----BEGIN PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

----END PRIVATE KEY-----

PKCS#8 Encrypted

-----BEGIN ENCRYPTED PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

-----END ENCRYPTED PRIVATE KEY-----

Public keys
Public key from key pair

-----BEGIN PUBLIC KEY----

KEY_ENCODED_IN_BASE64

-----END PUBLIC KEY-----

X509 certificate

-----BEGIN CERTIFICATE-----

KEY_ENCODED_IN_BASE64

-----END CERTIFICATE-----

JSON format

These are text file with the key encoded in a JSON structure, equivalent to PEM but less prone to formatting errors

JSON Web Key

Represents a single key, can contain the private or public key

{

"use": "sig",

"kty": "RSA",

"kid": "key_id",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}


JSON Web Key Set

A set of multiple JSON Web Keys

{

"keys": [

{

"use": "sig",

"kty": "RSA",

"kid": "key_id_1",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

},

{

"use": "sig",

"kty": "RSA",

            "kid": "key_id_2",

"alg": "RS512",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}

]

}


Usage


Generate a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

A JWT can be generated, in two different ways. The difference is in the token Signature definition, related to the JWT security. On one hand, a JWT can be generated using either a secret plain key (for secret key) or a private key (generating a PEM file). On the other hand, a JWT can be generated using a JSON Web Key (JWK), as a private key. This key is a JSON object.


a) Generate it using a secret plain / PEM key

──────────────────────────────────────────────────────────────────

To generate a JWT using a private key (for asymmetric algorithms), a PEM file must be generated to obtain a private and public key. Consult the Google documentation to generate these keys.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

  • Choose an algorithm using an entity identifier:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use the SymmetricAlgorithm static entity to choose a symmetric algorithm.

Use the AsymmetricAlgorithm static entity to choose an Asymmetric algorithm.

  • Choose a key identifier (key id). This key indicates which key was used to secure the signature, assigned when adding the existing key in REST service configuration. However, the key id IS NOT a signature key.


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

 

Signature configuration

  • Provide either a secret plain text key or a private key from a generated PEM file:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use a secret plain text key. It is recommended to use a long and complex secret key, because this same key is used to decrypt the generated JWT when reading it.

Use a private key from a generated PEM file. The corresponding public key must also be generated in another PEM file. Consult the Google documentation to generate these keys.

 

  • Only for Asymmetric algorithms: A passphrase can also be provided. This passphrase represents a private password that protects the specified private key.


 Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).

  • Drag the corresponding action in the canvas of GenerateJWT action:

For Symmetric algorithms (using secret plain text key)

Use CreateSignedSymmetricTokenService action and fill it with values specified in the previous step for the Header, Payload and Signature.

 

 

For Asymmetric algorithms (using a private key from a PEM file)

Use CreateSignedAsymmetricTokenWithPemKeyService action and fill it with the values specified in the previous step, for the Header, Payload and Signature parts.

 

 

Step 3 - Validate the generated token

Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.





b) Generate it using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

A JSON Web Key (JWK) must be generated to obtain a private and public keypair. Consult https://mkjwk.org/ to generate all necessary keys, for testing purposes the online generator can be used but for Production is highly recommended to generate them locally or use the one from your authentication provider.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

When generating a token using a JWK as signature, the Header cannot be configured. The related JWT must use an asymmetric algorithm, and both algorithm and key id parameters are defined when generating the JSON Web Key (JWK).


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

Signature configuration

The signature must be a generated JSON Web Key (JWK). Consult https://mkjwk.org/ to generate all necessary keys.

The public and private keypair must be used to encode the JWT. The related public key (another key generated at the same time) will be used to validate the generated token.

Public and private keypair sample.

 

 

Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).
  • Drag and drop the CreateSignedAsymmetricTokenService action inside the canvas of GenerateJWT action and fill it with the values specified in the previous step, for the Header, Payload and Signature.


Step 3 -  Validate the generated token


Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.


 

 

Read a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

Two types of JWT can be decoded, using the related validation method. On one hand, a JWT generated using a Plain / PEM key, can only be decoded using either the same secret plain key, or the public key related to a private PEM key. On the other hand, a JWT generated using a JSON Web Key can only be decoded using the related public key (or the generated keypair).


a) Read a JWT generated using a plain secret / PEM key

──────────────────────────────────────────────────────────────────

To verify the signature of an asymmetric generated token (token generated using a private key in a PEM file), the public key related to the private one (when generating the PEM file) is necessary.

──────────────────────────────────────────────────────────────────

Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, either the secret plain text key or public key related to the private one, must be provided.


Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.


Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.

  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.


 Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent. 

 

 b) Read a JWT generated using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

To verify the signature of the generated token, the public key (or keypair) related to the private one (when generating the JWK) is necessary.

──────────────────────────────────────────────────────────────────


Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, the public key related to the keypair (JWK) must be provided.

Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.

 

Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.
  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.



Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent.





Considerations when implementing a REST authentication using JSON Web Tokens

Although the action for reading tokens is the same for all signing scenarios (no separation between algorithms) and its invocation is easier that the Create Token actions, using JWT for authentication will require some preparation prior to the first call. If when creating a token for authentication in a REST service the rules to fill its payload are defined by the third-party service, now when we're implementing authentication on our service we must define the all the additional rules consumers should follow.

Should I use JSON Web Tokens?

JSON Web Tokens is just one of the authentication options for REST APIs, it works really well for scenarios where different servers need to connect, as it can provide authentication between two or even more entities. It can also be used on client-to-server implementations where there's no human involved, but whenever there's human involved in that flow an authentication based in OAuth makes much more sense.

Asymmetric or symmetric?

Assuming generated tokens will always be signed (which should be) there's the decision whether to use asymmetric or symmetric algorithm. The rule of thumb is simple:

  • Symmetric algorithms are better suited when there's a high trust between entities and the need to identify who's making the call isn't as important, so that a common secret can be shared between all parties. If that's the case a symmetric algorithm is easier to implement, and that shared secret can work in both ways of the communication. Examples:

    • Different APIs from the same suite of applications
    • Mobile calls from an app to its server, when there's no user involved
    • Different applications from the same organization
  • Asymmetric algorithms should always be used when the API is meant to be called publicly or from outside the domain of the organization, as it provides stronger identification of parties.

JSON Web Tokens aren't encrypted!

It's very important to never forget that these tokens are signed but not encrypted. It's encouraged that some additional claims are added to the tokens, like additional identifiers, but no sensitive information should ever be saved inside it.

JSON Web Tokens aren't session tokens!

It's tempting to use JSON Web Tokens as an application's session token, its custom claims can hold lots of data in a single structure that can be added throughout the session. But a JSON Web Token has a higher footprint than other simpler session containers (like plain old session variables) and with a cryptographic signature involved in each call that will take a toll in the performance. JSON Web Tokens are well suited for authentication and identification.

Further reading

Introduction to JSON Web Tokens

Authentication in REST services using JSON Web Tokens with Outsystems



4.0.3

JWT


Introduction


JWT is a service application that provides a set of actions to handle JSON Web Tokens, both for creating tokens and parsing existing ones, exposed via server and service actions on the JWT module, so it can be consumed in an Outsystems application. The actions provided are meant to handle different cryptographic algorithms and key formats, but they can be divided into three groups and most likely only one action per usage scenario might be needed:

  • Create/sign tokens - allows to fill the data for a token and encode it.
  • Decode/validate tokens - allows to decode and existing token, decode its information and perform validations
  • Key Helpers - provide helper actions to handle some types of keys


To learn more about JWT usage and its structure, consult the JWT introduction.

It is recommended to consult the component demo to obtain implementation examples.


Supported cryptographic features


Supported algorithm types

  • Symmetric (same key is used to sign and validate the token)

    • HS256 - HMAC using SHA-256
    • HS384 - HMAC using SHA-384
    • HS512 - HMAC using SHA-512
  • Asymmetric (private key is used to sign and public key to validate the token)

    • RS256 - RSA Signature with SHA-256
    • RS384 - RSA Signature with SHA-384
    • RS512 - RSA Signature with SHA-512


Supported key formats


PEM format

PEM format is a text file with the delimited key encoded in base64

Private keys
PKCS#5

-----BEGIN RSA PRIVATE KEY-----

Proc-Type: 4,ENCRYPTED

KEY_ENCODED_IN_BASE64

-----END RSA PRIVATE KEY-----

PKCS#8

-----BEGIN PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

----END PRIVATE KEY-----

PKCS#8 Encrypted

-----BEGIN ENCRYPTED PRIVATE KEY-----

KEY_ENCODED_IN_BASE64

-----END ENCRYPTED PRIVATE KEY-----

Public keys
Public key from key pair

-----BEGIN PUBLIC KEY----

KEY_ENCODED_IN_BASE64

-----END PUBLIC KEY-----

X509 certificate

-----BEGIN CERTIFICATE-----

KEY_ENCODED_IN_BASE64

-----END CERTIFICATE-----

JSON format

These are text file with the key encoded in a JSON structure, equivalent to PEM but less prone to formatting errors

JSON Web Key

Represents a single key, can contain the private or public key

{

"use": "sig",

"kty": "RSA",

"kid": "key_id",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}


JSON Web Key Set

A set of multiple JSON Web Keys

{

"keys": [

{

"use": "sig",

"kty": "RSA",

"kid": "key_id_1",

"alg": "RS256",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

},

{

"use": "sig",

"kty": "RSA",

            "kid": "key_id_2",

"alg": "RS512",

"n": "KEY_ENCODED_IN_BASE64",

"e": "AQAB"

}

]

}


Usage


Generate a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

A JWT can be generated, in two different ways. The difference is in the token Signature definition, related to the JWT security. On one hand, a JWT can be generated using either a secret plain key (for secret key) or a private key (generating a PEM file). On the other hand, a JWT can be generated using a JSON Web Key (JWK), as a private key. This key is a JSON object.


a) Generate it using a secret plain / PEM key

──────────────────────────────────────────────────────────────────

To generate a JWT using a private key (for asymmetric algorithms), a PEM file must be generated to obtain a private and public key. Consult the Google documentation to generate these keys.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

  • Choose an algorithm using an entity identifier:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use the SymmetricAlgorithm static entity to choose a symmetric algorithm.

Use the AsymmetricAlgorithm static entity to choose an Asymmetric algorithm.

  • Choose a key identifier (key id). This key indicates which key was used to secure the signature, assigned when adding the existing key in REST service configuration. However, the key id IS NOT a signature key.


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

 

Signature configuration

  • Provide either a secret plain text key or a private key from a generated PEM file:

For Symmetric algorithms

(secret plain text key)

For Asymmetric algorithms

(private key from PEM file)

Use a secret plain text key. It is recommended to use a long and complex secret key, because this same key is used to decrypt the generated JWT when reading it.

Use a private key from a generated PEM file. The corresponding public key must also be generated in another PEM file. Consult the Google documentation to generate these keys.

 

  • Only for Asymmetric algorithms: A passphrase can also be provided. This passphrase represents a private password that protects the specified private key.


 Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion).

  • Drag the corresponding action in the canvas of GenerateJWT action:

For Symmetric algorithms (using secret plain text key)

Use CreateSignedSymmetricTokenService action and fill it with values specified in the previous step for the Header, Payload and Signature.

 

 

For Asymmetric algorithms (using a private key from a PEM file)

Use CreateSignedAsymmetricTokenWithPemKeyService action and fill it with the values specified in the previous step, for the Header, Payload and Signature parts.

 

 

Step 3 - Validate the generated token

Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.





b) Generate it using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

A JSON Web Key (JWK) must be generated to obtain a private and public keypair. Consult https://mkjwk.org/ to generate all necessary keys, for testing purposes the online generator can be used but for Production is highly recommended to generate them locally or use the one from your authentication provider.

──────────────────────────────────────────────────────────────────

Step 1 - JSON Web Token (JWT) configuration

Header configuration

When generating a token using a JWK as signature, the Header cannot be configured. The related JWT must use an asymmetric algorithm, and both algorithm and key id parameters are defined when generating the JSON Web Key (JWK).


Payload configuration

Fill the Payload data. All data is optional, however it is recommended to fill some Payload information. Custom claims can also be added. This image shows all Payload information that can be added in the generated token.

The given data is only as an example. You must adapt the data with your requirements.

Signature configuration

The signature must be a generated JSON Web Key (JWK). Consult https://mkjwk.org/ to generate all necessary keys.

The public and private keypair must be used to encode the JWT. The related public key (another key generated at the same time) will be used to validate the generated token.

Public and private keypair sample.

 

 

Step 2 - Configure the corresponding action

  • Create a submit action (typically a screen action) to handle the JWT generation and its validation. Name it GenerateJWT (as suggestion). 
  • Drag and drop the CreateSignedAsymmetricTokenService action inside the canvas of GenerateJWT action and fill it with the values specified in the previous step, for the Header, Payload and Signature. 


Step 3 -  Validate the generated token


Verify the success parameter returned by the corresponding action. An encoded token is also returned, and can be separated to obtain the header, payload and the signature individually using a String_Split action.


 

 

Read a JSON Web Token (JWT)

──────────────────────────────────────────────────────────────────

Two types of JWT can be decoded, using the related validation method. On one hand, a JWT generated using a Plain / PEM key, can only be decoded using either the same secret plain key, or the public key related to a private PEM key. On the other hand, a JWT generated using a JSON Web Key can only be decoded using the related public key (or the generated keypair).


a) Read a JWT generated using a plain secret / PEM key

──────────────────────────────────────────────────────────────────

To verify the signature of an asymmetric generated token (token generated using a private key in a PEM file), the public key related to the private one (when generating the PEM file) is necessary.

──────────────────────────────────────────────────────────────────

Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, either the secret plain text key or public key related to the private one, must be provided.


Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.


Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.

  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.


 Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent. 

 

 b) Read a JWT generated using a JSON Web Key (JWK)

──────────────────────────────────────────────────────────────────

To verify the signature of the generated token, the public key (or keypair) related to the private one (when generating the JWK) is necessary.

──────────────────────────────────────────────────────────────────


Step 1 - Configure all necessary parameters

  • Provide the encoded JSON Web Token to decode and read.
  • Provide values about verifications to perform when decoding the JWT. When no verifications are specified, the token is readed, but the signature part is not verified. To verify the signature, the public key related to the keypair (JWK) must be provided.

Note:

To verify the LifeTime, the expected Issuer and the expected Audience, the signature verification must be enabled (set as TRUE).

All input parameters to decode a generated JWT.

 

Step 2 - Configure the corresponding action

  • Create a read action (typically a screen action) to handle the JWT reading and decoding.
  • Open the read action (ReadToken) created previously and drag the ReadTokenService action in the canvas. Fill the action parameters, passing the encoded token, and verifications to perform with expected values.



Step 3 - Trigger the read action to decode the JWT

The read action created in the first step, can be triggered using a button or a link with the Destination property set to the read token action.

The ReadTokenService action returns the following parameters:

  • PlainToken: The decoded token information in JSON format
  • TokenPayloadRec: All Payload data of decoded token.
  • TokenHeaderRec: All Header data of decoded token.
  • ValidToken: Defines if the decoded token is a valid one.
  • ResultMessage: If validation fails, an output message is sent.





Considerations when implementing a REST authentication using JSON Web Tokens

Although the action for reading tokens is the same for all signing scenarios (no separation between algorithms) and its invocation is easier that the Create Token actions, using JWT for authentication will require some preparation prior to the first call. If when creating a token for authentication in a REST service the rules to fill its payload are defined by the third-party service, now when we're implementing authentication on our service we must define the all the additional rules consumers should follow.

Should I use JSON Web Tokens?

JSON Web Tokens is just one of the authentication options for REST APIs, it works really well for scenarios where different servers need to connect, as it can provide authentication between two or even more entities. It can also be used on client-to-server implementations where there's no human involved, but whenever there's human involved in that flow an authentication based in OAuth makes much more sense.

Asymmetric or symmetric?

Assuming generated tokens will always be signed (which should be) there's the decision whether to use asymmetric or symmetric algorithm. The rule of thumb is simple:

  • Symmetric algorithms are better suited when there's a high trust between entities and the need to identify who's making the call isn't as important, so that a common secret can be shared between all parties. If that's the case a symmetric algorithm is easier to implement, and that shared secret can work in both ways of the communication. Examples:

    • Different APIs from the same suite of applications
    • Mobile calls from an app to its server, when there's no user involved
    • Different applications from the same organization
  • Asymmetric algorithms should always be used when the API is meant to be called publicly or from outside the domain of the organization, as it provides stronger identification of parties.

JSON Web Tokens aren't encrypted!

It's very important to never forget that these tokens are signed but not encrypted. It's encouraged that some additional claims are added to the tokens, like additional identifiers, but no sensitive information should ever be saved inside it.

JSON Web Tokens aren't session tokens!

It's tempting to use JSON Web Tokens as an application's session token, its custom claims can hold lots of data in a single structure that can be added throughout the session. But a JSON Web Token has a higher footprint than other simpler session containers (like plain old session variables) and with a cryptographic signature involved in each call that will take a toll in the performance. JSON Web Tokens are well suited for authentication and identification.

Further reading

Introduction to JSON Web Tokens

Authentication in REST services using JSON Web Tokens with Outsystems