AyumuOgasawara / receipt-scanner

レシートの写真から家計簿を生成してくれるアプリ
0 stars 0 forks source link

NextAuthを使用して認可認証をしてからアプリにサインアップ、ログインできるようにする #15

Closed AyumuOgasawara closed 3 weeks ago

AyumuOgasawara commented 2 months ago

NextAuthのGoogoleProviderを使用する

https://next-auth.js.org/providers/google

AyumuOgasawara commented 3 weeks ago

まずはGetting Startedから行っていく。

https://next-auth.js.org/getting-started/example

AyumuOgasawara commented 3 weeks ago

prismaのアダプターも必要 https://next-auth.js.org/v3/adapters/prisma

よって、nextauthとprismaのadapterをインストールする。

npm install next-auth @next-auth/prisma-adapter

AyumuOgasawara commented 3 weeks ago

全然書いてなかった。。。

どうやら、ユーザーテーブルはgoorleで決まっているものがあった、それは必要らしい。

Invalid `prisma.user.create()` invocation:

{
  data: {
    name: "Ayumu Ogasawara",
    email: "ogasaayumu0114@gmail.com",
    image: "https://lh3.googleusercontent.com/a/ACg8ocIj-EQRWcnmDC_9pE0lCugiInShiCpWbOAY2Km7qbrEJJyhMQ=s96-c",
    ~~~~~
    emailVerified: null,
?   id?: String,
?   passwordDigest?: String | Null,
?   createdAt?: DateTime,
?   updatedAt?: DateTime,
?   expenses?: ExpenseCreateNestedManyWithoutUserInput,
?   budgets?: BudgetCreateNestedManyWithoutUserInput,
?   accounts?: AccountCreateNestedManyWithoutUserInput
  }
}
AyumuOgasawara commented 3 weeks ago

ずっとこのエラーが出る。

Unknown argument `provider_providerAccountId`. Did you mean `providerId_providerAccountId`? Available options are marked with ?.
    at In (/Users/ayumu/my-projects/receipt-scanner/node_modules/@prisma/client/runtime/library.js:114:7526)
    at Ln.handleRequestError (/Users/ayumu/my-projects/receipt-scanner/node_modules/@prisma/client/runtime/library.js:121:7396)
    at Ln.handleAndLogRequestError (/Users/ayumu/my-projects/receipt-scanner/node_modules/@prisma/client/runtime/library.js:121:7061)
    at Ln.request (/Users/ayumu/my-projects/receipt-scanner/node_modules/@prisma/client/runtime/library.js:121:6745)
    at async l (/Users/ayumu/my-projects/receipt-scanner/node_modules/@prisma/client/runtime/library.js:130:9633)
    at async getUserByAccount (webpack-internal:///(rsc)/./node_modules/@next-auth/prisma-adapter/dist/index.js:211:29) {
  name: 'GetUserByAccountError',
  code: 
AyumuOgasawara commented 3 weeks ago

だけど、名前はちゃんとあってる。

model Account {
  userId            String
  type              String
  provider          String
  providerAccountId String
  refresh_token     String?
  access_token      String?
  expires_at        Int?
  token_type        String?
  scope             String?
  id_token          String?
  session_state     String?

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@id([provider, providerAccountId])
  @@map("accounts")
}
AyumuOgasawara commented 3 weeks ago

これに関してのイシューが開かれていた。

https://github.com/nextauthjs/next-auth/issues/11205#issuecomment-2178251882

AyumuOgasawara commented 3 weeks ago

いろいろ試したが何もできなかった。

AyumuOgasawara commented 3 weeks ago

以下のgithubを参考にしてやってみる。 https://github.com/SSazzadur/nextjs-google-auth

Next.js Google Authentication with Auth.js, Prisma, and MongoDB

AyumuOgasawara commented 3 weeks ago

https://qiita.com/okm-uv/items/0b84c75e7524640dab11

Auht.jsのPrisma Adapterのprisama.schemaを見ると、cuid()が使われている。 uuidの方がメジャーだと書いてあったため、uuidを使う。

AyumuOgasawara commented 3 weeks ago

Headerでもログイン・ログアウトできるようにしたい。 そのため、以下のようにした。

## src/_components/layouts/Header/Header.tsx
{isSignedIn ? (
            <>
              <Typography variant="h6">{userName}</Typography>
              <Button variant="outlined" onClick={async() => {await authControl("SignOut")}} sx={{backgroundColor: "white"}}>ログアウト</Button>
            </>
          ) : (
            <Button variant="outlined" onClick={async() => {await authControl("SignIn")}} sx={{backgroundColor: "white"}}>ログイン</Button>
          )}
## src/_components/layouts/Header/HeaderServer.ts

import { signIn, signOut } from "@/auth";

export const authControl = async(action: string) => {
if(action == "signOut"){
    await signIn("google")
}else{
    await signOut()
}
}

すると以下のようなエラーが出た。

Error: `headers` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context 
AyumuOgasawara commented 3 weeks ago

Headerでもログイン・ログアウトできるようにしたい。 そのため、以下のようにした。

## src/_components/layouts/Header/Header.tsx
{isSignedIn ? (
            <>
              <Typography variant="h6">{userName}</Typography>
              <Button variant="outlined" onClick={async() => {await authControl("SignOut")}} sx={{backgroundColor: "white"}}>ログアウト</Button>
            </>
          ) : (
            <Button variant="outlined" onClick={async() => {await authControl("SignIn")}} sx={{backgroundColor: "white"}}>ログイン</Button>
          )}
## src/_components/layouts/Header/HeaderServer.ts

import { signIn, signOut } from "@/auth";

export const authControl = async(action: string) => {
if(action == "signOut"){
    await signIn("google")
}else{
    await signOut()
}
}

すると以下のようなエラーが出た。

Error: `headers` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context 

ただ、"use server"を使っていないだけだった。

AyumuOgasawara commented 3 weeks ago

GoogleでクライアントIDを作成している (参考)

AyumuOgasawara commented 3 weeks ago

jwtについてはこちらを参考にした (参考)