In a microservice environment, should any producer be able to verify JWT tokens? - authentication

I'm trying to figuring out how to manage authorization in a microservice environment.
This is my hypothetical scenario.
I have a service which provides authentication (using devise gem) and authorization via oauth2 (using doorkeeper gem). Once logged in, the service returns a JWT token to the user.
Now let's suppose I have two API servers. The user must provide the JWT token to these API servers in order to access to private resources.
Is it ok to share the JWT secret key I used to sign JWT token with my two API servers so they can decode the token and verify its validity? Or should my API servers forward the JWT token to the authorization service and ask it to verify it?
Pros of sharing JWT secret key with API servers:
no round trip to the authorization service
Cons of sharing JWT secret key with API servers:
if someone breaks in any of my API server, he/she have access to my JWT secret key
I am stuck. I don't even know if there is a third solution I didn't consider :)
Thanks!

You can use a PKI signing/verification system. In this approach, your authorization service will sign the JWT using a private key and all the consuming services will need the public key to use the JWT. The public key can be distributed easily - maybe through a config server if you have that in your architecture. Even if someone breaks into one of your services then he will only have a public key and not the private key.

Related

Authentication in microservices using jwt

I'm going to build micrservices using Laravel framework.
I have users microservice that processes clients credentials and authenticates them (creates JWT for clients).
Also, there are another microservices that require user authentication.
And the question is, how can i validate clients access tokens in microservices (except users microservice), if the secret access token key is only in users microservice? Or, should i keep the secret key in each microservice?
Instead of handing out the secret key to each service you might want to consider signing JWTs with private/public key pair using RSA. That way only one service has the ability to create/modify tokens and the others can only verify them. Public key should be stored in the services or requested from the authentication service in the backend.
More thoughts on SSO in microservices can be found here.

Use JWT to authenticate separate API Microservice

I am developing an app using microservices in NodeJS. I have built an auth api which handles the usual registration login etc and it issues JWT's
How do I use these to protect routes in a separate API microservice written with Express?
Do I need to use JWT with the secret to decrypt the token in the API app?
You could write a library that you import into your other microservices that requires all routes by default to require authentication. This library could have a mechanism to validate JWT's at the microservice level, so you never need to talk to your auth api to see if a JWT is valid or not. See the description and diagram below:
Your auth server will will need to be the single issuer of JWTs to your microservices. So, when a user logs in and successfully authenticates, your auth server will issue a JWT signed with a private key (signing MUST be asymmetric - RS256 is one example) you keep on the auth server only; do not give this private key to other microservices that you wish to validate JWTs inside of. What you can do is derive a public key based on the private key you sign your tokens with and publish that to an endpoint on your auth server that requires no authentication - the public key will be represented in the form of a JWK (see link to spec). Google does something similar here. Then, in each of your microservices, your library will need to devise a way to make a GET request to the public key endpoint on your auth server every X minutes to see if there are any changes and cache the public key in each microservice. By having the public key cached in your microservice, you will be able to validate the requesting JWT inside the service that is being requested.
Then whenever a request comes into one of your microservices, the library you import will examine the requesting JWT, check its validity, and grant access/authorization if the token is valid. The beauty of using a private/public key pair and asymmetric key signing is that you can validate a token based on the public key alone, but not sign it. So as long as each service has the public key from your /cert endpoint, they can validate a token without ever needing to talk to the auth server or knowing the private key.
This will require a little more work up front, but will yield you massive amount of ease, flexibility, and peace of mind in the future knowing only one source knows your private key.
One common pattern here would be to use an API gateway as the entry point to your entire microservice architecture. Incoming requests for authentication would be routed to the appropriate microservice. If the credentials provided be correct, a new JWT would be returned to the gateway, which would then forward to the caller. For the actual microservice APIs which comprise your application, the gateway would check that the incoming JWT be valid before allowing the request to hit the microservice.
This answer leaves out a few things, for simplicity. For instance, often you would want to have an authorization microservice, which decides what a user is allowed to do. Also, implementing JWT can be involved. You might need a cache layer to keep track of whitelisted and/or blacklisted JWT.
Here is the solution I came up with, to handle user data we can implement an Identity Provider Service (IDP) which is responsible for signing JWTs with symmetrical keys (rs256) and storing user information. The Identity Provider also has an open endpoint which will expose the public key in the form of a JWK (JSON Web Key) which is used to sign the JWT, This endpoint can be used to validate issued keys by any other service (ideally the external service would cache the JWK to reduce traffic to the IDP).
But This also poses another issue, that is we will have to implement more code to validate the tokens with the JWK endpoint. This is where an API Gateway comes in, The API gateway sits between the frontend client and the API server acting as a checkpoint. The API Gateway caches the JWK using the IDP endpoint and validates all the incoming requests. This means we would only have to implement features like JWK validation, rate-limiting, and SSL only to the API Gateway and we will not have to rely on the internal services for implementing these. Plus another improvement to the API Gateway would be to write the decoded JWT data onto the headers so the API Gateway can pass the decoded data for example: x-jwt-email: person#email.com directly to the internal services.
I found inspiration for this implementation from various sources and this was one of the first system designs that have completed building so let me know if there are any loopholes or improvements that could be implemented.
The code for the above implementation can be found here:
Identity Provider
API Gateway

