Single Sign-On in Microservice Architecture - security

I'm trying to design a green-field project that will have several services (serving data) and web-applications (serving HTML). I've read about microservices and they look like good fit.
The problem I still have is how to implement SSO. I want the user to authenticate once and have access to all the different services and applications.
I can think of several approaches:
Add Identity service and application. Any service that has protected resources will talk to the Identity service to make sure the credentials it has are valid. If they are not it will redirect the user for authentication.
Use a web-standard such as OpenID and have each service handle it own identities. This means the user will have to authorize individually each service/application but after that it will be SSO.
I'll be happy to hear other ideas. If a specific PaaS (such as Heroku) has a proprietary solution that would also be acceptable.

While implementing a microservice architecture at my previous job we decided the best approach was in alignment with #1, Add identity service and authorize service access through it. In our case this was done with tokens. If a request came with an authorization token then we could verify that token with the identity service if it was the first call in the user's session with the service. Once the token had been validated then it was saved in the session so subsequent calls in the user's session did not have to make the additional call. You can also create a scheduled job if tokens need to be refreshed in that session.
In this situation we were authenticating with an OAuth 2.0 endpoint and the token was added to the HTTP header for calls to our domain. All of the services were routed from that domain so we could get the token from the HTTP header. Since we were all part of the same application ecosystem, the initial OAuth 2.0 authorization would list the application services that the user would be giving permission to for their account.
An addition to this approach was that the identity service would provide the proxy client library which would be added to the HTTP request filter chain and handle the authorization process to the service. The service would be configured to consume the proxy client library from the identity service. Since we were using Dropwizard this proxy would become a Dropwizard Module bootstrapping the filter into the running service process. This allowed for updates to the identity service that also had a complimentary client side update to be easily consumed by dependent services as long as the interface did not change significantly.
Our deployment architecture was spread across AWS Virtual Private Cloud (VPC) and our own company's data centers. The OAuth 2.0 authentication service was located in the company's data center while all of our application services were deployed to AWS VPC.
I hope the approach we took is helpful to your decision. Let me know if you have any other questions.

Chris Sterling explained standard authentication practice above and it makes absolute sense. I just want to put another thought here for some practical reasons.
We implemented authentication services and multiple other micro services relying on auth server in order to authorize resources. At some point we ran in to performance issues due to too many round trips to authentication server, we also had scalability issues for auth server as number of micro services increased. We changed the architecture little bit to avoid too many round trips.
Auth server will be contacted only once with credentials and it will generate the token based on a private key. Corresponding public key will be installed in each client (micro service server) which will be able to validate the authentication key with out contacting auth server. Key contain time generated and a client utility installed in micro service will validity as well. Even though it was not standard implementation we have pretty good success with this model especially when all the micro services are internally hosted.

Related

How to authenticate api calls in Kubernetes

I am planning on building a K8s cluster with many microservices (each running in pods with services ensuring communication). I'm trying to understand how to ensure communication between these microservices is secure. By communication, I mean HTTP calls between microservice A and microservice B's API.
Usually, I would implement an OAuth flow, where an auth server would receive some credentials as input and return a JWT. And then the client could use this JWT in any subsequent call.
I expected K8s to have some built-in authentication server that could generate tokens (like a JWT) but I can't seem to find one.
K8s does have authentication for its API server, but that only seems to authenticate calls that perform Kubernetes specific actions such as scaling a pod or getting secrets etc.
However, there is no mention of simply authenticating HTTP calls (GET POST etc).
Should I just create my own authentication server and make it accessible via a service or is there a simple and clean way of authenticating API calls automatically in Kubernetes?
Not sure how to answer this vast question, however, i will try my best.
There are multiple solutions that you could apply but again there is nothing in K8s for auth you can use.
Either you have to set up the third-party OAuth server or IAM server etc, or you write and create your own microservice.
There are different areas which you cannot merge,
For service interconnection service A to service B it would be best to use the service mesh like Istio and LinkerD which provide the mutual TLS support for security and are easy to set up also.
So the connection between services will be HTTPS and secured but it's on you to manage it and set it up.
If you just run plain traffic inside your backend you can follow the same method that you described.
Passing plain HTTP with jwt payload or so in backend services.
Keycloak is also a good idea to use the OAuth server, i would also recommend checking out Oauth2-proxy
Listing down few article also that might be helpful
https://medium.com/codex/api-authentication-using-istio-ingress-gateway-oauth2-proxy-and-keycloak-a980c996c259
My Own article on Keycloak with Kong API gateway on Kubernetes
https://faun.pub/securing-the-application-with-kong-keycloak-101-e25e0ae9ec56
GitHub files for POC : https://github.com/harsh4870/POC-Securing-the--application-with-Kong-Keycloak
Keycloak deployment on K8s : https://github.com/harsh4870/Keycloack-postgres-kubernetes-deployment

