はじめに
Hasuraを使っていて認証をするときにどうすればいいんだろうってなったので自分なりに記事にしておきます。
Hasuraとは
HasuraはPostgres上でGraphQLを簡単に扱うことのできるGraphQL Engineです。 コンソール上でスキーマの定義などが全て行えてすごい楽。 https://hasura.io/
Hasuraを準備する
Hasuraをデプロイ
- Hasura Docを開き、
Deploy to Herokuをクリックします
- 次にHerokuの画面が出てくるので適当なアプリ名を決めてデプロイ

テーブルを定義
デプロイが完了したらManage appからアプリの管理画面に飛ぶので右上のOpen appからHasuraのコンソールを開きます。
コンソールを開いたらヘッダーにあるDATAをクリックしてスキーマ定義のページに飛びます。
次にCreate Tableをクリックしてテーブルを定義をします。今回はUserがArticleを作成するときのことを想定します。Userはidとnameを文字列で持っていて、主キーはidです。
次にArticleはidとtitleとbody、そして作成したuserのidを持ち、主キーはidです。
また、ArticleとUserには親子関係が発生するので Foreign Keyを設定します。

Roleの作成
先ほど設定したTablesに対してRoleを作成し権限を付与します。 ここではすでにadminというRoleが作成されているのでuserとanonymousというRoleを追加で作成します。
anonymousの作成
anonymousは記事を見ることしかできないのでarticleのデータを一部を見ることに対してのみ権限を与えます。
左のTablesにあるarticleを開き、Permissionsタブを選択します。
そしてRoleのところにanonymousと入力し、selectのところのペンマークをクリックして下の画像のような設定を行います。
下の設定では、全ての列に対して中身を見ることを許すのでAllow role anonymous to select rows:の部分はWithout any checksを選択します。
また、articleの中身は公開してもよいのでToggle Allを選択します。
最後のaggregationに関しても今回は公開しても大丈夫なのでチェックをつけています。

userの作成
anonymousと同じようにuserのRoleも作成していきます。
userは自分の書いた記事は編集をすることができるのでarticleのinsertとupdate、deleteに対しては以下の設定をします。

{
"user_id":{
"_eq": "X-Hasura-User-Id"
}
}
この設定はarticleのuser_idがX-Hasura-User-Idと同一のときにpermissionを与えるというものです。selectに関してはanonymousのときと同じ設定で大丈夫です。
次にuserというRoleは自分自身の情報も編集できるので同じような設定をuserテーブルにも行います。
環境変数の設定
HasuraをデプロイしているHerokuのコンソールに移動し、Settingsを開きます. 次にConfig VarsのReveal Config Varsを押し、環境変数の設定を行います。
ここでは、HASURA_GRAPHQL_ADMIN_SECRETとHASURA_GRAPHQL_UNAUTHORIZED_ROLEという2つの環境変数を設定します.
HASURA_GRAPHQL_ADMIN_SECRET
あとで出てくるJWTモードを有効するために必要となります。 またこれを設定するとHasuraのコンソールにログインするときに入力が求められるようになります。
HASURA_GRAPHQL_UNAUTHORIZED_ROLE
エンドポイントにクエリを投げるときに、認証が行われていない場合はここに設定されたRoleの権限で許されていることが実行することができます。
今回は先ほど作ったanonymousというRoleをHASURA_GRAPHQL_UNAUTHORIZED_ROLEに設定しました。
また、HASURA_GRAPHQL_ADMIN_SECRETは今回xxxxxxxxにしていますがこれが漏れたら終わりなので出来る限りセキュアなものにしてください。
Auth0の準備
アプリケーションの作成
Auth0のダッシュボードに移動し、CREATE APPLICATIONから新規アプリケーションを作成します。
アプリケーションタイプに関しては自分の作りたいアプリにあったものを選択

Roleの作成
Auth0のサイドバーからUsers & Rolesをクリックし、Rolesを選択する. その後CREATE ROLEからRoleを作成していきます。今回はadminとuserというRoleを作成します。

