# accounts-js and Apollo Serverを使ったEメールとパスワードでの認証

個人的にGraphQLは、、

GraphQLが生まれた背景を紹介しているドキュメンタリーを日本語でまとめてみたり『GraphQL: The Documentary』をYoutubeで観ました | ヨシダレッド

Prismaが提供しているHow to GraphQLというチュートリアルをコンプリートしてみたりHOW TO GRAPHQLでGraphQLの勉強をはじめました | ヨシダレッド

何かと気にはなっているけど、そこまで使い倒すというところまではいってない、、といった感じなのですが、

たまたまAplloのサイトを訪れたら、Email & password authentication with accounts-js and Apollo Serverなんていう面白そうなブログ記事をみかけて、せっかくなのでやってみようかな、と。

このブログを書いてるのは @leopradelさん。

# accounts-jsとは

accounts-jsは、フルスタックなJavascriptのauthentication&アカウントマネージメントライブラリでREST APIでもGraphQLでも使えるみたいで、database agnostic(データベースによらない)ものだそうです。

とはいえ、GitHubのページみると、MongoかTypeormかRedis(セッションだけ)って書いてあるんだけど、MySQLとかPostgreSQLはTypeormを使いなさいってことなのかな。

accounts

このブログの内容を最後まで実施すると、新しいユーザーのサインアップや、情報を保護するための制限としてのユーザーログインおよび認証をすることができるようになる、と。

# nodeプロジェクトのセットアップ

プロジェクトのディレクトリを作って、そこにcdして、npm init。全てデフォルトのまま。

$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (accounts-js-server) 
version: (1.0.0) 
description: 
entry point: (index.js) 
test command: 
git repository: 
keywords: 
author: 
license: (ISC) 
About to write to /Users/eijishinohara/accounts-js-server/package.json:

{
  "name": "accounts-js-server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

続いて、Apollo ServerとGraphQLのインストール。

$ npm install apollo-server graphql

> core-js@3.6.5 postinstall /Users/eijishinohara/accounts-js-server/node_modules/core-js
> node -e "try{require('./postinstall')}catch(e){}"

Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library!

The project needs your help! Please consider supporting of core-js on Open Collective or Patreon: 
> https://opencollective.com/core-js 
> https://www.patreon.com/zloirock 

Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -)


> @apollo/protobufjs@1.0.4 postinstall /Users/eijishinohara/accounts-js-server/node_modules/@apollo/protobufjs
> node scripts/postinstall

npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN graphql-subscriptions@1.1.0 requires a peer of graphql@^0.10.5 || ^0.11.3 || ^0.12.0 || ^0.13.0 || ^14.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN graphql-tag@2.10.3 requires a peer of graphql@^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN subscriptions-transport-ws@0.9.16 requires a peer of graphql@^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.1 || ^14.0.2 but none is installed. You must install peer dependencies yourself.
npm WARN graphql-upload@8.1.0 requires a peer of graphql@0.13.1 - 14 but none is installed. You must install peer dependencies yourself.
npm WARN apollo-graphql@0.4.5 requires a peer of graphql@^14.2.1 but none is installed. You must install peer dependencies yourself.
npm WARN accounts-js-server@1.0.0 No description
npm WARN accounts-js-server@1.0.0 No repository field.

+ graphql@15.1.0
+ apollo-server@2.15.0
added 175 packages from 221 contributors and audited 175 packages in 7.087s

14 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities



   ╭────────────────────────────────────────────────────────────────╮
   │                                                                │
   │      New minor version of npm available! 6.13.4 → 6.14.5       │
   │   Changelog: https://github.com/npm/cli/releases/tag/v6.14.5   │
   │               Run npm install -g npm to update!                │
   │                                                                │
   ╰────────────────────────────────────────────────────────────────╯

VS Codeでディレクトリを開いて、index.jsを作成。Apolloサーバーが起動できる感じ。

const { ApolloServer, gql } = require('apollo-server');

