Next auth + graphqlのログイン機能を実装したいです。ユーザー情報を保存するサーバーは、apollo-serverとmongodbをつかっていて、JWTでパスワードをトークンとして保存しています。
その上で、今一番困っていることはSessionの設定の仕方がわからないことです。
エラーメッセージはこんなかんじです。
[next-auth][error][CALLBACK_CREDENTIALS_JWT_ERROR] https://next-auth.js.org/errors#callback_credentials_jwt_error Signin in with credentials only supported if JWT strategy is enabled UnsupportedStrategy [UnsupportedStrategyError]: Signin in with credentials only supported if JWT strategy is enabled at assertConfig (C:\Users\kenta\Desktop\Apps\g-sns-client\node_modules\next-auth\core\lib\assert.js:45:14) at NextAuthHandler (C:\Users\kenta\Desktop\Apps\g-sns-client\node_modules\next-auth\core\index.js:34:52) at NextAuthNextHandler (C:\Users\kenta\Desktop\Apps\g-sns-client\node_modules\next-auth\next\index.js:16:51) at NextAuth (C:\Users\kenta\Desktop\Apps\g-sns-client\node_modules\next-auth\next\index.js:55:10) at __WEBPACK_DEFAULT_EXPORT__ (C:\Users\kenta\Desktop\Apps\g-sns-client.next\server\pages\api\auth[...nextauth].js:137:128) at Object.apiResolver (C:\Users\kenta\Desktop\Apps\g-sns-client\node_modules\next\dist\server\api-utils.js:101:15) at runMicrotasks (<anonymous>) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async DevServer.handleApiRequest (C:\Users\kenta\Desktop\Apps\g-sns-client\node_modules\next\dist\server\next-server.js:770:9) at async Object.fn (C:\Users\kenta\Desktop\Apps\g-sns-client\node_modules\next\dist\server\next-server.js:661:37) { code: 'CALLBACK_CREDENTIALS_JWT_ERROR' }
こちらがブラウザのコンソールに出たエラーメッセージです。
[next-auth][error][CLIENT_FETCH_ERROR] https://next-auth.js.org/errors#client_fetch_error JSON.parse: unexpected character at line 1 column 1 of the JSON data Object { error: {…}, path: "session", message: "JSON.parse: unexpected character at line 1 column 1 of the JSON data" } client: true error: Object { message: "JSON.parse: unexpected character at line 1 column 1 of the JSON data", stack: "", name: "SyntaxError" } message: "JSON.parse: unexpected character at line 1 column 1 of the JSON data" path: "session" <prototype>: Object { … } logger.js:46 error logger.js:46 level logger.js:81 _callee$ _utils.js:73 Babel 12 fetchData _utils.js:24 _callee2$ index.js:128 Babel 8 getSession index.js:115 _callee$ index.js:457 Babel 8 React 5
やってみたこと。
const session = { jwt: true,//strategy: "jwt" のほうもやってみました。 }
[...next-auth].jsの中身はこんな感じです。
import NextAuth from "next-auth" import CredentialsProvider from "next-auth/providers/credentials"; import axios from 'axios' import { getToken } from "next-auth/jwt" import { gql, useMutation } from '@apollo/client'; const LOGIN_MUTATION = gql` mutation loginMutation($email: String!, $password: String!) { LoginUser(email: $email, password: $password) { username } } ` const providers= [ CredentialsProvider({ id: 'credentials', name: "email", async authorize(credentials) { const [loginMutation, {data, loading, error}] = useMutation(LOGIN_MUTATION) if (loading) return 'Submitting...'; if (error) return `Submission error! ${error.message}`; try { console.log(credentials.username) console.log(credentials.password) console.log(data) loginMutation({variables: {email: credentials.username, password: credentials.password}}) if (data) { user = data return user; } } catch (e){ const errorMessage = e.message; throw new Error(errorMessage + '&email' + credentials.email) } } }) ] const callbacks = { async signIn(user, account, profile) { if (typeof user.email !== typeof undefined) { if (user.isActive === '1') { return user; } else { return false; } } else { return false; } }, async session({ session, token }) { if (userAccount !== null) { session.user = userAccount; } else if (typeof token.user !== typeof undefined && (typeof session.user === typeof undefined || (typeof session.user !== typeof undefined && typeof session.user.userId === typeof undefined))) { session.user = token.user; } else if (typeof token !== typeof undefined) { session.token = token; } return session; }, async jwt(token, user, account, profile, isNewUser) { if (typeof user !== typeof undefined) { token.user = user; } return token; } } const secret = process.env.NEXT_PUBLIC_AUTH_SECRET /** const cookie = { secure:process.env.NODE_ENV && process.env.NODE_ENV === 'production', }*/ const session = { jwt: true, //maxAge: 30 * 24 * 60 * 60 } const options = { providers, callbacks, secret, session, pages: { error: '/login' } } export default (req, res) => NextAuth(req, res, options)
認証ページはこんな感じです。ぜひよろしくおねがいします。
import { useState, useEffect } from 'react' import { useRouter } from 'next/router' import { signIn, getSession, useSession } from 'next-auth/react' async function getServerSideProps(ctx) { return { props: { session: await getSession(ctx) } } } export default function Login () { const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [isLoginStarted, setIsLoginStarted] = useState(false) const [loginError, setLoginError] = useState('') const router = useRouter() useEffect(() => { if (router.query.error) { setLoginError(router.query.error) setEmail(router.query.email) } }, [router]) const handleLogin = (e) => { e.preventDefault() setIsLoginStarted(true) signIn('email', { email, password, callbackUrl: 'http://localhost:3000'///${window.location.origin} } ) } return ( <div > <main > <div > <h1>Welcome Back salesdude@gmail.com</h1> <form onSubmit={(e) => handleLogin(e)} > <label htmlFor='loginEmail'>Email</label> <input id='loginEmail' type='email' value={email} onChange={(e) => setEmail(e.target.value)} /> <label htmlFor='inputPassword'>Password</label> <input id='inputPassword' type='password' value={password} onChange={(e) => setPassword(e.target.value)} /> <button type='submit' disabled={isLoginStarted} >Log In</button> </form> </div> </main> </div> ) }
あなたの回答
tips
プレビュー