Closed Blackening999 closed 6 years ago
@Blackening999 I don't fully understand the problem because that I don't know that's the JWT token look like. In my case, you can store some info like this
let userInfo = {
name: 'tom',
age: 26,
}
let token = 'abcd1234'
ctx.session.user = userInfo
ctx.session.token = token
Hope this can help you~
Unfortunately, it's not working :\
Here's my case:
server.js
import Koa from 'koa'
import KoaRouter from 'koa-router'
import cors from '@koa/cors'
import compress from 'koa-compress'
import koaSession from 'koa-session2'
import graphqlHTTP from 'koa-graphql'
import webpackMiddleware from 'koa-webpack'
import chalk from 'chalk'
import sessionService from './services/session'
import Store from './redisStore'
import webpackConfig from '../../webpack.config.dev'
import graphqlSchema from './schema'
// const ENV = process.env.NODE_ENV || 'development'
const PORT = process.env.PORT || 3000
// const isDev = ENV === 'development'
const graphQLServer = new Koa()
const router = new KoaRouter().get('/ping', async ctx => {
ctx.body = 'pong'
})
router.get('*', ctx => {
ctx.body = `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Create relay modern app</title>
</head>
<body>
<div id="reactDiv" />
<script type="application/javascript" src="/build/bundle.js"></script>
</body>
</html>`
})
graphQLServer.use(
koaSession({
store: new Store(),
key: 'sssecret',
}),
)
graphQLServer.use(sessionService)
router.all(
'/graphql',
graphqlHTTP((request, _, ctx) => ({
schema: graphqlSchema,
graphiql: true,
rootValue: { ctx },
pretty: true,
})),
)
graphQLServer.use(cors())
graphQLServer.use(compress())
graphQLServer.use(
webpackMiddleware({
config: webpackConfig,
hot: true,
}),
)
graphQLServer.use(router.routes()).use(router.allowedMethods())
graphQLServer.listen(PORT, () => {
console.log(`${chalk.magenta('\n[INFO]')} App listening on port ${PORT}!`)
})
store.js
import Redis from 'ioredis'
import { Store } from 'koa-session2'
class RedisStore extends Store {
constructor() {
super()
this.redis = new Redis()
}
async get(sid) {// ctx
const data = await this.redis.get(`SESSION:${sid}`)
return JSON.parse(data)
}
async set(session, { sid = this.getID(24), maxAge = 630000000 } = {}) { // ctx
try {
// Use redis set EX to automatically drop expired sessions
await this.redis.set(
`SESSION:${sid}`,
JSON.stringify(session),
'EX', maxAge / 1000
)
} catch (e) {
console.log(e)
}
return sid
}
async destroy(sid) {// ctx
return await this.redis.del(`SESSION:${sid}`)
}
}
export default RedisStore
session.js
import { decodeToken } from '../../lib/authentication'
async function loadSessionData(ctx) {
if (ctx.session && ctx.session.token) {
return new Promise(resolve => {
let tokenData = null
let err = null
try {
tokenData = decodeToken(ctx.session.token)
} catch (error) {
// eslint-disable-next-line no-undef
err = error
console.log(err)
}
resolve([err, tokenData])
})
}
return new Promise(resolve => resolve([null, null]))
}
export default async function sessionMiddleware(ctx, next) {
console.log(`session: ${ctx.session}`)
console.log(`session: ${JSON.stringify(ctx.session)}`) // nothing here
const [err, sessionData] = await loadSessionData(ctx)
if (err) {
console.log(`err: ${err}`)
ctx.status = 400
ctx.body = 'no token'
await next()
} else if (sessionData) {
ctx.tokenData = sessionData || {}
await next()
} else {
await next()
}
}
LoginMutation.js (where I actually attempt to record something to session)
import { GraphQLNonNull, GraphQLString } from 'graphql'
import { mutationWithClientMutationId } from 'graphql-relay'
// TODO: work on login
import { createToken, decodeToken } from '../../../lib/authentication'
import { getUserWithCredentials } from '../../services/user'
import UserType from '../type/UserType'
export default mutationWithClientMutationId({
name: 'Login',
inputFields: {
email: {
type: new GraphQLNonNull(GraphQLString),
},
password: {
type: new GraphQLNonNull(GraphQLString),
},
},
outputFields: {
user: {
type: UserType,
resolve: ({ user }) => user,
},
},
mutateAndGetPayload: async ({ email, password }, _, { rootValue: { ctx } }) => {
const user = await getUserWithCredentials(email, password)
// set session token so that user is authenticated on next requests via a cookie
if (user) {
/* eslint-disable no-param-reassign */
const token = createToken(user)
ctx.session.token = token
ctx.tokenData = decodeToken(token)
console.log(`${JSON.stringify(ctx.session)}`) // it's here!
/* eslint-enable no-param-reassign */
}
return { user }
},
})
@Blackening999 Could you check if koa has received cookies by this code ctx. cookies.get('sssecret')
?
The issue were because of lack of "credentials: "same-origin" header
Hello,
interesting lib. With better docs in comparison with koa/session. I'm struggling to share a context while working with graphQL app. There, I have to set a token after performing login mutation (based on user data). I wasn't able to do so with koa/session as the only property I could change was maxAge