const typeDefs = gql`
  type Query {
    # This query will be protected so only authenticated users can access it
    sensitiveInformation: String
  }
`;

const resolvers = {
  Query: {
    sensitiveInformation: () => 'Sensitive info',
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

// The `listen` method launches a web server.
server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});

node index.jsを叩いて👇のようにロケットと4000番ポートでリスンしてる感じならOK。

$ node index.js
🚀  Server ready at http://localhost:4000/

# accounts-jsのセットアップ

npmでMongoDBをaccount-jsで使う用のセットアップをしていきます。

a$ npm install @accounts/mongo mongoose
npm WARN apollo-graphql@0.4.5 requires a peer of graphql@^14.2.1 but none is installed. You must install peer dependencies yourself.
npm WARN graphql-subscriptions@1.1.0 requires a peer of graphql@^0.10.5 || ^0.11.3 || ^0.12.0 || ^0.13.0 || ^14.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN graphql-tag@2.10.3 requires a peer of graphql@^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN graphql-upload@8.1.0 requires a peer of graphql@0.13.1 - 14 but none is installed. You must install peer dependencies yourself.
npm WARN subscriptions-transport-ws@0.9.16 requires a peer of graphql@^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.1 || ^14.0.2 but none is installed. You must install peer dependencies yourself.
npm WARN accounts-js-server@1.0.0 No description
npm WARN accounts-js-server@1.0.0 No repository field.

+ mongoose@5.9.19
+ @accounts/mongo@0.27.0
added 36 packages from 23 contributors and audited 211 packages in 4.999s

15 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

そして、index.jsにそのまま👇のコードを貼り付けていきます。(本来なら複数のファイルにするところだけど、簡素化のため)

const mongoose = require('mongoose');
const { Mongo } = require('@accounts/mongo');

// We connect mongoose to our local mongodb database
mongoose.connect('mongodb://localhost:27017/accounts-js-server', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

// We tell accounts-js to use the mongo connection
const accountsMongo = new Mongo(mongoose.connection);

っていうか、MongoDBはローカルで動いてなきゃダメなんじゃん、っていう。笑

brew install mongodb-communityしたらエラーになっちゃった…👇

〜略〜
Error: No previously deleted formula found.
==> Searching for similarly named formulae...
Error: No similarly named formulae found.
==> Searching taps...
==> Searching taps on GitHub...
Error: No formulae found in taps.
$ echo $?
1

brew tap してあげて、、、

 brew tap mongodb/brew
==> Tapping mongodb/brew
Cloning into '/usr/local/Homebrew/Library/Taps/mongodb/homebrew-brew'...
remote: Enumerating objects: 81, done.
remote: Counting objects: 100% (81/81), done.
remote: Compressing objects: 100% (70/70), done.
remote: Total 280 (delta 32), reused 25 (delta 11), pack-reused 199
Receiving objects: 100% (280/280), 60.66 KiB | 388.00 KiB/s, done.
Resolving deltas: 100% (124/124), done.
Tapped 9 formulae (36 files, 119.8KB).

MongoDBをインストールできました。

$ brew install mongodb-community
==> Installing mongodb-community from mongodb/brew
==> Downloading https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-4.2.8.tgz
######################################################################## 100.0%
==> Caveats
To have launchd start mongodb/brew/mongodb-community now and restart at login:
  brew services start mongodb/brew/mongodb-community
Or, if you don't want/need a background service you can just run:
  mongod --config /usr/local/etc/mongod.conf
==> Summary
🍺  /usr/local/Cellar/mongodb-community/4.2.8: 21 files, 306.3MB, built in 3 seconds

mongodコマンド叩けるようになったよ、と。

$ mongod --version
db version v4.2.8
git version: 43d25964249164d76d5e04dd6cf38f6111e21f5f
allocator: system
modules: none
build environment:
    distarch: x86_64
    target_arch: x86_64

そして、ようやくMongoDB起動完了👇

$ mongod --config /usr/local/etc/mongod.conf

mongoコマンドで接続できた!

$ mongo
MongoDB shell version v4.2.8
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("7d7fc036-2fe4-463e-abd1-bb13a2b8a9b5") }
MongoDB server version: 4.2.8
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
	http://docs.mongodb.org/
