[JWT] JWT for REST APIs. Where to keep the token and the public key?
Forge component by João Almeida
Application Type
Service

Hello,

I am exposing a REST API and would like to create authentication logic with JWT. I installed this Forge component but there are a few things I don't understand regarding the use of Asymmetric Signature with JSON Web Key. Some of my doubts are:

  • Should I generate a new public/private key pair each time I generate a token? How do I pass the Public key to the API, should I do it in the payload?
  • Should I save the token in a session variable in the consumer module or generate a new token each time I call the service?

Thanks in advance!

Solution

In short:

a) keep pub/priv keys unique per environment. Private key should be kept very secret and public one exposed via JWKS. Change ~once a year or if compromised.

b) session stuff doesn't work on Outsystems API endpoints, no session vars. If you need to bound it with UI sessions, then you need to create custom authorization on API endpoint, but you have to rely on JWT tokens, thus include UserID, TenantID in JWT cliams and then in custom auth extract them and do TenantSwitch -> UserLogin, to have user context in API stuff. Of course always check if JWT token is valid. Btw you can store JWT in session cookie too.

I have the same doubts. 

Solution

In short:

a) keep pub/priv keys unique per environment. Private key should be kept very secret and public one exposed via JWKS. Change ~once a year or if compromised.

b) session stuff doesn't work on Outsystems API endpoints, no session vars. If you need to bound it with UI sessions, then you need to create custom authorization on API endpoint, but you have to rely on JWT tokens, thus include UserID, TenantID in JWT cliams and then in custom auth extract them and do TenantSwitch -> UserLogin, to have user context in API stuff. Of course always check if JWT token is valid. Btw you can store JWT in session cookie too.

Thanks for your feedback Ivan!

Could you clarify what "exposed via JWKS" means? Is it something that goes in the payload of the token?


Basically @Ivan Nudzik wrapped it up pretty well, but just want to add something. Are you exposing or consuming an API with JWT? Because  you start by saying you're exposing the service, but is questions are related with consuming one.

  • The setup of keys is the authentication part of the token and is something that's part of the setup of the API usage, so it isn't meant to be changed regularly, just like Ivan wrote. Assuming you're indeed consuming an API, the public key must set in the API service's configuration in some way (usually via a developer dashboard) but you must check with their support or documentation on how to do it.
  • Just as long as the token hasn't expired and the information defined in it remains valid you can reuse it.  

Thanks for your feedback João.

Actually I am both exposing and consuming the API, since I am trying to understand how the authentication flow works. It's the first time I implement this king of logic. Right now I have:

  1. a module that exposes the API
  2. a module that deals with authentication and token generation
  3. a module that consumes the API

So let me see if I got it right. 

  • The public/private key pair is used by module B
  • Module B provides the endpoint with the public key for module A to verify the signature
  • Module C is agnostic to all of this keys


That's not it. Trying to understand generating and validating token at the same time may be a bit too much at the same time, I'd advise to take a look at consuming a REST service with JWT by looking at an existing service first.

Modules shouldn't expose private keys in endpoints at all! Public keys may be exposed publicly, to easily share them, but the flow doesn't them to be exposed. In theory when it begins the corresponding key should already be configured in the producer and consumer.


The short version of the flow goes like this: 

  1. The consumer (not the module C) will generate a keypair
  2. The private key of the keypair is meant to be saved in some kind of configuration on the consumer side
  3. The public key of the keypair is meant to be set in the producer, usually via a web interface or similar (like a developer dashboard). Basically this is a configuration in the producer for each client
  4. Module C, in order to call the endpoint of module A, must generate a JWT, it will do so and sign it using the private key already saved in 2)
  5. Module C calls Module A endpoint, passing the generated JWT in the request, usually as a Bearer in the Header but can be in the body also
  6. Module A receives the request, reads the JWT (a JWT is signed but never encrypted, data is encoded but readable).
  7. Module A retrieves the public key configured in 3) for the user/client/account/id/etc. defined in the received token
  8. Module A validates the received JWT signature with that saved public key


Another question: are you implementing exposing and consuming because those are parts of the same implementation? If so, consider using symmetric signature instead, which is much more suited in scenarios where there's a higher trust between the producer and consumer.  

You are right, it's a bit confusing doing both at the same time!

It's getting clearer for me now with your explanation of the flow. I am going to seach for some free API on the web to consume and get a better grip of all this concepts.

Concerning your question: Yes those are parts of an implementation based on services. I am going to consider using the symmetric key. I was testing the asymetric key just to understand it.



 

Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.