问题
I have a Passport-using application with a GraphQL endpoint and a /logout
endpoint. For some reason when I called request.isAuthenticated()
from inside the GraphQL endpoint I got back true
, but when I made the same exact call from inside the /logout
endpoint I got back false
.
So, I did a bit of logging (of request.session.id
) and it turns out that I somehow wound up with two sessions. Stranger still, the session used by my GraphQL endpoint is persistent: if I restart the server it keeps the same ID, while the one in /logout
keeps changing.
I think that what's happening is that the persistent session is cookie/DB-based, and so gets restored when my client makes its first request, while the /logout
session is not cookie-based and gets reset with the server. What I don't understand is why I have two sessions!
Here's the relevant code:
// Session setup
const store = new KnexSessionStore({ knex, tablename: 'sessions' });
app.use(
session({
cookie: { maxAge: 1000 * 60 * 60 * 24 * 5},
secret: `a secret`,
store
})
);
// Passport setup
passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((user, done) => done(null, user));
app.use(passport.initialize());
app.use(passport.session());
// GraphQL Setup
// NOTE: request.session.id from inside a function in schema = persistent session
const graphQLHandler = graphqlHTTP(request =>({ graphiql: true, schema }));
app.use('/graphql', graphQLHandler);
// Logout Setup
app.get('/logout', (request, response) => {
// NOTE: request.session.id = non-persistent session
response.send(`user has been logged out`); // someday do request.logout()
});
As you can see, the express session setup function (session
) is only called once. I do call app.use(passport.session())
(which looks like it might be creating a second session), but my understanding is that line just tells Passport to use the session ... it doesn't create a whole separate parallel session.
Can anyone explain what's going on, and how I can get my app to share a single session? Or alternatively if anyone can explain where I could add some code to throw an error whenever a session gets created (so that I can figure out what part of my code creates the second session) that would helpful too.
回答1:
I found the answer! Apparently I wasn't the only one having this problem: https://github.com/jaredhanson/passport/issues/244. You can read all the details there, but ...
TLDR: My client was fetch
-ing /logout
from the server. However by default fetch
doesn't set the { credentials: 'same-origin' }
option, and apparently you need to provide that or else Passport just silently starts creating duplicate sessions :(
So it turned out there was nothing wrong with my server code at all, the fix was just doing the following on the client-side:
fetch(`/logout`, { credentials: 'same-origin' });
Here's hoping the Passport people start throwing errors or warnings or something in response to this case, rather than letting their poor users boggle at the inexplicable, but common result (the comment with the answer had 15 thumbs ups).
来源:https://stackoverflow.com/questions/48777201/how-do-i-have-two-express-sessions