Questions? Try the support group
	http://groups.google.com/group/mongodb-user
Server has startup warnings: 
2020-06-18T19:52:18.624+0900 I  CONTROL  [initandlisten] 
2020-06-18T19:52:18.624+0900 I  CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2020-06-18T19:52:18.624+0900 I  CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2020-06-18T19:52:18.624+0900 I  CONTROL  [initandlisten] 
---
Enable MongoDB's free cloud-based monitoring service, which will then receive and display
metrics about your deployment (disk utilization, CPU, operation statistics, etc).

The monitoring data will be available on a MongoDB website with a unique URL accessible to you
and anyone you share the URL with. MongoDB may use this information to make product
improvements and to suggest MongoDB products and deployment options to you.

To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---

> 

そして、accounts-jsサーバーの依存ライブラリをインストール

  • @accounts/server は accounts-js のcore dependency
  • @accounts/password は、その名の通りパスワードサービスでemail+passwordで認証できるようにしてくれる
$ npm install @accounts/server @accounts/password
npm WARN apollo-graphql@0.4.5 requires a peer of graphql@^14.2.1 but none is installed. You must install peer dependencies yourself.
npm WARN graphql-subscriptions@1.1.0 requires a peer of graphql@^0.10.5 || ^0.11.3 || ^0.12.0 || ^0.13.0 || ^14.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN graphql-tag@2.10.3 requires a peer of graphql@^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN graphql-upload@8.1.0 requires a peer of graphql@0.13.1 - 14 but none is installed. You must install peer dependencies yourself.
npm WARN subscriptions-transport-ws@0.9.16 requires a peer of graphql@^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.1 || ^14.0.2 but none is installed. You must install peer dependencies yourself.
npm WARN @accounts/password@0.27.0 requires a peer of @accounts/server@^0.19.0 but none is installed. You must install peer dependencies yourself.
npm WARN accounts-js-server@1.0.0 No description
npm WARN accounts-js-server@1.0.0 No repository field.

+ @accounts/server@0.27.0
+ @accounts/password@0.27.0
added 27 packages from 44 contributors and audited 238 packages in 5.627s

15 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

ということで、このライブラリを組み込むコードを書いていきます。これもそのままindex.jsに追記です。

const { AccountsServer } = require('@accounts/server');
const { AccountsPassword } = require('@accounts/password');

const accountsPassword = new AccountsPassword({
  // You can customise the behavior of the password service by providing some options
});

const accountsServer = new AccountsServer(
  {
    // We link the mongo adapter we created in the previous step to the server
    db: accountsMongo,
    // Replace this value with a strong random secret
    tokenSecret: 'my-super-random-secret',
  },
  {
    // We pass a list of services to the server, in this example we just use the password service
    password: accountsPassword,
  }
);

次にGraphQL周りを整えていきます。

