We have few micro-services that are used by a UI. Azure B2C is our auth provider. Each micro-service(API) requires an access token and needs to talk to a database for authorization. This database has role based access permission.
This is how it looks today:
With this we have two problems:
As Azure B2C do not allow adding scopes from multiple resources into one access token, we have to get multiple access tokens.
We are now at a stage where the UI need to call two or more APIs to display the data on one page.
We wanted to use GraphQL as an API Gateway. Something like this:
All the micro-services are placed inside a private vnet and only GraphQL API is allowed to talk to them. GraphQL Layer handles all authentication and authorization.
Now the questions are:
Do you see any problems with this approach?
Is it okay to use a client and secret for communication between GraphQL layer and other API's? or Is there an provision in Azure B2C that can do this validation with out GraphQL layer requesting individual access tokens?
what are the additional advantages of adding Azure API Management to this (other than logging, analytics, rate limiting etc)? Do I need to worry about SSL termination?
Option 2 looks like a good architecture.
A common pattern is for the UI to call a dedicated 'entry point' API, which then orchestrates calls to microservices in a private network - as in your second diagram.
Eg an Online Sales UI calls only an Online Sales API
This also helps to keep UI specific requirements out of microservices and keep responsibilities clean.
In OAuth terms as you say there will be a single resource - the entry point API - and you should only need a single access token.
The entry point API's token (or its claims) can then be forwarded directly to Microservices and used to identify the user there if needed.
I'd avoid getting additional tokens for microservices and just enforce authorization based on roles from your user database.
In some cases it may also make sense to also enforce rules such as 'Online Sales API not allowed to call Payroll microservice'.
Personally I would develop entry point APIs using the same technology as microservices.
Related
I am going to build a web application that allows users to sign in with their Google or Twitter account. I think OpenID Connect(OAuth2) is the standard today to verify the identity.
I also want to provide several API services that can be only accessed with a valid access token from either Google or Twitter.
For example, all the four API's above are going to be public and so I have to protect from unauthorized users. For NodeJS based API services I can use http://www.passportjs.org/ to protect all APIs.
Assume, in the future the number of API's will be grow for example up to 20 API's and sign in with Facebook account will be also allowed.
Again, all the API's have to be protected and I have to do it 16 times with http://www.passportjs.org/.
In addition add the new provider Facebook, I have to do the changes on all 20 APIs.
The question is, is their a way to keep centralized, which means in the future when I will provide more the providers for example GITHUB for sign in I would like to do changes in one place not in 20 places.
Is the tool https://www.ory.sh/hydra what I need?
These are perhaps the two primary features of OAuth 2.0 and Open ID Connect:
Federated sign in to your UIs via multiple identity providers and the ability to easily add new options such as GitHub in a centralised manner
Full control over claims included in access tokens, so that your APIs can authorize requests however you'd like
FOREIGN ACCESS TOKENS
You should aim to avoid ever using these in your apps. Your UIs and APIs should only use tokens issued by your own Authorization Server (Ory Hydra), which manages the connection to the Identity Provider. Adding a new sign in method will then just involve centralised configuration changes, with zero code changes in either UIs or APIs.
IF YOU DON'T HAVE AN AUTHORIZATION SERVER YET
Maybe have a look at the Curity Identity Server and its free community edition - use sign in with GitHub, which has strong support for both of these areas:
Many Authenticators
Many Options for Issuing Claims
EXTERNAL RESOURCES
One exception to the above is that your APIs may occasionally need to access a user's Google resources after login, by calling Google APIs. This would require the token issued by Google. It can be managed via an embedded token approach - though it doesn't sounds like you need that right now.
I am new to Azure API Management and will be happy to receive suggestion and advise on my implementation.
I am developing a B2B Api Channel for 3rd parties to call my services via the API Management (APIM) Gateway. On the APIM developers portal I can onboard new clients and generate API key. My struggle is how best to figure out at the underlying services who is calling?
I have considered add the API Key generated in the APIM to a database which the underlying service will call to authenticate, however, the implementation will be manual and will not be in sync when the 3rd party client goes to APIM and regenerate a new API key.
What I want is a solution that auto syncs authorization and authentication between APIM and the underlying services.
Since API keys can be replaced, you better rely on IDs to identify clients.
You can pass a client ID to a backend in a header: https://stackoverflow.com/a/42277313/2579733
Now how do you correlate APIM's client IDs with your backend's client IDs?
If there are only a few clients, you can probably update that association in your backend's database manually. If you can use the clients's email to connect the APIM client and your backend client, that's even easier (you're done).
If you will need to register many clients and the manual approach is not feasible... One way to do it is with Delegated Authentication:
Delegation allows you to use your existing website for handling developer sign in/sign up and subscription to products, as opposed to using the built-in functionality in the developer portal. It enables your website to own the user data and perform the validation of these steps in a custom way.
I never used it but it seems you can transfer the responsibility of creating new clients to a backend service (developed by you).
This way you have access to client emails, you generate IDs and can store the ID relationship in the backend as necessary.
I am fairly new to the concept of microservices and api gateways in general. I am trying to understand the role that an api gateway plays in a modern web application using many microservices. I have been reading the documentation and tutorials of express-gateway but am a bit confused on how a web application would perform authentication with an api gateway set up like express-gateway.
My web app would have multiple microservices that it would talk to. I thought that putting an API gateway in front of all my microservices would make it so that each microservice would not need to worry about whether a user/request is authenticated or not, because if the microservice was being talked to it meant that the api gateway had verified the request was a valid user. Is my understanding of this correct?
Assuming that my thought of the api gateway serving as a gatekeeper to other microservices is correct, my follow up question is with the specifics of how it is performed.
Does this mean that all user creation and authentication is performed by the api gateway? Meaning that I would have no custom user creation/login microservices? Or would I have a publically reachable through the api gateway custom user creation microservice which upon creation would itself create the user accounts within the api gateway? Is user information now duplicated by my microservice in a database somewhere and the express-gateway's own storage? I guess my general confusion is around does an api gateway take the role of authentication/user creation entirely away from a web app's own microservices, or do you still need both parts?
I thought that my own authentication microservice would first validate a user then work with the api gateway to generate a valid short lived token, but reading about creating user or app accounts for authentication in express-gateway has made me confused on the roles each play.
to have an overview of the role of an API Gateway in a microservice based solution, I suggest you to have a look to this presentation I did couple of months ago. That should clarify the things a little bit.
Is my understanding of this correct?
Yes, you got it. If you have a look to the video, you can actually see that concept in practice as well.
For the storage, that kind of depends.
Express Gateway offers a subset of identity services such as users, applications and credentials. They're good enough for most application usages but you might find yourself with the needs of using an external service, such as Auth0.
Now, features aside — where you store the data, it's up to you. You can keep some of the data in Express Gateway and some of it in your own database — or entirely in Express Gateway. There's not a good or bad strategy here.
I'm reading a tutorial provided by AWS explaining how to break up a monolithic NodeJS application into a microservice architectured one.
Here is a link to it.
One important piece is missing from the simple application example they've provided and that is user authentication.
My question is, where does authentication fit into all this?
How do you allow users to authenticate to all these services separately?
I am specifically looking for an answer that does not involve AWS Cogntio. I would like to have my own service perform user authentication/management.
First, there is more than one approach for this common problem.
Here is one popular take:
Divide your world to authentication (you are who you say you are) and authorization (you are permitted to do this action).
As a policy, every service decides on authorization by itself. Leave the authentication to a single point in the system - the authentication gateway - usually combined inside the API gateway.
This gateway forwards requests from clients to the services, after authenticating, with a trusted payload stating that the requester is indeed who they say they are. Its then up to the service to decide whether the request is allowed.
An implementation can be done using several methods. A JWT is one such method.
The authenticator creates a JWT after receiving correct credentials, and the client uses this JWT in every request to each service.
If you want to write your own auth, it can be a service like the others. Part of it would be a small client middleware that you run at all other service endpoints which require protection (golang example for middleware).
An alternative to a middleware is to run a dedicated API Gateway that queries the auth service before relaying the requests to the actual services. AWS also has a solution for those and you can write custom authentication handlers that will call your own auth service.
It is important to centralize the authentication, even for a microservices approach for a single product. So I'm assuming you will be looking at having an Identity Service(Authentication Service) which will handle the authentication and issue a token. The other microservices will be acting as the service providers which will validate the token issued.
Note: In standards like OpenID connect, the id_token issued is in the format of JWT which is also stateless and self-contained with singed information about the user. So individual Microservices doesn't have to communicate with the authentication service for each token validation. However, you can look at implementing or using Refresh tokens to renew tokens without requiring users to login again.
Depending on the technology you choose, it will change the nature how you issue the tokens and validate.
e.g:
ExpressJS framework for backend - You can verify the tokens and routes in a Node Middleware Handler using Passport.
If you use API Gateway in front of your Microservice endpoints you can use a Custom Authorizer Lambda to verify the tokens.
However, it is recommended to use a standard protocol like OpenID connect so that you can be compatible with Identity Federation, SSO behaviors in future.
Since you have mentioned that you are hoping to have your own solution, it will come also with some challenges to address,
Password Policies
Supporting standards (OpenID Connect)
Security (Encryption at rest and transit especially for PIDs)
SSO, MFA & Federation support etc.
IDS/IPS
In addition to non-functional requirements like scalability, reliability, performance. Although these requirements might not arise in the beginning, I have seen many come down the line, when products get matured, especially for compliance.
That's why most people encourage to use an identity server or service like Cognito, Auth0 & etc to get a better ROI.
I need to implement an application where I am going to use an Authorization Server generating a JWT token. These token will include the roles a user is granted to then authorize the user access to different resources. There will also be a gateway where this security will be added.
My question is regarding the user roles and the security between internal microservices.
When the user is created, he should be granted a set of roles and he may be granted different ones at a later point or maybe new roles will be added later. All this information should be stored in the Authorization Server. But how is this information replicated to other microservices? If I use a framework like Spring Security to secure my endpoints, where I add the roles needed for the different URLs, do I need to hardcode the user roles into my security configuration in the downstream microservices or is there any other way to find them from the Authorization Server?
The architecture is going to use an API gateway in a public network that then communicates with a service discovery in an internal one to find the different microservices. These also find each other through the service discovery. I use Zuul for routing. In this situation, do I need to also secure the communication within the internal network? I understand that to use Spring Security for authorization I would need to pass the JWT token anyway to get the user roles. But would it be necessary otherwise? Would it be enough to use HTTPS from the client to the gateway and unsafe HTTP within the private network?
There are many options here.
One of these is that you may use spring-security-oauth2 in combination with spring security. In this setup you will distinguish two kind of applications:
Authorization service (AS) - this service issues and verifies access tokens for authenticating clients (e.g. using password grants or authorization codes);
Resource service (RS) - it exposes a REST API for CRUD operations on resources, for example. The endpoints are protected. The RS communicates with the AS in order to grant access;
In a resource server you will use and configure the Spring Security as you would normally do in a stand alone application. Below is one very simple example.
Here is the code in a REST controller with protected endpoints:
#PreAuthorize("hasRole('READ_BOOK')")
#GetMapping(value = "/books/{id}")
public ResponseEntity<Book> getBook(#PathVariable("id") String id) {
...
//retrieves book details if you have role READ_BOOK
}
#PreAuthorize("hasRole('WRITE_BOOK')")
#PostMapping(value = "/books")
public Book createBook(#RequestParam("title") String title) {
...
//creates a book if you have role WRITE_BOOK
}
The security configuration will look just as if you are writing a monolithic application with the exception that:
you will add an #EnableResourceServer annotation on your configurations;
you will configure an instance of RemoteTokenServices - the task of this service is to verify the provided tokens against the authorization server and fetch user roles;
The AS will issue access tokens based on some OAuth2 workflow. These tokens will be used by the client to access the protected endpoints.
I've made a small PoC (proof of concept) setup in which I created two simple apps showing the whole thing in action. Please find it here and feel free to submit questions, proposals and PRs. The complete source code is included bundled with more explanations.
Please note though that this setup in certain cases may cause too much inter-service communication. I have seen a more complicated setup in which the API gateway acts as a resource server and if the user has enough credentials it enriches the request with the necessary details and passes the request to downstream services which basically trust the gateway.