フルスタックチャンネル
サインアップサインアップ
ログインログイン
利用規約プライバシーポリシーお問い合わせ
Copyright © All rights reserved | FullStackChannel
受付中
Django REST Framework + NextJS + Google認証システム構築 で作成した認証機能を用いて、DRFのAPIを実行したい。
DRF
Next.js
hodakam
2023/05/23 15:55

実現したいこと

  • Django REST Framework + NextJS + Google認証システム構築
    で作成した認証機能を用いて、DRFのAPIを実行したい。

発生している問題

  • Google認証で認証でログイン後、取得したaccessTokenを用いてDRFのAPIを叩いても認証エラーになってしまう。
  • ChromeののDevtoolsは下記の通りで、DRFからは401エラーが返ってきております。

code: "token_not_valid"
detail: "Given token not valid for any token type"

ソースコード

  • 認証機能周りはDjango REST Framework + NextJS + Google認証システム構築に準拠しています。
  • 一部、記事のとおりでは動かない部分があったので修正しています。

component.tsx (抜粋です)

import { getSession } from 'next-auth/react';

const DatasourceTableView: FC = () => {
  useEffect(() => {
    const fetchData = async () => {
      if (!data.length) {
        setIsLoading(true);
      } else {
        setIsRefetching(true);
      }
      const session = await getSession();
      // console.log(session.accessToken)
    
      const url = new URL(
        'api/v1/datamanagement/',
        process.env.NODE_ENV === 'production'
          ? 'https://www.material-react-table.com'
          : 'http://localhost:8000',
      );
      try {
        const response = await fetch(url.href,
          {
            headers: {
              'Authorization': 'JWT ' + session.accessToken,
            },
          }
          )

pages/api/auth/[...nextauth].ts

import NextAuth from 'next-auth'
import GoogleProvider from "next-auth/providers/google";
import axios from 'axios'

const settings = {
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      secret: process.env.SECRET,
    }),
  ],
  callbacks: {
    async signIn({user, account}) {
      if (account.provider === 'google') {
        const accessToken = account.access_token;
        const idToken = account.id_token;
        try {
          const response = await axios.post(
            `${process.env.DJANGO_URL}/api/v1/social/login/google/`,
            {
              access_token: accessToken,
              id_token: idToken,
            }
          )

          const { access_token } = response.data
          console.log(access_token)
          user.accessToken = access_token
          return true
        } catch (error) {
          return false
        }
      }
      return false
    },

    async jwt({ token, account }) {
      if (account) {
          token.accessToken = account.access_token
      }
      // console.log(token)
      return token
    },

    async session({ session, token }) {
      session.accessToken = token.accessToken
      return session
  }
  },
}

export default (req, res) => NextAuth(req, res, settings)

自分で試したこと

  • 表示されたaccessTokenをこのサイトでエンコードしようと思ってもinvalid Signatureになる
  • curl -X GET http://localhost:8000/api/v1/datamanagement/ -H 'Authorization: JWT mytoken' と送っても同様のエラーが起きる

補足情報

回答 3件
login
回答するにはログインが必要です
hodakam
約2年前

いろいろ確認したところ、tokenのコピーミスであったようです。無事動作することが確認できました!

hodakam
2年以上前

回答ありがとうございます。
ログインやトークン取得はできているように見えます。
というのも、

  const response = await axios.post(
    `${process.env.DJANGO_URL}/api/v1/social/login/google/`,
    {
      access_token: accessToken,
      id_token: idToken,
    }
  )

のresponseを確認すると

  data: {
    access_token: '****',
    refresh_token: '****',
    user: {
      userId: '9257b**',
      username: 'kp**',
      email: '***@gmail.com',
      password: '***'
    }
  }
}

となっているためです。ここで表示されたaccess_tokenをcurl -X GET http://localhost:8000/api/v1/datamanagement/ -H 'Authorization: JWT mytoken'
とすると、

{"detail":"Given token not valid for any token type","code":"token_not_valid","messages":[{"token_class":"AccessToken","token_type":"access","message":"Token is invalid or expired"}]}

というエラーになります。つまりdjango側からGoogle認証を行い、tokenを発行するところまではできているが、そのtokenを使って認証しようとするとトークンエラーになるという状況です。

はる@講師
2年以上前

Djangoからエラーが返ってくるのは、おかしいですね。

GCPの設定やDjangoのSocial applicationsの設定がうまくいってないなどでしょうか。