$ npm install @accounts/graphql-api @graphql-toolkit/schema-merging @graphql-modules/core
npm WARN deprecated @graphql-toolkit/common@0.10.7: GraphQL Toolkit is deprecated and merged into GraphQL Tools, so it will no longer get updates. Use GraphQL Tools instead to stay up-to-date! Check out https://www.graphql-tools.com/docs/migration-from-toolkit for migration and https://the-guild.dev/blog/graphql-tools-v6 for new changes.
npm WARN deprecated @graphql-toolkit/common@0.10.6: GraphQL Toolkit is deprecated and merged into GraphQL Tools, so it will no longer get updates. Use GraphQL Tools instead to stay up-to-date! Check out https://www.graphql-tools.com/docs/migration-from-toolkit for migration and https://the-guild.dev/blog/graphql-tools-v6 for new changes.
npm WARN @accounts/password@0.27.0 requires a peer of @accounts/server@^0.19.0 but none is installed. You must install peer dependencies yourself.
npm WARN apollo-graphql@0.4.5 requires a peer of graphql@^14.2.1 but none is installed. You must install peer dependencies yourself.
npm WARN graphql-subscriptions@1.1.0 requires a peer of graphql@^0.10.5 || ^0.11.3 || ^0.12.0 || ^0.13.0 || ^14.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN graphql-tag@2.10.3 requires a peer of graphql@^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN graphql-upload@8.1.0 requires a peer of graphql@0.13.1 - 14 but none is installed. You must install peer dependencies yourself.
npm WARN subscriptions-transport-ws@0.9.16 requires a peer of graphql@^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.1 || ^14.0.2 but none is installed. You must install peer dependencies yourself.
npm WARN @accounts/graphql-api@0.27.0 requires a peer of @accounts/password@^0.19.0 but none is installed. You must install peer dependencies yourself.
npm WARN @accounts/graphql-api@0.27.0 requires a peer of @accounts/server@^0.19.0 but none is installed. You must install peer dependencies yourself.
npm WARN @accounts/graphql-api@0.27.0 requires a peer of @accounts/types@^0.19.0 but none is installed. You must install peer dependencies yourself.
npm WARN @accounts/graphql-api@0.27.0 requires a peer of @graphql-modules/core@0.7.14 but none is installed. You must install peer dependencies yourself.
npm WARN @accounts/graphql-api@0.27.0 requires a peer of graphql-tools@^5.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN @graphql-modules/di@0.7.17 requires a peer of reflect-metadata@^0.1.12 but none is installed. You must install peer dependencies yourself.
npm WARN accounts-js-server@1.0.0 No description
npm WARN accounts-js-server@1.0.0 No repository field.

+ @graphql-toolkit/schema-merging@0.10.7
+ @accounts/graphql-api@0.27.0
+ @graphql-modules/core@0.7.17
added 35 packages from 13 contributors and audited 273 packages in 6.79s

17 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
  • @accounts/graphql-api コレでaccounts-jsが提供する全てのクエリとミューテーションがカバーされる
  • @graphql-toolkit/schema-merging スキーマのマージ用
  • @graphql-modules/core 内部的なGraphQLスキーマとリゾルバを管理するもの

👇これでアクセスできるようになるよ、と。

// Add makeExecutableSchema to the imported variables
const { ApolloServer, gql, makeExecutableSchema } = require('apollo-server');
const { mergeTypeDefs, mergeResolvers } = require('@graphql-toolkit/schema-merging');
const { AccountsModule } = require('@accounts/graphql-api');

// We generate the accounts-js GraphQL module
const accountsGraphQL = AccountsModule.forRoot({ accountsServer });

// A new schema is created combining our schema and the accounts-js schema
const schema = makeExecutableSchema({
  typeDefs: mergeTypeDefs([typeDefs, accountsGraphQL.typeDefs]),
  resolvers: mergeResolvers([accountsGraphQL.resolvers, resolvers]),
  schemaDirectives: {
    ...accountsGraphQL.schemaDirectives,
  },
});

// When we instantiate our Apollo server we use the schema and context properties
const server = new ApolloServer({
  schema,
  context: accountsGraphQL.context,
});

そして、ずっとindex.jsへの追記追記でやってきたのが、なんか既にそれ宣言されてっぞ、みたいなエラーが出るとおもったら、、、

$ node index.js
/Users/eijishinohara/accounts-js-server/index.js:56
const { ApolloServer, gql, makeExecutableSchema } = require('apollo-server');
        ^
SyntaxError: Identifier 'ApolloServer' has already been declared
    at Module._compile (internal/modules/cjs/loader.js:892:18)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)
    at Module.load (internal/modules/cjs/loader.js:812:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1025:10)
    at internal/main/run_main_module.js:17:11

👇がキレイにした版ですよ、と。まぁ、そりゃそうだよねって話で。笑

