kleydon / prisma-session-store

Express session store for Prisma
MIT License
116 stars 18 forks source link

Incomplete session data #81

Closed hugil closed 1 year ago

hugil commented 2 years ago

Used in conjunction with:

import passport from 'passport';
import { Strategy } from 'passport-steam';

Session data generated is incomplete, an invalid json object.

Console output, debugging output of session variable:

23:43:52 - Starting compilation in watch mode...
[0] 
[0] 
[0] 23:43:53 - Found 0 errors. Watching for file changes.
[1] ⚡️[server]: Server is running at https://localhost:3000
[1] {
[1]   id: 'CBpA13VXdJwuIFAkenkOzekaILnpMY_8',
[1]   sid: 'CBpA13VXdJwuIFAkenkOzekaILnpMY_8',
[1]   data: '{"cookie":{"originalMaxAge":86400000,"expires":"2022-04-30T21:43:25.453Z","httpOnly":true,"path":"/"},"passport":{"user":{"provider":"steam","_json":{"steamid":"7656xxxxx","communityv',
[1]   expiresAt: 2022-04-30T21:43:25.453Z
[1] }
[1] get(): SyntaxError: Unexpected end of JSON input
[1] GET / 500 21.584 ms - 566

data variable content:

{"cookie":{"originalMaxAge":86400000,"expires":"2022-04-30T21:43:25.453Z","httpOnly":true,"path":"/"},"passport":{"user":{"provider":"steam","_json":{"steamid":"7656xxxxx","communityv',

as can be seen the json content is incomplete

application crashes.

hugil commented 2 years ago

SyntaxError: Unexpected end of JSON input at JSON.parse () at PrismaSessionStore. (F:\x\node_modules\@quixo3\prisma-session-store\dist\lib\prisma-session-store.js:310:54) at step

(F:\x\node_modules\@quixo3\prisma-session-store\dist\lib\prisma-session-store.js:63:23) at Object.next

(F:\x\node_modules\@quixo3\prisma-session-store\dist\lib\prisma-session-store.js:44:53) at fulfilled

(F:\x\node_modules\@quixo3\prisma-session-store\dist\lib\prisma-session-store.js:35:58)

kleydon commented 2 years ago

@hugil - thanks for the report. Not sure what's going on here...

hugil commented 2 years ago

@kleydon - thanks for looking into this

However haven't had time to look into those details yet.

kleydon commented 2 years ago

Great - thanks @hugil !

kleydon commented 2 years ago

Hi @hugil - I noticed that you and another user of prisma-session-store, @decifris - see issue #83 - are both using passport; maybe you can put your heads together on this issue, if its still occuring?

ivenuss commented 1 year ago

Hi. I'm having similar error using passport.

Data will get saved, but only part of them, not the user variable.

Table row example:

id: hDun73nT-sm4CS84tKj9hsqcaVWONxqa
sid: hDun73nT-sm4CS84tKj9hsqcaVWONxqa
data: {"cookie":{"originalMaxAge":604800000,"expires":"2022-06-26T21:16:58.261Z","httpOnly":true,"path":"/"}}
expiresAt: 2022-06-26 21:16:58.262

Error (happens on auth callback)

Error: 
Invalid `this.prisma[this.sessionModelName].delete()` invocation in
C:\node_modules\@quixo3\prisma-session-store\dist\lib\prisma-session-store.js:266:91      

  263 case 3:
  264     _a.sent();
  265     return [3 /*break*/, 6];
→ 266 case 4: return [4 /*yield*/, this.prisma[this.sessionModelName].delete(
  An operation failed because it depends on one or more records that were required but not found. Record to delete does not exist.
    at RequestHandler.request (C:\node_modules\@prisma\client\runtime\index.js:49022:15)  
    at PrismaClient._request (C:\node_modules\@prisma\client\runtime\index.js:49919:18) 

My schema;

model Session {
  id        String   @id
  sid       String   @unique
  data      String
  expiresAt   DateTime
}

Express session config:

app.use(
  session({
    proxy: true,
    secret: process.env.SESSION_SECRET,
    name: 'the_session',
    resave: true,
    saveUninitialized: false,
    store: new PrismaSessionStore(prisma, {
      checkPeriod: 2 * 60 * 1000,
      dbRecordIdIsSessionId: true,
      dbRecordIdFunction: undefined,
    }),
    cookie: {
      maxAge: 7 * 24 * 60 * 60 * 1000, //week
    },
  })
kleydon commented 1 year ago

A fix from PR #93 may improve matters, here; tbd.

ivenuss commented 1 year ago

A fix from PR #93 may improve matters, here; tbd.

Thank you for the immediate response. However first session store worked fine after upgrading the package. The next one throwed me same error.

kleydon commented 1 year ago

Ok - good to know; thanks for the feedback.

hugil commented 1 year ago

Hi again, Sorry for the delay on updates on this issue from my side. Did some further investigation.

So it turns out that the issue is due to the MySQL default character limitation (191 characters)

This affects the Steam passport sign in strategy in particular since it serializes the entire json object containing metadata about the steam profile which is quite large. Things you would normally query the database for when you actually need them.

For further explanation on the SQL limit:

The index key prefix length limit is 767 bytes for InnoDB tables that use the REDUNDANT or COMPACT row format. For example, you might hit this limit with a column prefix index of more than 191 characters on a TEXT or VARCHAR column, assuming a utf8mb4 character set and the maximum of 4 bytes for each character.

Attempting to use an index key prefix length that exceeds the limit returns an error.

Reference: https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html

Solution

I guess there's two ways to go about this.

  1. You can set the maximum length in your Prisma schema using the annotation @db.VarChar to a higher value, or set the datatype to JSON.
  2. Better, serialize less session data like only storing the user id.
kleydon commented 1 year ago

@hugil - Glad the source of the problem finally revealed itself! Thanks for sharing what you discovered.