simov / grant

OAuth Proxy
MIT License
4.1k stars 257 forks source link

Avoiding sessions #59

Closed kyrylkov closed 8 years ago

kyrylkov commented 8 years ago

Is there a reason why Grant requires the use of sessions and cookies?

simov commented 8 years ago

Grant uses cookies and session to persist state between the OAuth steps (redirects). After the OAuth flow is complete you can generate the jwt token inside your callback route and then you can remove the flow data from the session.

kyrylkov commented 8 years ago

Both for oauth 1.0 and 2.0?

simov commented 8 years ago

Yep, there is no difference when using Grant. I guess it's safe enough to even use the in memory session store in production, because you really use it only during the OAuth flow, after that you can choose where and how to store the user's credentials.

kyrylkov commented 8 years ago

How much effort would it be to make it use express-jwt as an option instead of express-session?

simov commented 8 years ago

I'm not sure what exactly is your goal, but you can create a route on your server that uses the express-jwt middleware, that redirects to the /connect/:provider route. After that inside the final callback route of the OAuth flow you can destroy the session and tell the browser to remove the cookie as well.

Let me know if that makes any sense.

simov commented 8 years ago

Also I forgot to mention that after your are being redirected to the third party server of the provider, when the third party server redirects you back to your server that request won't have a JWT token in it (correct me if I'm wrong).

simov commented 8 years ago

Another thing is that once you have the OAuth access_token from the third party provider you have to store it somewhere on your server. Meaning that you can still use JWT to make requests to your own API, but once that API request involves requesting a third party resource you have to load the access_token from somewhere. Obviously storing the access_token in your JWT is not a good option.

kyrylkov commented 8 years ago

Creating and deleting a cookie for this purposes only is very kludgy.

I'm looking for a solution to replace repetitious satellizer server code

simov commented 8 years ago

You are asking for two separate things:

The first part is about having a cookie:

Grant is purely a server side solution. The server should persist state during the OAuth flow. After the third party server redirects you back to your website the server should be able to know which state to pick to continue with the flow. That's what the cookie is for.

The second part is about generating JWT:

If I'm understanding correctly you want only to login your users using various third party providers, get their profile data, and generate JWT based on that.

If that's the case take a look at the profile example on how to get the user's profile inside the callback route. That's the place where you should generate the JWT and return it to the user. It's not that hard to do it actually, take a look at the jws module it's all you need really.

Lastly you should destroy the session and remove the cookie.

kyrylkov commented 8 years ago

I have everything implemented manually, however I'd like to rely on well supported modules to minimize maintenance.

I just reviewed passport and it doesn't require the use of express-session.

simov commented 8 years ago

Take a look at this, that's the module that every passport- OAuth2 provider depend on:

This is the state store implementation for the OAuth2Strategy used when the state option is enabled. It generates a random state and stores it in req.session and verifies it when the service provider redirects the user back to the application. This state store requires session support. If no session exists, an error will be thrown.

The only difference is that the session store is required in Grant, because it is used for dynamic overrides as well. It also helps you out in the rare cases when you do override the redirect_uri that is generated by Grant by default.

simov commented 8 years ago

I just pushed a small example about JWT.

This is the session configuration and this is how you destroy the session and tell the browser to remove the cookie. I'm looking at the Resources tab in my Chrome Dev Tools and I don't see the cookie there after the OAuth flow is complete.

On a side note: The session is also used for security reasons. In case you don't specify transport: 'session' in your config, the access token is returned as querystring inside the final callback, and usually that data end up being stored in the server logs as well.

kyrylkov commented 8 years ago

Thanks. We'll check it out.

kyrylkov commented 8 years ago

After implementing Oauth 1.0 manually, it is finally clear where session or some sort of other state is required. Previously we used had only Oauth 2.0, which didn't need it.

simov commented 8 years ago

OAuth2.0 have an optional state parameter. However you should always include one to prevent certain vectors of attack.

You can enable the automatic state generation for OAuth2.0 by adding state: true to your server's config:

"server": {"state": true}

Here is the required state you are talking about:

simov commented 8 years ago

So, to answer your question: Some sort of state is unavoidable, whether it's a session or something else.

Using sessions is the most flexible solution that also works out of the box, and pretty much every web developer is familiar with it.

If you can suggest a better alternative for keeping state on the server, I'll take it into consideration. Otherwise this issue can be closed.

simov commented 8 years ago

@kyrylkov feel free to re-open this issue and/or ask any other question.