const { ApolloServer, gql, makeExecutableSchema } = require('apollo-server');
const mongoose = require('mongoose');
const { Mongo } = require('@accounts/mongo');
const { mergeTypeDefs, mergeResolvers } = require('@graphql-toolkit/schema-merging');
const { AccountsServer } = require('@accounts/server');
const { AccountsPassword } = require('@accounts/password');
const { AccountsModule } = require('@accounts/graphql-api');

// We connect mongoose to our local mongodb database
mongoose.connect('mongodb://localhost:27017/accounts-js-server', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

const accountsMongo = new Mongo(mongoose.connection);

const typeDefs = gql`
  type Query {
    # This query will be protected so only authenticated users can access it
    sensitiveInformation: String
  }
`;

const resolvers = {
  Query: {
    sensitiveInformation: () => 'Sensitive info',
  },
};

const accountsPassword = new AccountsPassword({});

const accountsServer = new AccountsServer(
  {
    db: accountsMongo,
    // Replace this value with a strong secret
    tokenSecret: 'my-super-random-secret',
  },
  {
    password: accountsPassword,
  }
);

// We generate the accounts-js GraphQL module
const accountsGraphQL = AccountsModule.forRoot({ accountsServer });

// A new schema is created combining our schema and the accounts-js schema
const schema = makeExecutableSchema({
  typeDefs: mergeTypeDefs([typeDefs, accountsGraphQL.typeDefs]),
  resolvers: mergeResolvers([accountsGraphQL.resolvers, resolvers]),
  schemaDirectives: {
    ...accountsGraphQL.schemaDirectives,
  },
});

const server = new ApolloServer({ schema, context: accountsGraphQL.context });

// The `listen` method launches a web server.
server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});

ってことで、logalhost:4000にアクセスすると👇こんなのが。

local

# 最初のユーザーを作っていきます

👇のミューテーションを叩いたら、

mutation {
  createUser(
    user: { email: "john.doe@john.com", password: "superSecurePassword" }
  )
}

👇なんかエラーでてますがな…

