はじめに
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に関する記事などを見たことがなかったのでこれが皆さんの参考になると嬉しいです。