rkusa / koa-passport

Passport middleware for Koa
MIT License
774 stars 54 forks source link

State, sessions and cookies are not avaible in `returnURL` #106

Closed Bartozzz closed 7 years ago

Bartozzz commented 7 years ago

I am trying to save persistent data in order to send it back to user once the authorization has succeeded. I am trying to achieve this using sessions (koa-session), cookies (implemented by default in Koa.js) and in Passport.js state. None of those works.

I am not sure though, if it is a problem with koa-passport or passport itself. It looks like one of those modules is blocking cookies/sessions at one point.

Client      ->      Server      ->      Provider      ->      Server      ->      Client
                       ^                                         ^
             (A) /api/auth/steam/               (B) /api/auth/steam/callback/

Cookies are set in (A) (and they are available there even in subsequent requests). However, those are undefined in (B).

Server configuration/middlewares:

import Koa from "koa";
import session from "koa-session";
import convert from "koa-convert";
import parser from "koa-bodyparser";
import passport from "koa-passport";

app = new Koa();
app.keys = [ … ];

app.use(convert(parser()));
app.use(session(app));
app.use(passport.initialize());
app.use(passport.session());

Strategy:

Note that the cookies and the session are not available here in the ctx even if passReqToCallback is set to true. ctx.state also doesn't contain ctx.query.connectionID (see routes below).

passport.use(new SteamStrategy({
    returnURL: "http://localhost:8000/api/auth/steam/callback",
    realm: "http://localhost:8000/",
    apiKey: "…",
    state: true,
    passReqToCallback: true
}, (ctx, identifier, profile, done) => {
    Users.findOrCreate({ … })
      .then(user => …)
      .catch(err =>  …);
}));

Routes:

router.get("/api/auth/steam", (ctx, next)  => {
    let n = ctx.session.views || 0;
    let m = parseInt(ctx.cookies.get("views")) || 0;

    ctx.session.views = ++n;
    ctx.cookies.set("views", ++m);

    // Works correctly, displays `n+1, m+1` and this number persist after each refresh
    console.log(ctx.session.views, ctx.cookies.get("views"));

    return passport.authenticate("steam", {
        session: false,
        state: ctx.query.connectionID
    })(ctx, next);
});

router.get("/api/auth/steam/callback", (ctx, next) => {
    // Displays `undefined undefined`
    console.log(ctx.session.views, ctx.cookies.get("views"));

    return passport.authenticate("steam", {
        session: false,
        state: true
    }, …)( ctx, next );
});

When I am requesting /api/auth/steam (A) it outputs n+1 and m+1 correctly, so cookies and sessions are set. However, those are undefined in returnURL (B).

I am not sure if passport is regenerating sessions/refreshing cookies or something in the returnURL (B), but it should not be the case as I've disabled sessions by myself ({ session: false }). Any thought why those cookies/sessions/states are not avaible in another route (returnURL)?

rkusa commented 7 years ago

Hi @Bartozzz,

I am not able to spot something particularly wrong with your code, so I can just try to guess.

First, for

Note that the cookies and the session are not available here in the ctx even if passReqToCallback is set to true.

Maybe #89 issue provides you with an intermediate solution (https://github.com/rkusa/koa-passport/issues/89#issuecomment-284972922) until this issue is finally integrate into koa-passport somehow.

My guess for the actual problem would be that the steam authentication provider ignores Set-Cookie and simply does not provide you with a Cookie header for the callback. Could this be the reason?