Should the server to server authentication include User on which behalf the request is made? - security

I am going to implement security (using Identity Server 4). I have mobile application (front end) and few microservices (back end).
General scenario is that User_John calls Service_A_API using User-JWT token (obtained with Device flow). In order for Service_A to complete request, it has to access some data from Service_B. Service_A is calling Service_B using Server2Server-JWT token (obtained with Client credentials flow).
Server2Server-JWT is "Full access" token, allowing Service_A to do operations on any user on Service_B (e.g. it can delete user's order, update user's money balance, etc.)
Concerns that I have:
Is it correct to assume that Server2Server-JWT can have some long lifetime (e.g. 10-20 minutes) and it can be used for many requests originated from many different users?
Assuming Service_A and B are hosted in AWS (Dockers), is the Server2Server-JWT secure in those service's memory? What if (and how) the Server2Server-JWT get stolen?
Should Service_A request new Server2Server-JWT token for every user to call Service_B (and e.g. store this UserId in Claims)? Or is it safe to assume that Server2Server-JWT is safe in memory, and can be reused for any user request within the lifetime span of the full access Server2Server-JWT token?
Is Hybrid flow an answer to create a Server-to-server token on behalf of a user? Or is it something else?
My source of info are:
http://docs.identityserver.io/en/latest/topics/grant_types.html
https://www.pluralsight.com/courses/asp-dotnet-core-oauth2-openid-connect-securing

I definitely can answer the last question and only try with the rest.
Hybrid is a kind of interactive flow where one app has both client and server parts. Interactive means that a user goes through the IdP's portal to get authenticated.
Mobile apps usually run Authorization Code authorization flow with PKCE extension which all together behave pretty similar to hybrid where the "client" is a mobile browser and the "server" is the app itself.
No place for an API. But... you can look into the Extension Grant docs. Allows to implement Service Credentials on behalf of a user, exactly what you want, but... probably you don't need that with AWS.
They offer Network firewalls built into Amazon VPC, and web application firewall capabilities in AWS WAF to create private networks, and control access to your instances and applications. Together with "Customer-controlled encryption in transit with TLS across all services" that might be more than enough. The decision is yours.

Related

Method for site wide authentication?

I am currently looking for a method to provide site wide authentication, for services exposed to the cloud, on the site I am responsible for. Some services are a Python based, some in PHP and some in Perl. Individual services would need to be able to get access to the user profile and the associated roles.
On the main page users are logged in and a cookie is created using a JWT token. The main site is using NodeJS for the auth system and is built in-house.
At this point I am wondering whether we should use OAuth2 across the site or whether there is another approach that may be simpler, where we don’t need to deal with inter domain requirements?
The approach you're currently investigating is the re-use of a JWT as an authentication token across multiple services. Although it's technically possible - it is not the ideal secure approach.
The most secure approach is for separation of application contexts, whereby each application should be tied to a different application credential (in OAuth2 terms). This is ensures that the user receives a credential unique to that application, allows the credentials to be managed/revoked separately and audited in isolation.
To implement this smoothly for UI flows requires an identity provider that supports SSO, and also assumes that each UI application can handle negotiation to the IDP to access that SSO session.
For interactions that are system to system authenticated, eg. Python, you would need to use system to system authentication (OAuth2 client credentials) that again have its own credential. In the case where you need access to the end-user's profile, a management api key (or similar) would be required.

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.

Single Sign-On in Microservice Architecture

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.

Hiding oauth secrets

I'm building an (amateur) application that uses the Twitter API, which supports authentication via the OAuth protocol.
Part of the OAuth sign-in process involves each application being assigned a Consumer Key and Consumer Secret (both strings), which are used to generate signatures for communication with the Twitter server.
The Twitter dev guide explicitly states that one should 'Keep the "Consumer secret" a secret. This key should never be human-readable in your application.'. This is obviously important, as if a malicious individual obtains your credentials, they can impersonate your app.
However, I do not see how this can be achieved. In order for the application to use the string, it must be accessible to the app somehow (either directly coded into the app, stored in a bundled database, or accessible via a linked web service) - and if it's accessible to the app, it must be accessible to the user. It can be obfuscated by splitting, character-shifting, etc., but not (as far as I can see) in any way that can't be undone.
This SO answer confirms my suspicions that this is a problem - I was wondering if there had been any progress since it was posted in December '09?
The problem with mobile devices is that is in the users hands. And with enough time/effort the user can pull any data out of the device. It isn't an OAuth security problem, it is an overall security problem that there really isn't an answer for.

Resources