We have a service that sends delivery notification messages to a client via HTTP requests - meaning, the client must also act as a Server (must expose an HTTP endpoint) in order to receive these notifications.
Some of our clients are asking that our requests authenticate against their endpoints via OAuth. We would prefer to implement this using a third-party so as to avoid having security features implemented in-house (and avoid security issues/not well-handled edge cases that we could end up introducing); More specifically, we'd prefer to have a reverse-proxy.
The idea would be that our service would send a request to the client through the reverse proxy, which would identify that the request is missing a token and would be responsible for getting a token and injecting it into the request.
I googled for this but couldn't find anything; perhaps I'm not searching for the correct keywords. Is there a packaged/"market" reverse-proxy solution for this? Or perhaps a programmable reverse-proxy that could bootstrap a solution for us?
I can see two approaches for this:
have an oauth2 client library in your own code to handle the oauth2 authentication flow for your app. Most programming languages have an oauth2 client so you wouldn't re-implement anything and have a secure authentication mechanism,
use a proxy that implements an oauth2 client so it would do that part of the flow for your service but I'm not sure it exists. I couldn't find anything also related to this because of the fact that most of the languages have an oauth2 client that's readily available.
I hope you find the solution to your problem :)
Related
I’m developing my own OAuth2 + OpenID Connect implementation. I am a bit confused about how to handle OAuth flows for native (specifically, Mobile) clients. So far, I am seeing that I need to use an Authentication Code Flow. However, based on my research, there are some details that seem to contradict each other(at least based on my current understanding).
First, standard practice seems to say that mobile apps are not inherently private and, as such, standard flows that make use of a back channel should not be used. As a work around, the PKCE extension can be used (and utilize the built-in device browser as opposed to a web view so the tokens and sensitive information are less likely to be leaked).
However, under the Protocol’s Dynamic Client Registration specification, it is also mentioned that mobile apps should use this method of client registration to get a valid client ID and client secret... But, why would we do this when in an earlier section it was established that mobile applications were indeed public clients and couldn’t be trusted with confidential information like a client secret (which we are getting by using this DCR mechanism...
So, what am I not understanding? These two things seem to contradict one another. One claims mobile apps are public shouldn’t be trusted with a secret. Yet, in the recommended DCR mechanism, we assign them the secret we just established they can’t be trusted with.
Thanks.
A bit late, but hope it helps. So part of the OAuth2.0 protocol is two components, the client_id, and client secret. The client and server must agree on those two values outside the protocol i.e. before the protocol start. Usually, the process is as follows. The client communicates with the Authorization Server using an out-of-bound communication channel to get these values and be registered at the server. There is two way this client registration can happen, statically and dynamically. Statically mean the client_id and secret do change, i.e. the client gets them once when he registers with the server. Dynamic client registration refers to the process of registering a client_id every time the client wants to use to protocol, i.e. a client secret will be generated for him every time (also by an outbound communication).
Now, Why use dynamic registration?
Dynamic client registration is better at managing clients across replicated authorization servers., The original OAuth use cases revolved around single-location APIs, such as those from companies providing web services. These APIs require specialized clients to talk to them, and those clients will need to talk to only a single API provider. In these cases, it doesn’t seem unreasonable to expect client developers to put in the effort to register their client with the API, because there’s only one provider.
Does Dynamic Client registration offer any security advantages?
No, both are vulnerable if used with a JavaScript or a Native Mobile Client (JavaScript client can be inspected, and Mobile apps can be decompiled). Hence, both of them require PKCE as an extra layer of security.
This is just a general question about microservice architecture. Why do 2 or more internal services still need token auth like oauth2 to communicate with each other if the outside world doesn't have access to them? Couldn't their apis just filter internal IP addresses instead? What are the risks with that approach?
Why do 2 or more internal services still need token auth like oauth2 to communicate with each other if the outside world doesn't have access to them?
You don't need OAuth2 or token authentication, but you should use it. It depends on how much you trust your traffic. Now in the "cloud age" it is common to not own your own datacenters, so there is another part that own your server and network hardware. That part may do a misconfiguration, e.g. traffic from another customer is routed to your server. Or maybe you setup your own infrastructure and do a misconfiguration so that traffic from your test environment is unintendently routed to your production service. There is new practices to handle this new landscape and it is described in Google BeyondCorp and Zero Trust Networks.
Essentially, you should not trust the network traffic. Use authentication (e.g. OAuth2, OpenID Connect, JWT) on all requests, and encrypt all traffic with TLS or mTLS.
Couldn't their apis just filter internal IP addresses instead? What are the risks with that approach?
See above, maybe you should not trust the internal traffic either.
In addition, it is now common that your end-users is authenticated using OpenID Connect (OAuth2 based authentication) - JWT-tokens sent in the Authorization: Bearer header. Most of your system will operate in a user context when handling the request, that is located within the JWT-token, and it is easy to pass that token in requests to all services that are involved in the operation requested by the user.
For internal services it's usually less about verifying the token (which in theory was already done by the external-facing gateway/api), and more about passing through the identifying information on the user. It's very common for even internal services to want to know who the requesting/acting user is for permissions and access control, and sometimes it's just easier to tell every service creator who needs user-scoping to accept a JWT in the Authorization header than it is to say, "look for the user ID in the X-COMPANY-USER-ID header".
You can implement very granular role based access control(RBAC) on the apis exposed by Microservices using Oauth which you can not do using filtering IP address.
I'm creating an online store REST API that will mainly be used by a mobile app. The plan is for a microservices architecture using the Spring Cloud framework and Spring Cloud OAuth for security.
My question is really on best practices for communication between microservices: Should I have each service register for their own token, or should they just pass the user's token around?
For example, I have 3 services: user-service, account-service, order-service.
I've been able to implement two procedures for creating an order: One passes the user's token around, and in the other each service gets their own token. I use Feign for both approaches.
So for option 1: order-service -> GET account-service/account/current
order-service calls the account-service which returns the account based on a userId in the token. Then the order-service creates an order for the account.
Or for option 2: order-service -> GET account-service/account/user-id/{userId}
order-service gets the userId from the sent token, calls the account-service with it's own token, then creates the order with the retrieved account.
I'm really not sure which option is best to use. One better separates information but then requires two Feign Clients. However the other doesn't require the 2 clients and it becomes easier to block off end certain endpoints to outside clients, however it requires extra endpoints to be created and almost every service to go digging into the Authentication object.
What are all your thoughts? Has anyone implemented their system in one way or another way entirely? Or perhaps I've got the completely wrong idea.
Any help is appreciated.
I have found below 3 options:
If each microservice is verifying the token then we can pass the same token. But the problem is - in between same token can be expired.
If we use client_credentials grant then there we are having two issues: one is, we need to send the username/id in next microservice. Another one is, we need to request two times - first for getting the access token, next for actual call.
If we do the token verification in API gateway only (not in microservices) then from the API gateway we need to send the username in every microservices. And microservices implementation needs to be changed to accept that param/header.
When you do server to server communication, you're not really acting on behalf of a user, but you're acting on behalf of the server itself. For that client credentials are used.
Using curl for exemple :
curl acme:acmesecret#localhost:9999/oauth/token -d grant_type=client_credentials
You should do the same with your http client and you will get the access token. use it to call other services.
You should use client tokens using the client_credentials flow for interservice communication. This flow is exposed by default on the /oauth/token endpoint in spring security oauth.
In addition to this, you could use private apis that are not exposed to the internet and are secured with a role that can only be given to oauth clients. This way, you can expose privileged apis that are maybe less restrictive and have less validation since you control the data passed to it.
In your example, you could expose an public endpoint GET account-service/account/current (no harm in getting information about yourself) and a private api GET account-service/internal/account/user-id/{userId} that could be used exclusively by oauth clients to query any existing user.
After reading the article How To Control User Identity Within Microservices I've been trying to implement such access control scheme (Value and Reference Tokens), but after going through multiple other topics and examples in GitHub related to Spring Security + OAuth + Zuul, I couldn't find concrete examples on how this can be achieved. All the examples that involve JWT return User Details when the token is returned, and that is what I would like to avoid. The User Details should never reach the Client directly but should be passed to the backend services instead. The tutorial Spring Security + AngularJs has a lot of information on how to evolve an application towards a secure one, but uses an Access Token or mentions the possibility of getting the User Details directly via JWT.
This SO question, Using Zuul as an authentication gateway by #phoenix7360, is exactly the approach I've been trying to implement but it only supplies a brief overview of the configuration required to carry out this kind of security approach for microservices. Please refer to the image in this question for a clear picture of how it would go.
I can't fully get my head around how the Zuul Pre-Filter should be configured and what the Authorization Server's configuration should look like. As stated in both the article and the SO question, the flow would go something like this:
External (HTTPS)
The client authenticates against OAuth2 Server
OAuth Server returns an opaque Access Token (a UUID with no other information)
The client sends the request to the API Gateway with the Access Token in the Authorization header
API Gateway requests User Details to the OAuth Server with the Access Token in the Authorization header
OAuth Server checks the Access Token is valid and returns User Information in JSON format
Internal (HTTP/S)
API Gateway creates a JWT with User Details and signs it with a private key
API Gateway adds the JWT to request and forwards it to Resource Server
Resource Server verifies the JWT using API Gateway's public key
Note: API Gateway should return an error if OAuth Server indicates Access Token is no longer valid.
How would the ZuulFilter work? Does a new request need to be issued against the OAuth Server (for instance, via RestTemplate), or are these schemes supported with the current implementation? Is there any particular configuration required for the JavaConfig classes for both OAuth and Zuul? If someone knows of a working example that would be really helpful and would be great for future reference regarding this topic.
I'm using Spring Boot (1.4.0-M3) + Spring OAuth + Spring Cloud (Eureka, Ribbon, Zuul)
I know this question is very similar to the one linked previously, and if this is not the right way of doing it I apologize, but I thought a new thread would be better than asking for help on a SO thread that aimed at solving another problem.
Thanks in advance!
JHipster does a pretty good job in handling this issue. If I want to tell the login process briefly, first you do login, in time you fetch every information you need to pass to your below services (such as username,email,etc) then you pass them to your microservices.
you can see the link below from okta for more information
https://developer.okta.com/blog/2018/03/01/develop-microservices-jhipster-oauth
I'm developing an API which only needs to be accessed by servers, as opposed to specific, human users. I've been using the client credentials grant which, if I'm not mistaken, is appropriate for this use case.
So the remote websites/apps, after registering their corresponding OAuth2 clients, are simply requesting an an access token using their client ID/secret combination, via a SSL POST request + HTTP Basic authentication.
Now I was wondering if it would be a good idea, during said access token request, to check the remote IP to make sure it actually belongs to the client that was registered (you'd have to state one or several IPs when declaring your app, then it would be checked against the remote IP of the server making the POST /token request).
I feel like this would be an easy way to make sure that, even if the client ID/secret are somehow stolen, they wouldn't be just usable from anywhere.
Being fairly new to the OAuth2 protocol, I need some input as to whether this is a valid approach. Is there a more clever way to do this, or is it straight up unnecessary (in which case, for what reasons)?
Thanks in advance
That's certainly a valid approach but binds the token tightly to the network layer and deployment which may make it difficult to change the network architecture. The way that OAuth addresses your concern is by the so-called Proof-of-Possession extensions https://datatracker.ietf.org/doc/html/draft-ietf-oauth-pop-architecture.
It may be worth considering implementing that: even though it is not a finalized specification yet, it binds the token to the client instead of the IP address which safeguards against network changes and is more future proof.