How can I use OAuth with stateless REST API? - node.js

When using Passport, a session is used to transfer the user information. This breaks the statelessness of my REST api. How can I use OAuth statelessly on a node/express server?

Most APIs will use the Authorization header, but this is not fundamentally different from putting it in a cookie. Having an authentication token in either header doesn't really break any REST constraints.
The Authorization header is probably preferred unless you want your API to be usable by web browsers.

Related

How to implement a single secure RESTful API layer for both web client and micro-services

I am currently implementing a API project using express-js.
There are multiple clients for the API. This includes a front-end web app and some backend services.
I am looking at using a normal session based management for authentication using express-session.
I am preferring this over jwt since session based + secure cookies is easier for many use cases which I would need need
Ability to revoke user access from server side
Allow only single active web session for a user
I am sure I can maintain a separate persistance table with userid + refresh_token + access_token to achieve the above.
Its just that session based gives me these in straightforward.
Now when it comes to my daemon services, I would still like them to go via API route. This will be more like Client Credentials Flow.
Since these are non-http clients, cookies will not be supported.
I am not sure how my app can API's continue to support both of them ?
The only option I have now based on readings on various blog sources is to use JWT in the cookies for the web front end and using JWT as bearer in header.
This means that
I will need to implement all the security mechanisms like token black-listing, regenerating refresh_token etc.
I will potentially lose out on main benefit of JWT of statelessness.
What are the options I have to ensure that my API layer can support both front-end web apps like react/angular and other micro services
The standard solution here is to use an API gateway:
APIs receive JWT access tokens regardless of the client, and validate them on every request
Browser clients have their own routes to APIs, and send cookies that contain or reference tokens
Mobile clients call API directly, but with opaque access tokens
APIs call each other inside the cluster using JWTs, typically by forwarding the original token from the web or mobile client
The API gateway can perform translation where required. Here are a couple of related articles:
Phantom Token Pattern
Token Handler Pattern
Done well, all of this should provide a good separation of concerns and keep application code simple.

Correct strategy for auth in an API

I want to design a GraphQL API. This API would be used by some browser apps and also open to be used directly for people that want to create their own scripts/generate reports etc. The API would rely on a third party app supporting Oauth Openid Connect (okta) for user and role management. It would be written in Django.
Because JWT is a recommended way of protecting GraphQL APIs and also because OIDC uses JWT tokens. I thought of a simple way, where the API would simply accept the JWT tokens issued by okta. This works, but I see a lot of latency when API is asking okta validate the token (this latency might be smaller in production, because I'm testing on a free trial auth0 instead of production okta). So I think that maybe my API should issue its own JWT tokens. I can think of three strategies here:
Leave it as is – only use the OIDC JWTs.
Introduce a login mutation or a login REST endpoint, that would accept OIDC above and issue JWTs that can be used for all other operations.
As above, but also allow the direct use of okta's JWTs (I'm not sure if I can implement it with Django's auth system, so that if a token is recognised, the OIDC is not called).
Which of these three is the correct (and maybe intended by the OIDC designers) way to protect my API?
JWT token doesn't need to be validated by Okta (generally by IdP). You just need to get used public key (it can be found as jwks url in discovery response) and then can you can verify signatures without any IdP call.
IMHO you can get 2-4k validations/sec easily.

Sending session key in the header vs HTTP-Only cookie

I would like to know the best option for sending session key in my system.
In my system, there is an API server that is used by web browser, command line interface and desktop apps. It authenticates the user by looking at the Authorization HTTP header.
Currently, the browser stores the session key in the localStorage and attaches it in the Authorization header for requests that require login. However, it was pointed out that a more secure way to store secrets such as session keys is using HTTP-Only cookies.
The problem is that the web browser client will not be able to read the HTTP-Only cookie and put the session key in the HTTP header.
Given the situation, I am thinking about extending the API server to use either one of Authorzation header or cookie to authorize users. Is this a feasible option, and are there alternatives?
You are right, Cookies and Authorization headers are not compatible out of the box. As you pointed out, you are looking at two use-cases: one for browser usage and another for API (cli, desktop app).
If you want to support both via a single authentication scheme, you will need to work a bit more. As a good rule of thumb, browsers work well with cookies and its easy to set it up securely. You should opt for cookie-based session management with browsers.
Given the situation, I am thinking about extending the API server to
use either one of Authorization header or cookie to authorize users. Is
this a feasible option, and are there alternatives?
Yes, this is feasible, it will make your browser use-case more secure. As for alternatives, I put together a Web Authentication Guide that will greatly assist you in exploring your options.

Is there a way to use CSRF protection and JWT in a sails app together but not at the same time?

I'm working on an application using sails. web and mobile.
I want to use CSRF protection that sails provides when the app is visiting on the web. And if a request is send by the mobile app. send with the payload a jwt.
On the sails' documentation I found a property csrf.routesDisabled that disabled the CSRF for some routes. But that is not what I want. I'm trying to find a way to for example, check if the parameter jwt is send in the post request. And if the parameter was send then check and validate it. else, check for _csrf value of the form. Is this possible?
or the csrf protecction works before any information is send to the server?
my better choose is use jwt in the web app too?
any other good idea for solving this problem is welcome
thanks
Sounds like you've built the web app with SailsJS and you're trying to reuse the controller actions as REST endpoints for external applications.
Really what you should do, is decouple the data access from the front-end. Have an isolated REST API - using token authentication - which is used by both a web front-end (and any other applications).
For example, I'm currently working with a SailsJS REST API, used by an EmberJS front-end and an iOS app. Both front ends login using user credentials, in order to receive an authentication token. This token is then used for any future requests. A policy locks down all but the login authentication endpoint, to validate the token

Do I need OAuth if I use HTTPS?

I'm building an Node API, together with a Javascript client Application.
I was wondering if there are benefits to implementing OAuth, if I am also using HTTPS.
What if I just send username + password on each request instead of implement OAuth?
As far as I know, HTTPS encrypt the client-server communcation. But I might be missing something importatn.
I'm not going to allow third-party apps to access my API.
OAuth is authorization framework, so you are not getting any security over your API calls by default, especially if you are using OAuth2 which is most likely the case. If you don't need to authorize third party apps, then you don't need it.
If you want to secure your API though, then take a look at hawk, using just Basic authentication is a bit naive.

Resources