6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Hasura+Auth0で認証機能を実装する記事

Posted at

はじめに

この記事は公式チュートリアルを参考に認証機能を実装する記事です。公式チュートリアルもかなり充実しているのですが、Auth0周りはつまづきポイントが多かったので、これの副読書として、認証機能周りに着目して解説していきたいと思います!

Hasuraとは?

HasuraとはHasura社の提供するOSSです。たぶんBaaS(Backend As A Service)の1つです。立ち位置としてはDBのラッパー?という感じで、DBにHasuraを接続するだけでGraphQLの書き方でCRUD操作ができます。その他にRemote SchemeやHasura Actionsなど、他APIと連携するための仕組みが提供されています。

Auth0とは?

Auth0とはAuth0社の提供する認証プラットフォームサービスです。いわゆるIDaaS(Identity as a Service)の1つです。カスタマイズ性が高く、セキュリティレベルの高さが特徴で、認証時にHasuraに認証したユーザーの情報をクエリとして投げるというように任意の処理を実行することができます。

本編

早速認証機能を実装していく!

下準備

認証機能の実装方法の説明に集中するためにHasuraの基本的な操作や権限の詳細については省略しています。ここの部分は公式チュートリアルを触ってみるとわかりやすいです。

認証機能を実装するまえに、Hasuraのプロジェクトを作成し、認証したユーザーのデータを格納するusersテーブルを作成します。このリンクをクリックして「Get Started in 30 seconds」をクリックし、プロジェクトを作成してください。コンソール画面を開けたらData>Create New Databaseをクリックしてください。そうすると以下のような画面になります。

スクリーンショット 2023-03-23 22.38.44.png

公式チュートリアルではHerokuを使用していますが、有料化に伴い、無料枠のあるNeonというBaaSのサービスに置き換えられました。「Connect Neon Database」をクリックし、HasuraにPostgreSQLに接続します。しばらく時間がかかります。

DBが接続に成功したら下記のような画面に勝手に変わります。そうしたら、「Create Table」をクリックしてください。

スクリーンショット 2023-03-23 22.42.03.png

早速、Auth0で認証したユーザーのデータを書き込むためのテーブルを作成します。下記のようにカラムを設定してください。idはAuth0の方で認証時に生成されるのですが、これが文字列なのでIntegerなどにしないように気をつけてくだだい。

設定できたら、下の方にスクロールして「Add Table」をクリックしてください。

スクリーンショット 2023-03-23 22.50.45.png

次にテーブルを閲覧できるユーザーを制限します。Permissionsタブをクリックしてください。その後、userロールを追加し、select列のところをクリックします。

スクリーンショット 2023-03-23 22.53.35.png

Row select permissions>With custom checkに以下の内容を入力します。

{"id": {"_eq": "X-Hasura-User-Id"}}

スクリーンショット 2023-03-23 22.55.23.png

上記の設定により、認証した際に生成されるJWTに埋め込まれているのX-Hasura-User-Idとidが一致しない行のデータは表示されなくなります。JWTについては下記の記事を参考にしてください。

列レベルの権限を以下のように設定します。

スクリーンショット 2023-03-23 23.00.55.png

以上で下準備完了です!

Auth0アプリを作成する

ここからAuth0の設定を進めていきます。
Auth0ダッシューボードにアクセスします。

左上の「dev-*******」みたいな名前の場所をクリックして「Create Tenant」をクリックします。

スクリーンショット 2023-03-17 9.15.28.png

「Tenant Domain」を適当に設定します。ここでは「hasura-de-auth0-tsukauyo」とします。

スクリーンショット 2023-03-17 9.17.06.png

テナントドメインを入力したら、「Create」をクリックします。

次にアプリケーションを作成します。左下の「>>」をクリックして、「Applications」のプルダウンを開き、「Applications」をクリックします。

スクリーンショット 2023-03-17 9.20.41.png

「Create Application」をクリックします。

スクリーンショット 2023-03-17 9.22.10.png

名前を「My App」とし、「Single Page Web Application」を選択し、「Create」をクリックしてください。

スクリーンショット 2023-03-17 9.26.36.png

これでアプリケーションの作成は完了です。次にAPIを作成します。先程と同様に「>>」をクリックし、「Applications>APIs」をクリックしてください。もしくはここをクリックしてください。

「Create API」をクリックし、Nameに「hasura」とIdentifierに「https://hasura.io/learn」を入力します。Identifierはなんでもいいです。入

スクリーンショット 2023-03-17 9.34.40.png

力したら「Create」をクリックしてください。

カスタムJWTクレームのルール

クライアントからのクエリをHasuraで受け取ったとき、ユーザーのIDやロールなどの情報が埋め込まれたJWTが必要になります。ここではJWTにどのようなデータを埋め込むかを設定します。

左のメニューから「Auth Pipeline>Rules」を選択します。その後、「Create」をクリックし、「Empty rule」をクリックします。Nameに「hasura-jwt-claims」と入力し、下記の内容を書き込みます。

function (user, context, callback) {
  const namespace = "https://hasura.io/jwt/claims";
  context.accessToken[namespace] =
    {
      'x-hasura-default-role': 'user',
      // do some custom logic to decide allowed roles
      'x-hasura-allowed-roles': ['user'],
      'x-hasura-user-id': user.user_id
    };
  callback(null, user, context);
}

スクリーンショット 2023-03-17 9.47.37.png

JWTに「x-hasura-default-role」「x-hasura-allowed-roles」「x-hasura-user-id」を埋め込むように設定しています。

HasuraをAuth0に接続する

