Frontend passing oauth token to dropwizard backend - oauth

I'm looking for some advice on 'proxying' authentication for my application. i.e. using the same authentication on the front- and back- end of my application. The architecture consists of a DropWizard backend API and a NodeJS frontend.
Currently, the frontend is protected by Google OAuth and is working well. However, the backend is only protected by Basic authentication. The NodeJS server has the basic auth credentials embedded in it, to allow backend calls, which is not a great solution.
I'd like to know if there's a way to pass the OAuth credentials/token from the front end to the back end, so that I can lock down the back end more securely. Additionally, it would be nice to either keep the basic auth on the backend, or have a way to make OAuth backend api calls from the command line, using curl.

An alternative is to use something like a VPC to keep your back end server on a secure network. Give your front end a public-facing IP, but keep the back end internal, and only accept requests on the back end from that front end server, or just from the internal network. Then you don't need any authentication on the back end, and you can access it with VPN or another machine on the secure network.

Related

Securing Api Calls without OAuth2 client credentials flow in a SPA application

I've got a SPA application which gives statistics and information to anonymous users. It is a react spa app and will consume backend REST Web API(.net core). These data are not specific to users, therefore the information is freely available and no user authentication is required. However, I don't want my Backend Api layer to be exposed to the internet (i.e not use by anonymous applications such as postman, rest clients, etc). I'm familiar with the Client credential flow (OAuth) but I can't use it for this application because there is no concept for user login in this application.
What would be my best options that limit access to my API layer to anonymous applications (i.e postman, etc), or is it not possible at all?
You can't use client credentials flow for your SPA. Anyone would be able to download your SPA, extract the client id and secret and use it to call your API.
If you do not want to authenticate your users, there's no good way to protect your API. Move your SPA to a traditional web application hosted on a server to protect it using client credentials flow.
It's not possible to make an API accessible to a public client (your SPA) without also making it accessible to users making API calls from Postman or custom code. It's possible to do the reverse, only because of the limitations that browsers put in place.
Depending on what you're trying to achieve, you could use something like reCAPTCHA to validate that the users of your API are humans, not scripts. That along with human-scale rate limiting would probably filter out most of non-app users.

User authentication and dynamic routing in traefik

I want to replace haproxy with traefik. But in order to that, I have to replace a Lua script which handles authentication (via auth token calling a rest API) and custom redirect (certain docker service) depending on headers and authentication from before.
Is there an (easy) way to that?
Right now as for migrating I was thinking to leave haproxy for now and routing all valid traffic to traefik.
Authentication and Traefik is not an easy thing. At my company, we just switched back from Traefik to nginx since handling ldap/kerberos/pki etc. With Traefik can be painfully awkward. There is the possibility to pass authentication on from Traefik to a 3rd party and collect the session token or other relevant information using Forward Auth, so maybe take a look at that. You can also use BasicAuth
Although getting it to run with your setup might prove hacky.

Access Token/Authorization Between Microservices

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.

RoR reverse proxy (oauth)

We currently have the following architecture (for a RoR based production system)
A gateway, which also acts as auth (oauth functionality implemented using DoorKeeper) is the starting point for all requests coming from the front end.
The system is working perfectly well. The task we are faced with now involves addition of a legacy application (written in multiple languages, including ASP.NET). This legacy application currently works fine as a standalone system. What we intend to do is
Integrate the legacy system within our working system (within our own subnet)
Do minimum (or if possible zero) modifications to the legacy system
keep using our oauth layer (gateway) as the first point of contact for all incoming requests (including the requests to the legacy system)
We are in control of the front end requests and routing, so CSRF is not a concern
One solution that we are considering is that the auth layer (gateway) also acts as a reverse proxy. In essence any request coming for the legacy environment (from the legacy front end clients) will be authenticated by doorkeeper but they will now be redirected to the legacy server-application and the response is then send back to the client.
The above sounds like a nginx reverse proxy, but I want a RoR gem which I can use because I want this to be flexible for future modifications. For example (but not limited to)
I can modify the legacy client to start using multiple auth mechanisms (so the request from client to auth layer will have different headers, but I would like to change this request to its legacy format during the journey from auth-legacy-backend-server-application and back) [easier]
I would like to add encryption (SSL) on client to auth (gateway) requests. The gateway will decrypt the request and send un-encrypted request for the auth-legacy-backend-server-application and back journey) [tougher]
A few of the legacy system requests are such that Legacy-FrontEnd (LFE) --> Legacy-Backend (LBE) use cookie based sessions. I want to use the gateway to simulate this behavior.
LFE -> gateway uses my auth mechanism (say encrypted tokens)
gateway -> LBE simulates the cookie based sessions behavior
gateway keeps the mapping of token to session-cookie
[the last point above is a over simplification of a use case we might encounter at a later date]

Securing REST and JSON

I want to build my web services serving JSON data utilizing RESTful architecture.
But I want my own client apps only that can request from my web services.
Basically, my web services contain sensitive data that is not for public consumption, but I wanted to build it that way so I can build many different client apps that connects to my web service.
Would appreciate any ideas for this, thanks.
The fact that it's RESTful or uses JSON isn't a relevant factor when it comes to securing a web service. Any web service would need to be secured in the same manner. There are a few things you should do:
If possible, don't host your web service on the Internet. If the web service is hosted within your company's LAN, for example, it won't be exposed to public consumption unless you specifically exposed it through your router.
Set up authentication and authorization rules. If you're hosting your web service inside of a Windows domain, you could simply use Windows authentication and set up rules based on Active Directory users and groups. Other options are to use HTTP authentication, client certificate authentication, or if you're developing in .NET, forms authentication.
Use encryption (HTTPS), especially if your web site is hosted on the Internet.
You just need a couple things in place to do this. First, the service client will need to authenticate against your service (over HTTPS) to make a request. Once the client is authenticated, you can return a private token which the client has to include with this token. As long as the token expires after a reasonable amount of time, and a secure algorithm is used to generate it, this should do what you want.
If you have more strict security requirements, you can follow Jakob's suggestion, or have the client start a VPN session prior to making requests.

Resources