Apollo 서버와 Prisma를 사용한 JWT 인증
소개
본 기사에서는 GraphQL에서 JWT를 이용한 사용자 인증에 대해 테스트를 한 비망록입니다.
Prisma란?
GraphQL 서버(본 기사에서는 GraphQL 서버로서 Apollo를 이용)와 데이터베이스를 연결하는 ORM의 하나입니다.
ORM이란 다음과 같은 기능의 집합을 말합니다.
① 데이터베이스에서 데이터 검색
② 취득한 데이터를 오브젝트화한다
③ 데이터의 갱신·변경 등을 데이터베이스에 격납한다
참고 : 더 ORM을 사용할 수 있기를 원하기 때문에 검토했습니다.
JWT란?
JWT(Jot)는 JSON Web Token의 약자로, JSON 데이터에 서명하고 암호화하는 방법을 말합니다.
본 기사에서는 로그인 인증에 이용합니다.
자세한 내용은 여기
Prisma 설정
조속히 Prisma 설정으로 시작합니다 😊
$ mkdir jwt-Auth
$ cd jwt-Auth
$ npm init
$ npm install apollo-server graphql prisma-client-lib
$ npm install -g prisma
npm 설치가 완료되면 프로젝트에서 Prisma를 사용할 수 있도록 설정합니다.
$ prisma init
그대로 Docker를 사용하여 Prisma를 설정합니다.
? Set up a new Prisma server or deploy to an existing server?
❯ Create new database Set up a local database using Docker
? What kind of database do you want to deploy to?
❯ PostgreSQL PostgreSQL database
? Select the programming language for the generated Prisma client
❯ Prisma JavaScript Client
성공하면 아래와 같은 안내가 표시됩니다.
Created 3 new files:
prisma.yml Prisma service definition
datamodel.graphql GraphQL SDL-based datamodel (foundation for database)
docker-compose.yml Docker configuration file
Next steps:
1. Start your Prisma server: docker-compose up -d
2. Deploy your Prisma service: prisma deploy
3. Read more about Prisma server:
Docker 컨테이너 시작
Docker 컨테이너를 시작하기 전에 생성된 파일의 설정을 변경합니다.
①docker-compose.yml내의 중간 정도 있는, port에 관한 설정의 코멘트 아웃을 제외한다.
여기가 코멘트 아웃 된 상태라면 localhost에서 시작할 수 없습니다.
docker-compose.yml# Uncomment the next two lines to connect to your your database from outside the Docker environment, e.g. using a database GUI like Postico
ports:
- "5432:5432"
② datamodel.graphql을 다시 씁니다. 이 파일은 ORM으로 작동하는 데 필요한 파일의 원본입니다.
datamodel.graphqltype User {
id: ID! @id
name: String!
email: String! @unique
password: String!
}
③prisma.yml은 변경 불필요합니다만, 아래와 같이 됩니다.
prisma.ymlendpoint: http://localhost:4466
datamodel: datamodel.prisma
generate:
- generator: javascript-client
output: ./generated/prisma-client/
준비가 되면 방금 전의 「Next steps」의 안내에 따라 컨테이너를 기동시킵니다.
$ docker-compose up -d
$ prisma deploy
$ prisma generate
위의 명령을 성공적으로 실행하면 datamodel.prisma 파일에서 생성된 ORM 역할을 하는 데 필요한 파일이 만들어집니다.
아래와 같이 Prisma 인스턴스를 파일로 import하면 Query나 Mutation을 실행할 때 데이터베이스에 액세스할 수 있습니다.
const { prisma } = require('./generated/prisma-client')
Apollo 서버에 대한 코드 작성
Prisma 설정이 완료되면 GraphQL 서버로 Apollo를 사용할 준비를 할 것입니다. bcrypt는 암호 해시를 위해 사용하는 라이브러리입니다.
$ mkdir resolver
$ touch index.js schema.js resolver/Mutation.js
$ npm install bcrypt jsonwebtoken
먼저 스키마를 정의합니다.
schema.js
const {gql} = require('apollo-server');
const typeDefs = gql`
type Query {
users(query: String): [User!]!
}
type Mutation {
createUser(data: CreateUserInput!): AuthPayload!
login(data: LoginUserInput!): AuthPayload!
}
type AuthPayload {
token: String!
user: User!
}
input CreateUserInput {
name: String!
email: String!
password: String!
}
input LoginUserInput {
email: String!
password: String!
}
type User {
id: ID!
name: String!
email: String
password: String!
}
`
module.exports = typeDefs;
JWT와 bcrypt는 여기에서 이용하고 있습니다.
Prisma는 모든 해석기간에 공유되므로 세 번째 인수의 컨텍스트로 사용합니다.
Mutation.jsconst bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const Mutation = {
async createUser(parent, args, { prisma }, info) {
const { data: { email, name, password } } = args;
const newUser = await prisma.createUser({
email,
name,
// bcryptでパスワードをハッシュ化
password: bcrypt.hashSync(password, 3)
});
// サーバーがJWTトークンを発行
return {token : jwt.sign(newUser, "supersecret")};
},
async login(parent, args, { prisma }, info) {
const { data: { email, password } } = args;
// メールアドレスと照合
const [ signInUser ] = await prisma.users({
where: {
email
}
})
// console.log(signInUser) 該当ユーザーのid,name,email,passwordが格納されているオブジェクト
if (!signInUser) throw new Error('Unable to Login');
// 暗号化されたデータベース格納のパスワードと照合
const isMatch = bcrypt.compareSync(password, signInUser.password);
if (!isMatch) throw new Error('Unable to Login');
// 一致した場合、新しいユーザ認証トークンを戻り値として返す
return {token : jwt.sign(signInUser, "supersecret")};
},
}
module.exports = Mutation
마지막으로 Apollo 서버(GraphQL 서버)를 시작하는 설정 처리를 작성합니다.
index.jsconst { ApolloServer } = require('apollo-server');
const Mutation = require('./resolver/Mutation')
const typeDefs = require('./schema')
// datamodel.prismaファイルから生成されたPrismaインスタンス
const { prisma } = require('./generated/prisma-client')
const server = new ApolloServer({
typeDefs: typeDefs,
resolvers: {
Mutation
},
context: {
prisma
}
})
server.listen().then(({ url}) => {
console.log(`🚀 Server ready at ${url}`);
});
GraphQL IDE에서 테스트하기
GraphQL IDE를 사용하여 테스트합니다.
$ node index.js
🚀 Server ready at http://localhost:4000/
가입
IDE에서 name,email.password가 포함된 쿼리를 작성합니다.