{
  "error": {
    "errors": [
      {
        "message": "Field \"createUser\" of type \"CreateUserResult\" must have a selection of subfields. Did you mean \"createUser { ... }\"?",
        "locations": [
          {
            "line": 2,
            "column": 3
          }
        ],
        "extensions": {
          "code": "GRAPHQL_VALIDATION_FAILED",
〜略〜

ってか、これ、CreateUserResultのサブセットも全部書き出しなさいってことですよね…汗

ってことで、いちいち全部書きだしましたよ、と。。

mutation {
  createUser(
    user: { username: "john", email: "john.doe@john.com", password: "superSecurePassword" }
  ){
    userId
    loginResult{
      sessionId
      tokens{
        refreshToken
        accessToken
      }
      user{
        id
        emails{
          address
          verified
        }
        username
      }
    }
  }
}

そしたら、、、👇これってユーザー出来てるのかな?w

{
  "data": {
    "createUser": {
      "userId": null,
      "loginResult": null
    }
  }
}

でもサーバーはエラーとかうんともすんとも言ってないし、MongoDBには何のCollectionもない…。

ってか、たしかにMongoDBにデータベースとか作った記憶がない…笑

ってことで、、

> use accounts-js-server
switched to db accounts-js-server

で、mutation叩いたら👇なんか出来てる

> show collections
users

👇アレ、、ちゃんとユーザー作成できてたってことか。。。

> db.users.find();
{ "_id" : ObjectId("5eeb51d96a649fdc4edefe3c"), "services" : { "password" : { "bcrypt" : "$2a$10$DsH3Y5uVCCKxMa1nM06MiuTIkuJ7OpveFxohlOnva.mwse774IzPG" } }, "createdAt" : 1592480217634, "updatedAt" : 1592480217634, "username" : "john", "emails" : [ { "address" : "john.doe@john.com", "verified" : false } ] }

では、別のユーザー作成mutationをカマしてみる

mutation {
  createUser(
    user: { username: "eiji", email: "eiji@eijiiji.com", password: "password" }
  ){
    userId
    loginResult{
      sessionId
      tokens{
        refreshToken
        accessToken
      }
      user{
        id
        emails{
          address
          verified
        }
        username
      }
    }
  }
}

相変わらず👇だけど、、

{
  "data": {
    "createUser": {
      "userId": null,
      "loginResult": null
    }
  }
}

👇MongoDBにデータは入ってる

> db.users.find();
{ "_id" : ObjectId("5eeb51d96a649fdc4edefe3c"), "services" : { "password" : { "bcrypt" : "$2a$10$DsH3Y5uVCCKxMa1nM06MiuTIkuJ7OpveFxohlOnva.mwse774IzPG" } }, "createdAt" : 1592480217634, "updatedAt" : 1592480217634, "username" : "john", "emails" : [ { "address" : "john.doe@john.com", "verified" : false } ] }
{ "_id" : ObjectId("5eeb54136a649fdc4edefe3d"), "services" : { "password" : { "bcrypt" : "$2a$10$NpOFASvvZggyrjjZSmr1KOkbflsiEmoJ1V1AFCGC7CCUOZlzutTki" } }, "createdAt" : 1592480787135, "updatedAt" : 1592480787135, "username" : "eiji", "emails" : [ { "address" : "eiji@eijiiji.com", "verified" : false } ] }

ってことで、ログインしていきます。

mutation {
  authenticate(
    serviceName: "password"
    params: {
      user: { email: "john.doe@john.com" }
      password: "superSecurePassword"
    }
  ) {
    sessionId
    tokens {
      accessToken
      refreshToken
    }
  }
}

👇くぅー、できた!

auth

👇もう一個のユーザーでもイケた 😃

mutation {
  authenticate(
    serviceName: "password"
    params: {
      user: { email: "eiji@eijiiji.com" }
      password: "password"
    }
  ) {
    sessionId
    tokens {
      accessToken
      refreshToken
    }
  }
}

ここで返ってきてるのは

  • セッションID
  • short livedなJWT accessToken (ユーザー認証用)
  • long lived refreshToken (accessTokenがexpireした時に新しく取得する用)

# クエリの保護

続いて、ログインが出来たユーザーにだけ発行できる sensitiveInformation というクエリを試してきます。

accounts-jsでは @auth というディレクティブがあって、それでプライベートなクエリを保護する、と。

該当するのはindex.jsの👇のところで、sensitiveInformation: Stringの後に@authを付けてあげます。

const typeDefs = gql`
  type Query {
    # We add the @auth directive
    sensitiveInformation: String @auth
  }
`;

これで、何も考えずに叩くとエラーになるけど、先ほどのリクエストのヘッダーに入ってるアクセストークンを使えば大丈夫とのこと。

ってことで、もう一度authenticateミューテーションを叩いて、accessTokenを取得して、左下のHTTP HEADERSのところに貼り付けます。(Bearer ってのはプレフィックス)

{
  "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7InRva2VuIjoiOTBlOGE0MTRmYWQ2M2ViN2ZiM2E0MDVhOTM3ZDM5N2Q5YmY4OWQ2Nzg5MzRmOTJiNDVjMTFlYWYwY2UwYzYzNzgxMjBjNGEwMmVhNzFhMzdlNzNlZTYiLCJpc0ltcGVyc29uYXRlZCI6ZmFsc2UsInVzZXJJZCI6IjVlZWI1NDEzNmE2NDlmZGM0ZWRlZmUzZCJ9LCJpYXQiOjE1OTI0ODE1MzQsImV4cCI6MTU5MjQ4NjkzNH0.1yVVQ6JOqIz6a6aa3rXdgwRcXftjiFnQNOHajw2OOf8"
}

👇確かに、Sensitive infoってのが返ってきました。

sensitive

HTTP HEADERSに何も入れなければ、Unautorizedエラーになりました!

unauth


コレはお手軽だし良いなぁ。

このエントリーをはてなブックマークに追加

Algolia検索からの流入のみConversionボタン表示