I have an API that doesn't have an authentication (intentionally). How can I secure it so only my application can make requests and API can identify those API requests coming from that server only?
Well, you need authentication 🤷
In order to verify who is calling your API you need to authenticate them. This doesn't mean that you have to authenticate users. Applications can also authenticate and present their identity to other applications. This is what you need here. You can achieve such app-to-app authentication in a few different ways:
Basic authentication. You can save an ID and a secret in your application and use them to send the Authentication header.
Use OAuth's client credentials flow. This is an OAuth flow that is made specifically for apps to identify themselves to other apps.
Use mutual TLS. You can tell your API what certificate will your application use and accept only connections with that certificate.
Identify with JWT Assertions. In this approach, your application signs a JWT with its ID and the API is able to verify the signature of the 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.
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
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.
Can someone guide me on the best practice for this situation;
I have a REST service which developers can access with an API KEY. (I have this working in the WCF WEB API), so this part is done.
I would like developers to be able to validate a USER. i.e. use REST to check the username and password entered by a user.
Each of the end point methods only needs API KEY authentication, rather than basic authentication on the method call (if you see what I mean).
How should I best implement this?
Phil.
To securely send password data to a RESTful service you will need to secure communications across http. There are loads of ways to do this, see this post here:
How to secure RESTful web services?