Skip to content
Migrating from NextAuth.js v4? Read our migration guide.

Dgraph Adapter

리소스

설정

설치

npm install @auth/dgraph-adapter

환경 변수

AUTH_DGRAPH_GRAPHQL_ENDPOINT=http://localhost: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,
    // 보안이 적용되지 않은 스키마를 사용 중이라면 다음 속성은 생략 가능
    authHeader: process.env.AUTH_HEADER, // 기본값: "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 지시자를 사용하는 것입니다.

Example_JYQNAyrsYBvgLQoT9sQSMr

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 객체를 정의하고, DgraphClient에 authHeaderjwtSecret 값을 제공해야 합니다.

# 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를 찾을 위치를 알려줍니다. 이 설정은 스키마 파일의 하단에 구성해야 합니다. 이 헤더는 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 알고리즘만 지원합니다. Dgraph 데이터베이스와 안전하게 상호작용하기 위해 JWT 세션을 사용하려면, 기본 알고리즘인 HS512 대신 next-auth의 encodedecode 함수를 커스터마이징해야 합니다. 또한, 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일
      })
    },
    decode: async ({ secret, token }) => {
      return jwt.verify(token, secret, { algorithms: ["HS256"] })
    },
  },
})

스키마에 Dgraph.Authorization을 정의하고 JWT 설정을 완료하면, 스키마의 각 부분에 대해 @auth 규칙을 정의할 수 있습니다.

Auth.js © Balázs Orbán and Team - 2025