JWT 토큰이 반환되었습니다.
로그인
이어서 로그인 확인입니다.
가입과 동일하게 email, password를 쿼리로 작성합니다.

가입 시와 같은 JWT 토큰이 돌아왔습니다!
성공입니다!
결론
이상, GraphQL에 있어서의 로그인 인증을 테스트해 보았습니다.
Prisma와 Docker를 통해 신속하게 환경을 만들 수 있었고 그 후에는 거의 의식하지 않고 코드를 작성할 수 있었던 것은 GraphQL의 강점이라고 느꼈습니다.
그럼 다시 😊
Reference
이 문제에 관하여(Apollo 서버와 Prisma를 사용한 JWT 인증), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/shotashimura/items/a59747e8ef987c89cc0c
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
$ mkdir jwt-Auth
$ cd jwt-Auth
$ npm init
$ npm install apollo-server graphql prisma-client-lib
$ npm install -g prisma
$ prisma init
? Set up a new Prisma server or deploy to an existing server?
❯ Create new database Set up a local database using Docker
? What kind of database do you want to deploy to?
❯ PostgreSQL PostgreSQL database
? Select the programming language for the generated Prisma client
❯ Prisma JavaScript Client
Created 3 new files:
prisma.yml Prisma service definition
datamodel.graphql GraphQL SDL-based datamodel (foundation for database)
docker-compose.yml Docker configuration file
Next steps:
1. Start your Prisma server: docker-compose up -d
2. Deploy your Prisma service: prisma deploy
3. Read more about Prisma server:
# Uncomment the next two lines to connect to your your database from outside the Docker environment, e.g. using a database GUI like Postico
ports:
- "5432:5432"
type User {
id: ID! @id
name: String!
email: String! @unique
password: String!
}
endpoint: http://localhost:4466
datamodel: datamodel.prisma
generate:
- generator: javascript-client
output: ./generated/prisma-client/
$ docker-compose up -d
$ prisma deploy
$ prisma generate
const { prisma } = require('./generated/prisma-client')
$ mkdir resolver
$ touch index.js schema.js resolver/Mutation.js
$ npm install bcrypt jsonwebtoken
const {gql} = require('apollo-server');
const typeDefs = gql`
type Query {
users(query: String): [User!]!
}
type Mutation {
createUser(data: CreateUserInput!): AuthPayload!
login(data: LoginUserInput!): AuthPayload!
}
type AuthPayload {
token: String!
user: User!
}
input CreateUserInput {
name: String!
email: String!
password: String!
}
input LoginUserInput {
email: String!
password: String!
}
type User {
id: ID!
name: String!
email: String
password: String!
}
`
module.exports = typeDefs;
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const Mutation = {
async createUser(parent, args, { prisma }, info) {
const { data: { email, name, password } } = args;
const newUser = await prisma.createUser({
email,
name,
// bcryptでパスワードをハッシュ化
password: bcrypt.hashSync(password, 3)
});
// サーバーがJWTトークンを発行
return {token : jwt.sign(newUser, "supersecret")};
},
async login(parent, args, { prisma }, info) {
const { data: { email, password } } = args;
// メールアドレスと照合
const [ signInUser ] = await prisma.users({
where: {
email
}
})
// console.log(signInUser) 該当ユーザーのid,name,email,passwordが格納されているオブジェクト
if (!signInUser) throw new Error('Unable to Login');
// 暗号化されたデータベース格納のパスワードと照合
const isMatch = bcrypt.compareSync(password, signInUser.password);
if (!isMatch) throw new Error('Unable to Login');
// 一致した場合、新しいユーザ認証トークンを戻り値として返す
return {token : jwt.sign(signInUser, "supersecret")};
},
}
module.exports = Mutation
const { ApolloServer } = require('apollo-server');
const Mutation = require('./resolver/Mutation')
const typeDefs = require('./schema')
// datamodel.prismaファイルから生成されたPrismaインスタンス
const { prisma } = require('./generated/prisma-client')
const server = new ApolloServer({
typeDefs: typeDefs,
resolvers: {
Mutation
},
context: {
prisma
}
})
server.listen().then(({ url}) => {
console.log(`🚀 Server ready at ${url}`);
});
$ node index.js
🚀 Server ready at http://localhost:4000/
Reference
이 문제에 관하여(Apollo 서버와 Prisma를 사용한 JWT 인증), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/shotashimura/items/a59747e8ef987c89cc0c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)