Why JWT is a stateless authentication?

I am trying to understand how JWT authentication is stateless. In stateful authentication, there will be a session id. Here there is a JWT token which is signed. So the authentication server issues the JWT token, but can I say the validation of the JWT token in subsequent requests are done by the endpoint server (application server) rather than the authentication server. I believe this is possible as JWT is signed with expiry date (and also some other information) and the public certificate of authentication server is available to all endpoint servers.
So the authentication server will be only responsible for issuing the tokens and not validation. The validation will be done by the endpoint server.
Is my understanding correct? Is this how JWT is made stateless? Otherwise, I don't see how it is different from a stateful authentication as both can be implemented using tokens.
In stateful authentication, the centralized server will be responsible for issuing the tokens as well as validation is each request.
JSON Web Tokens (JWT) are referred to as stateless because the authorizing server needs to maintain no state; the token itself is all that is needed to verify a token bearer's authorization.
JWTs are signed using a digital signature algorithm (e.g. RSA) which cannot be forged. Because of this, anyone that trusts the signer's certificate can safely trust that the JWT is authentic. There's no need for a server to consult the token-issuing server to confirm its authenticity.
Notice in this diagram that the Resource Server does not need to check back with the Authorization Server:
Source: https://jwt.io/introduction/
In stateless authentication there is no need to store user information in the session. We can easily use the same token for fetching a secure resource from a domain other than the one we are logged in to.
Refer : https://www.jbspeakr.cc/purpose-jwt-stateless-authentication/

Is API key a way of Authorization or Authentication?

I am using API keys with my web service. I share a key with the client and they send it with every request.
Is this Authorization or Authentication?
An API key is a method of authentication. Using them for security purposes is often frowned upon. You can read more about them here

Client authentication in microservices using JWT and OpenID Connect

I've some questions regarding authentication in a microservices architecture. I've right now a monolithic application and my goal is to split the application in small microservices.
My bigest problem is for authentication (for now). After reading a LOT a documentation, It seems that the best solution is to use OpenID Connect to authenticate an user to retrieve a JWT that can by passed with the request to the microservices.
Also, to avoid having multiple endpoints, you can deploy and API Gateway to have only one endpoint for the end user. Ok, so now I've two questions with this architecture.
The standard flow for authentication will be :
An user contact my identity server in OpenID Connect with the implicit flow and get the id_token (JWT) and also the access_token. The user can now contact my API with this access_token. The API Gateway will valide the access_token with the identity server and also retrieve the JWT to add it to the sub request to the microservice API.
1/ How the API Gateway can get the JWT from the access_token? From what I red from the documentation (http://openid.net/specs/openid-connect-core-1_0.html), It can contact the "/userinfo" endpoint but It will get just the JSON format not the JWT...
2/ I want to allow authenticated calls between my microservices. So each microservice needs to be able to generate a JWT to contact other microservices directly. My first thought was to contact the identity server. But with the OAuth2 Client Credentials flow, I don't retrieve a id_token or a JWT. Just a classic OAuth2 access token without JWT. My second thought was that the microservice can directly sign its own JWT with a certificate issued by the same PKI as the one used by the identity server. That mean that a JWT can be sign by several certificats but from the same private PKI. When a microservice receives a JWT, It needs to be able to identify witch certificat was used to sign the JWT. I don't find anything on the RFC regarding this problem. I can add my own private claim in the token to have the certificate but after several days of browsing the web without seeing this kind of solution, I'm wondering if I'm not on the wrong path... To sum up, how can i perfom "User to service" authentication AND alors "service to service" authentication in JWT?
Thank you very much!
I am implementing a similar solution. Not sure if it will address to your question completely, but, I hope it helps:
You can implement a new authentication micro-service to convert your oAuth2 access token to JWT token. This microservice will also sign this JWT token.
Your API gateway will route all client requests to authentication service, which will validate this token from IDM and will convert it to a signed JWT token.
API gateway will pass this JWT token to other microservices which will validate the signature from Authentication Service's public key. If the signature validates, roles can be extracted out of it for authorization.
Each microservice can have its own IDM credentials configured and when it wants to call any other microservice, it can generate an access token and call Authentication Service to get JWT which can be passed in call to other microservices.