ここからAuth0用の公開キーを生成します。
「Select Provider」に「Auth0」、「Enter Auth0 Domain Name」にテナントドメインを入力してください。そして、「GENERATE CONFIG」をクリックすると下記のように公開キーが表示されます。

スクリーンショット 2023-03-23 18.54.03.png

公開キーをHasuraの環境変数に登録します。Hasuraのコンソール画面の右上にある「SETTINGS」のとなりのボタンをクリックします。

スクリーンショット 2023-03-23 18.51.49.png

「Env vars」をクリックし、「New Env Var」をクリックします。その後、HASURA_GRAPHQL_JWT_SECRETという変数を作り、先程生成した公開キーを入力します。

スクリーンショット 2023-03-23 18.55.23.png

入力できたら「Add」を押します。

Rulesでユーザーを同期する

Auth0でユーザー認証が行われた際に認証したユーザーの情報をHasuraのuserテーブルに登録する必要があります。この処理を書いていきます。

Auth Pipeline>Rulesをクリックし、「Crate」ボタンをクリックしてください。「Empty rule」を選択し、下記のコードを入力していきます。

function (user, context, callback) {
  const userId = user.user_id;
  const nickname = user.nickname;

  const admin_secret = "xxxxxx";
  const url = "https://ready-panda-91.hasura.app/v1/graphql";
  const query = `mutation($userId: String!, $nickname: String) {
    insert_users(objects: [{
      id: $userId, name: $nickname, last_seen: "now()"
    }], on_conflict: {constraint: users_pkey, update_columns: [last_seen, name]}
    ) {
      affected_rows
    }
  }`;

  const variables = { "userId": userId, "nickname": nickname };

  request.post({
      url: url,
      headers: {'content-type' : 'application/json', 'x-hasura-admin-secret': admin_secret},
      body: JSON.stringify({
        query: query,
        variables: variables
      })
  }, function(error, response, body){
       console.log(body);
       callback(null, user, context);
  });
}

このときadmin_secreturlの値を適した値に変更してください。
admin_secretにはHasura側の環境変数HASURA_GRAPHQL_ADMIN_SECRETの値を入力してください。

urlにはコンソール上のURLを入力してください。

スクリーンショット 2023-03-23 19.15.48.png

入力できたらSave Changesで保存してください。この段階で「Save And Try」をクリックすると下記のようなユーザーが登録されていると思います。

スクリーンショット 2023-03-23 23.34.17.png

うまく行かない場合は「Save And Install Real-time Logs」をクリックし、デバッグ用のAuth0拡張機能を入れてください。「Installed Extentions」にある「Real-time Webtask Logs」をクリックし、Auth0との連携を有効にした上で再度「Save And Try」をクリックしてみてください。

成功している場合は下記のような出力が得られます。
スクリーンショット 2023-03-23 20.30.33.png

失敗している場合は失敗理由が表示されていると思うのでそれを参考にコードやこれまでの設定を見直してみてください。

例として、admin_secretが間違っている場合は下記のメッセージが得られます。

スクリーンショット 2023-03-23 20.31.43.png

Auth0トークンで試す

実際にAuth0で認証し、JWTを受け取り、Hasuraにクエリを投げてみます。
はじめにデバッグ用のツールである「Auth0 Authentication API Debugger」を「Extentions」をクリックしてインストールします。

スクリーンショット 2023-03-23 19.39.40.png

インストール後、「Extentions>Installed Extentions」から「Auth0 Authentication API Debugger」をクリックし、Auth0との連携を許可します。すると以下のような画面が表示されます。

スクリーンショット 2023-03-23 19.48.54.png

少し下にスクロールすると「Callback URL」という項目があると思います。これをコピーして「Applications>Applications>My App>Settings」の「Allowed Callback URLs」にペーストしてください。

スクリーンショット 2023-03-23 19.51.12.png

その後、画面を下までスクロールし、「Save Changes」をクリックしてください。

次に拡張機能の画面に戻り、「OAuth2 / OIDC」タブに切り替え、下の方にスクロールし、AudienceにApplication>APIsで設定したIdentifierの値を入力して、右のトグルスイッチをオンにしてください。

スクリーンショット 2023-03-23 19.53.14.png
スクリーンショット 2023-03-23 19.55.05.png

その後、「OAuth2 / OIDC」タブの「OAUTH2 / OIDC LOGIN」ボタンを押してください。下記のような画面が出て来ると思います。

スクリーンショット 2023-03-23 20.07.45.png

認証し下記のような画面に遷移すれば成功です。

スクリーンショット 2023-03-23 20.08.40.png

下記のような画面に遷移する場合はAllowed Callback URLsが保存できていない可能性があります。

スクリーンショット 2023-03-23 20.33.05.png

実際にクエリを叩いてみる

「Hash Fragments」の「access_token」の値をコピーしてください。それをHasuraのコンソール画面のヘッダの部分に新しく「Authorization」という項目を追加し、「Bearer $access_tokenの値」としてください。

スクリーンショット 2023-03-24 0.15.28.png

この状態で下記のクエリを実行してください。

query {
    users {
        id
        name
        last_seen
    }
}

これで自身のデータだけを取得することができれば認証成功です!お疲れさまでした!

スクリーンショット 2023-03-24 0.20.50.png

終わりに

筆者はAuth0による認証機能の公式チュートリアルでつまづきまくっていたのでこの記事が誰かの参考になればと思います。Hasura自体はGraphQLやAPIの面倒な部分を代わりにやってくれる熱いサービスだと思いますので、この記事でHasuraに興味を持っていただけると幸いです。

普段はいんでぃーはっかーの集いというコミュニティで活動しています。質問がある方や個人開発仲間を探している方はぜひご参加ください!

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?