コンテンツにスキップ
NextAuth.js v4 からの移行ですか?お読みください 移行ガイド.

Dgraph アダプター

リソース

セットアップ

インストール

npm install @auth/dgraph-adapter

環境変数

AUTH_DGRAPH_GRAPHQL_ENDPOINT=https://#:8080/graphql
AUTH_DGRAPH_GRAPHQL_KEY=abc123

設定

./auth.ts
import NextAuth from "next-auth"
import { DgraphAdapter } from "@auth/dgraph-adapter"
 
export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [],
  adapter: DgraphAdapter({
    endpoint: process.env.AUTH_DGRAPH_GRAPHQL_ENDPOINT,
    authToken: process.env.AUTH_DGRAPH_GRAPHQL_KEY,
    // you can omit the following properties if you are running an unsecure schema
    authHeader: process.env.AUTH_HEADER, // default: "Authorization",
    jwtSecret: process.env.AUTH_SECRET,
  }),
})

安全でないスキーマ

Dgraph を使用する最も簡単な方法は、安全でないスキーマをローカルの Dgraph インスタンスに適用することです。または、Dgraph クラウドを使用している場合は、コードボックスにスキーマを貼り付けて更新できます。

⚠️

このアプローチは安全ではなく、本番環境での使用には適していません。また、jwtSecretは必要ありません。

このスキーマは Dgraph での使用に適応されており、主要なスキーマに基づいています。

type Account {
  id: ID
  type: String
  provider: String @search(by: [hash])
  providerAccountId: String @search(by: [hash])
  refreshToken: String
  expires_at: Int64
  accessToken: String
  token_type: String
  refresh_token: String
  access_token: String
  scope: String
  id_token: String
  session_state: String
  user: User @hasInverse(field: "accounts")
}
type Session {
  id: ID
  expires: DateTime
  sessionToken: String @search(by: [hash])
  user: User @hasInverse(field: "sessions")
}
type User {
  id: ID
  name: String
  email: String @search(by: [hash])
  emailVerified: DateTime
  image: String
  accounts: [Account] @hasInverse(field: "user")
  sessions: [Session] @hasInverse(field: "user")
}
 
type VerificationToken {
  id: ID
  identifier: String @search(by: [hash])
  token: String @search(by: [hash])
  expires: DateTime
}

安全なスキーマ

本番環境へのデプロイでは、next-auth が使用する型へのアクセスを制限する必要があります。Dgraph で使用される主なアクセス制御の形式は、スキーマ内の型と併用される @auth ディレクティブです。

type Account
  @auth(
    delete: { rule: "{$nextAuth: { eq: true } }" }
    add: { rule: "{$nextAuth: { eq: true } }" }
    query: { rule: "{$nextAuth: { eq: true } }" }
    update: { rule: "{$nextAuth: { eq: true } }" }
  ) {
  id: ID
  type: String
  provider: String @search(by: [hash])
  providerAccountId: String @search(by: [hash])
  refreshToken: String
  expires_at: Int64
  accessToken: String
  token_type: String
  refresh_token: String
  access_token: String
  scope: String
  id_token: String
  session_state: String
  user: User @hasInverse(field: "accounts")
}
type Session
  @auth(
    delete: { rule: "{$nextAuth: { eq: true } }" }
    add: { rule: "{$nextAuth: { eq: true } }" }
    query: { rule: "{$nextAuth: { eq: true } }" }
    update: { rule: "{$nextAuth: { eq: true } }" }
  ) {
  id: ID
  expires: DateTime
  sessionToken: String @search(by: [hash])
  user: User @hasInverse(field: "sessions")
}
type User
  @auth(
    query: {
      or: [
        {
          rule: """
          query ($userId: String!) {queryUser(filter: { id: { eq: $userId } } ) {id}}
          """
        }
        { rule: "{$nextAuth: { eq: true } }" }
      ]
    }
    delete: { rule: "{$nextAuth: { eq: true } }" }
    add: { rule: "{$nextAuth: { eq: true } }" }
    update: {
      or: [
        {
          rule: """
          query ($userId: String!) {queryUser(filter: { id: { eq: $userId } } ) {id}}
          """
        }
        { rule: "{$nextAuth: { eq: true } }" }
      ]
    }
  ) {
  id: ID
  name: String
  email: String @search(by: [hash])
  emailVerified: DateTime
  image: String
  accounts: [Account] @hasInverse(field: "user")
  sessions: [Session] @hasInverse(field: "user")
}
 
