Use JWT to authenticate separate API Microservice - express

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

Related

Is it ok to send the Client Secret as nonce?

I am building an SPA that connects to my Backend API and I have to integrate Azure AD Login, I am slightly confused about the entire authorization flow. I am trying to be as secure as possible. I will explain the flow below:
I build the url in the backend (containing the tenant id and other info), which is returned to the SPA to be added on a button.
The user clicks the button, is redirected to the Microsoft/Company authentication page.
If the authentication is successful, the user is redirected back to the SPA together with the ID Token.
The SPA takes the ID Token and sends it as a Bearer Token on each request to the API.
The API checks the signature and then validates some of the JWT tokens claims (such as the aud, iss, exp etc).
I have read about the state and nonce parameters, which are sent initially to Azure as a way to increase security, but I am confused between the role of the two.
I want to set the nonce as the client secret, and then verify the claim when it comes back inside the ID Token (step 5).
Is the right way to do it? From what I've read you other use the JWT signature verification & validation OR the Client ID / Client Secret technique, but why can't I use both as in my example when the nonce is the secret.
Secondly, if I use the nonce for this, what should I used the state parameter for? Should I build the state as a random string created by the SPA (so the frontend).
UPDATE: Upon further reading, I realized that you CANNOT use the Client Secret as the nonce, because the entire idea of the nonce is to be unique each and every time. A nonce is in fact a word created and used just one time, after which it is discarded. Seeing as the Client Secret is always the same, it wouldn't mitigate "replay attacks".
I'll keep this post as I still have the following questions:
Is nonce used for the API/Backend to check and state is used by the Client/Browser (e.g. frontend)?
What should I do with the Client Secret? It seems to be useless now. Should I add it as an encrypted custom claim?
FINAL UPDATE:
Besides the accepted answer, please read about Implicit Flow, Auth Code Flow, ID Tokens and Access tokens and the difference between them to understand.
1. Don't implement the protocol, use a library
The best (and easiest) way to implement this securely is to not implement it yourself. Instead, use a trustworthy and well-maintained client library which implements the protocol, leaving you free to focus on the value your app is bringing, rather than on the details of the protocol.
In your case, I would recommend using the Microsoft Authentication Library for JavaScript (MSAL.js). The quickstart for MSAL.js is a good place to start.
2. For SPAs, use the Authorization Code Flow with PKCE
You're trying to implement the Implicit Grant flow from a JavaScript application. Instead, you should switch to using the Authorization Code flow (with PKCE). To do this correctly, you will need to deal with a "code verifier" and a "code challenge" and do some hashing. Instead, you should just use a library (see #1, above).
The latest version of MSAL.js implements the Authorization Code Grant flow with PKCE, and you don't have to deal with this at all.
3. No, do not use the client secret as the nonce.
(Edit was just added, so I won't go into the details of why not.)
Is nonce used for the API/Backend to check and state is used by the Client/Browser (e.g. frontend)?
No, both are used by the client (in your case, the JavaScript app). (In many/most cases, the single-page JavaScript app doesn't send the ID token to its backend, it sends the access token (which will not contain the nonce), so the backend never sees the state or the nonce.)
What should I do with the Client Secret? It seems to be useless now. Should I add it as an encrypted custom claim?
No, don't do that.
For starters, no part of your JavaScript app should have any long-term secret in it (such as the client secret). Remember that anybody who can load the app can look at the code for your app, and see all the traffic between your app and any backend server it calls. If this communication includes a secret, then any user of your app can see that secret.
If you have no use for your client secret, then you just don't need a client secret. For a public client application (which is what you seem to be building), it is normal that you don't need a client secret.

How API gateway validates access token via introspection

I found one interesting article that has this illustration:
It says that:
API Gateway verifies access token for all incoming requests via introspection
But what does this mean?
it says that gateway goes to authorization server and validates token (JWT).
why is that needed?
if gateway has authorization server's public key, it can check token validity using signature just like every backend service, why is introspection needed and how is it done?
Depending on your Identity provider it can be done either way but there are trade offs.
If you validate the token locally then yes it can use public keys to do that and that's very efficient way, however downside is that if the token or signing keys are revoked then your token is still valid. With Remote check you have to bear the http overhead but that is more reliable.
Normally tokens are kept short lived and validated locally. But if your access token are long lived, your application require strict access controls or library doesn't support local validation then it's a good idea to check them remotely
I believe you are looking at this document.
What I understood from this Secure API Gateway is that the gateway is responsible for introspection and the back-end services will only check the token signature, which is less secure than introspection, but still a layer of security.
Introspection is necessary to validate the token information against the Authorization Server.
This is more secure, because the system can ensure that the token received is not malicious, expired and it is from an known source.
The details on how it is done are explained in RFC 7662.
Yes, the gateway could validate the token signature if it has access to the certificate.
I can't really tell why they choose the back-end server to do it, probably a project decision.
API Gateway primarily meant for routing the incoming calls to the corresponding MicroService Clusters.
In addition to that,it can also play a role to validate the token, so that only valid traffic is routed to the downstream servers (filtering malicious traffic).
The level of validation could be up to the product owner/architect decision. It could be as simple as validating against the list of in memory cached token or in depth validation on set of claims, digital signature verification, expiry time, audience claim etc.
You can view the set of claims inside the token using JWT decoder like https://devtoolzone.com/decoder/jwt

Is there a thing like asymmetric authorization in web?

I have a private API, that I want 3rd party clients to authorize without sending sensitive information to the client, like a password. The usual flow in this case is:
We give a secret one time token to a client
Upon activating this token (e.g. calling api with this token)he's able to create an account by providing a password.
Client authorizes with this password and receives a secret token
This secret token is used with every api call.
The issue with this flow is when we're sending him one time token. If someone uses it first, he receives all the data he wanted.
Atm asymmetric encryption is used everywhere, https (ssl) is based on it. I wonder if there's such thing as asymmetric authentification. As I see this flow is:
A client and a server generates 2 magic tokens client_private_token, client_secret_token, server_public_token, server_secret_token.
We save opponents public tokens for example in settings files on both sides.
The server responds with server_public_token
The client uses client_private_token to generate some session_token and send it with every request that requires authorization
The server uses its server_private_token and user_public_token to verify that this session_token is valid.
The flow is very similar to ssl, but instead of encrypting data we just generate magic strings that proof that it's we.
Please don't confuse it with JWT, as JWT is just a payload with some information and server signature with it. To create a JWT user needs to be authorized in the first.
Also if there are such things it would be great to have clients to modern languages like java, js, python etc

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

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.

How do I use API keys, and token schemes effectively to secure REST API?

I know this question has been asked a lot of times in varying shapes and forms, but I'm still quite unclear about a few things. It's confusing how resources about this topic around the Web refer to "user" without clear context. API keys are issued for users, and so are access tokens, but I don't think API key users, are the same as access token users.
Do you need to have different API keys for different instances of end user clients? For example if I build a mobile app for a third party API, does each instance keep their own API key? I don't think they do, but how do I tie API keys, and access tokens together to say that a certain request comes from this particular instance of an app authorized by a known user? If I were the auth provider, do I have to keep track of each of those?
API keys, and access tokens are usually represented by a pair of public, and shared keys. As a service provider (server side), which one do I use to verify the message I receive, the API key, or the access token? If I understand correctly, the idea is that each request should come with a signature derived from the secret part of the API key so that the server can check that it comes from a trusted client. Now what use do I have for access token secret? I know the access token is used to verify that a system user has authorized the app to carry operations on their behalf, but which part of the message does the access token secret be useful for?
Is a hash generated from a (secured) random number, and a time stamp salt a good API key generation strategy?
Are there (preferably open source, Java-based) frameworks that do most of these?
Let me try to answer as many of your queries as I can.
Apikey vs Access Token usage
First of all, apikeys are not used per user. Apikeys are assigned per
application (of a developer). A developer of a service signs up their application and obtains a
pair of keys.
On the other hand access tokens are issued for each
end-user in context of the usage (exception is Client Credential
grant).
Service providers can identify the application from the
apikey in use.
Service providers can identify the end-users using
access token attributes.
You should have any end-user APIs, that is an API that has end-user resources (data or context) associated, protected by 3 legged Oauth. So access token should be necessary for accessing those resources.
Developer-only resources can be protected by apikey or two-legged Oauth. Here I am referring to Oauth2 standards.
Oauth1 is preferred when there is no HTTPS is supported. This way the shared secret is not sent over unprotected channel. Instead it is used to generate a signature. I strongly suggest Oauth2 over HTTPs and avoid Oauth1 for ease of use. You and your API consumers would find Oauth2 to be much more simpler to implement and work with. Unless you have a specific reason to use Oauth v1
As a service provider you can use Apigee's Edge platform that provides Oauth 1 and 2. It is not opensource. However you can use it for free, until you need some high TPS or higher SLAs.