Ruleの作成
今回はuserを作成するためのRule(insert-user)と認証を行いRoleを返すためのRule(hasura-jwt-claim)を作成します。
RuleはサイドバーでRulesをクリックし、CREATE RULEから作成します。templateはempty ruleを選択します。
insert-user
このRuleではユーザ-がAuth0でログインまたはサインアップを行ったときに、Hasuraにクエリを投げてユーザ登録または更新を行います。

function (user, context, callback) {
const userId = user.user_id;
const username = user.nickname;
const admin_secret = "[YOUR_ADMIN_SECRET_KEY]";
const url = "https://[YOUR_APP_NAME].herokuapp.com/v1/graphql";
request.post({
headers: {'content-type' : 'application/json', 'x-hasura-admin-secret': admin_secret},
url: url,
body: `{\"query\":\"mutation($userId: String!, $username: String) {\\n insert_user(\\n objects: [{ id: $userId, name: $username }]\\n on_conflict: {\\n constraint: user_pkey\\n update_columns: name\\n }\\n ) {\\n affected_rows\\n }\\n }\",\"variables\":{\"userId\":\"${userId}\",\"username\":\"${username}\"}}`
}, function(error, response, body){
console.log(body);
callback(null, user, context);
});
}
hasura-jwt-claim
このRuleではログインしたユーザーのRoleをJWTトークンに含めるようにしています。
また今回はRoleが設定されていなかった場合はuserのRoleを返すようにしています。
(JavaScriptに慣れていないので変なところがあったら教えてください)
(追記:5行目のrole.keys.lengthのところはkeysがない場合もあるそうです)

function (user, context, callback) {
let role = ["user"];
const namespace = "https://hasura.io/jwt/claims";
if(context.authorization !== undefined && (context.authorization || {}).roles.keys.length){
role = (context.authorization || {}).roles;
}
context.idToken[namespace] =
{
'x-hasura-default-role': role[0],
'x-hasura-allowed-roles': role,
'x-hasura-user-id': user.user_id
};
callback(null, user, context);
}
その他の設定
サイドバーのApplicationsを開いて、今回作成したアプリケーションを選択します。 SettingsのところのAllowed Callback URLsとAllowed Web Originsを設定していきます. 今回はサンプルなのでどちらも以下のように設定します。

HasuraとAuth0の連携
https://hasura.io/jwt-configに移動します。
そうすると以下のようなページが出てくるのでSelect ProviderにAuth0を選択し、Enter Auth0 Domain Nameに先ほど作った自分のAuth0のアプリケーションのURLを入力します。 アプリケーションのURLは先ほどAllwed Web Originsなどを設定したところの上の方のDomainに書いてあります。
入力が終わったらGENERATE CONFIGをクリックしてJWT Configを作成します。
作成が終わったらHerokuのコンソールからHASURA_GRAPHQL_JWT_SECRETという環境変数を作成します。 環境変数には先ほど作成したJWT Configをセットしてください。

これでHasuraとAuth0の連携は終了です。
Auth0 Tokenのテスト
- https://[YOUR_DOMAIN].auth0.com/login?client=[YOUR_CLIENT_ID]&protocol=oauth2&response_type=token%20id_token&redirect_uri=[YOUR_CALLBACK_URL]&scope=openid%20profile
の**[YOUR_DOMAIN]**を自分のアプリの
ドメイン名、**[YOUR_CLIENT_ID]**をAuth0のApplicationのSettingsにあるClient ID、**[YOUR_CALLBACK_URL]**のところを先ほどAuth0で設定したCallback URLに変更してリンクにアクセスしてください。 - ログインに成功したら以下のようなページに遷移されます。
ここのURLのid_tokenの部分がJWTです - JWTはjwt.ioでデバッグをすることができます。
- このテストの部分はTest with Auth0 Tokenにあるので参考にしてください。
さいごに
この半年間はずっとHasuraを使ったアプリケーション開発を行っているのですが、とても高速にアプリケーションを作成出来るのでとてもいい感じです。 また日本語であまりHasuraに関する記事などを見たことがなかったのでこれが皆さんの参考になると嬉しいです。