type VerificationToken
  @auth(
    delete: { rule: "{$nextAuth: { eq: true } }" }
    add: { rule: "{$nextAuth: { eq: true } }" }
    query: { rule: "{$nextAuth: { eq: true } }" }
    update: { rule: "{$nextAuth: { eq: true } }" }
  ) {
  id: ID
  identifier: String @search(by: [hash])
  token: String @search(by: [hash])
  expires: DateTime
}
 
# Dgraph.Authorization {"VerificationKey":"<YOUR JWT SECRET HERE>","Header":"<YOUR AUTH HEADER HERE>","Namespace":"<YOUR CUSTOM NAMESPACE HERE>","Algo":"HS256"}

Dgraph.Authorization

GraphQL バックエンドを保護するには、スキーマの下部に Dgraph.Authorization オブジェクトを定義し、authHeaderjwtSecret の値を DgraphClient に提供します。

# Dgraph.Authorization {"VerificationKey":"<YOUR JWT SECRET HERE>","Header":"<YOUR AUTH HEADER HERE>","Namespace":"YOUR CUSTOM NAMESPACE HERE","Algo":"HS256"}

VerificationKey と jwtSecret

これは、JWT の署名に使用されるキーです。例:process.env.SECRET または process.env.APP_SECRET

Header と authHeader

Header は、dgraph サーバーへの着信リクエストのヘッダー内にある JWT を Dgraph がどこで検索するかを指示します。スキーマファイルの下部に設定する必要があります。このヘッダーは、DgraphClient をインスタンス化するときに提供する authHeader プロパティと同じです。

nextAuth シークレット

$nextAuth シークレットは、jwtSecret を使用して安全に生成され、DgraphAdapter によって挿入されます。これにより、システム内で行われた匿名ユーザーのリクエスト (例:ログイン、登録) に対して JWT DgraphClient との安全なインタラクションが可能になります。これにより、next-auth に必要なすべての認証タイプと安全にインタラクションできます.安全なスキーマで定義されている各タイプの各認証ルールに指定する必要があります。

type VerificationRequest
  @auth(
    delete: { rule: "{$nextAuth: { eq: true } }" },
    add: { rule: "{$nextAuth: { eq: true } }" },
    query: { rule: "{$nextAuth: { eq: true } }" },
    update: { rule: "{$nextAuth: { eq: true } }" }
  ) {
}

JWT セッションと @auth ディレクティブ

Dgraph は HS256 または RS256 アルゴリズムのみで動作します。セッション JWT を使用して dgraph データベースと安全にインタラクションするには、デフォルトのアルゴリズムが HS512 であるため、next-auth の encode 関数と decode 関数をカスタマイズする必要があります。RBAC ロジックを実装する場合、ロールを使用して JWT をさらにカスタマイズできます。

./auth.js
import NextAuth from "next-auth"
import * as jwt from "jsonwebtoken"
 
export const { handlers, auth, signIn, signOut } = NextAuth({
  session: {
    strategy: "jwt",
  },
  jwt: {
    secret: process.env.SECRET,
    encode: async ({ secret, token }) => {
      return jwt.sign({ ...token, userId: token.id }, secret, {
        algorithm: "HS256",
        expiresIn: 30 * 24 * 60 * 60, // 30 days
      })
    },
    decode: async ({ secret, token }) => {
      return jwt.verify(token, secret, { algorithms: ["HS256"] })
    },
  },
})

スキーマで Dgraph.Authorization が定義され、JWT 設定が設定されると、スキーマのすべての部分に@auth ルールを定義できます。

Auth.js © Balázs Orbánおよびチーム -

2024