Authenticating end users in a first-party native app

We are in the process of developing a mobile (native) app, and are looking at how we should do user authentication. Most of the information I have found have been about web apps and / or third-party apps accessing public APIs. OAuth 2 is therefore recommended to be used most of the time.
Since we develop the app and our API isn't public, it seems like the Resource Owner Password Credentials OAuth 2 flow could be an option, but according to oauth.net that is not recommended any more.
We are using Google App Engine (with Node.js) and Cloud Endpoints (Not sure if end-points would be needed since it's a private API, but that is another question) as the back-end, and both Firebase Auth and Auth0 has built in support in Endpoints. However, we have some special requirements that doesn't make those services suitable (Swedish BankID for example).
What other options are there when authenticating users? Could we write an app in App Engine to check the users credentials against our database, and then send back a JWT (Cloud Endpoints supports custom authentication methods as long as they use JWT)? Would it be safe to do this ourselves? I have found some Node.js libraries for authentication, but most seem to be aimed at web apps. Are there any that are suited for a native app front end?
For authentication, yes, you can perform the check yourselves, in your database and deliver or not a JWT according with the authentication result.
However, and it's obvious, this authentication service must be public (because it's for authenticated unauthenticated users!). And thus, you can be expose to attacks on this service. And because it's the authentication service, if the service goes down, no one can no longer sign in, or worse, if you have a security breach, your user database can be stolen.
That's why, to use existing services, with all the protections, all the resources (people, monitoring, automatic response, high availability,...) deployed to managed a large number of threats. Firebase auth, Auth0, Okta (...) are suitable providers but I don't know your Swedish requirement and you might not avoid specific developments

How to handle user authentication with microservices in AWS?

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.

How can I replicate user roles from an Authorization Server to downstream microservices?

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.

Azure AD Login/logout implementation for Spring cloud microservices

I want to implement login and logout functionality and retrive user details like username and user role using Azure Active Directory.
We are using Docker to deploy Spring cloud microservices project on Azure cloud. Could you please suggest me steps to get user details?
Do we need to secure all microservices edge points using Spring cloud OAuth2 security using JWT or just we can secure one web microservice ? Do I need any permission ,specific user roles to implement this?
You can find Azure's documentation about OAuth 2.0 support for AAD here
https://learn.microsoft.com/en-us/azure/active-directory/active-directory-protocols-oauth-code
I've got an application that's using OAuth 2.0 with a different Authentication Server, and I'm about to see if I can use AAD as the Authentication Server. But, whatever ends up being your Auth Server, the rest of the application should be the same...
The Auth Server handles the log in (typically as a Single-Sign On pattern)
The Auth Server will return a Json Web Token (at some point, depending on the Grant Type being used to retrieve it)
The JWT should be included in each subsequent request to ensure the caller has authorization
From a Spring perspective, you'll need at least a SSO Client (denoted by the #EnableOAuthSSO annotation). If everything in hosted by that process, you'll need that JWT to call subsequent methods. If you have processes hosted in other processes, it's likely you'll want them secured as well. Using the #EnableResourceServer annotation will configure Spring Security to look for the JWT, just not attempt to retrieve one if the request does not have it.
Unless the endpoint is meant to be publicly accessible, you will want to secure it. Of course, I really don't know the context of your application, so this statement is purely an uninformed opinion based on zero knowledge of what you're trying to do with your application. Take it for what it's worth.
EDIT
This has become a little more complex than I originally thought. I have been able to write some code to dynamically retrieve the public key from Microsoft in order to validate the returned JWT.
But, the main issue is the fact the Azure AD supports Open Id Connect when acting as an Identity/Authentication Server. And, at the moment, spring-security-oauth2 doesn't support Open Id Connect.
I was able to make some small changes to the spring code, but I did ask the question to the Spring group and they are actively working on adding support for Open Id Connect. They hope to have a release two months (ish?).
For the short term, the oauth2 support doesn't support Open Id Connect. Given this is the protocol used by AAD, the current version of oauth2 won't work with AAD. That said, I will be happy to wait for the official support which shouldn't be too long.

Resources