はじめに
以前書いた、Auth0 サンプルの SPA を微修正して、 Auth0 サンプルの API に CORS していく では、Auth0 のログイン設定にて audience 設定をしていました。
app
.use(hljsVuePlugin)
.use(createRouter(app))
.use(
createAuth0({
domain: authConfig.domain,
clientId: authConfig.clientId,
authorizationParams: {
redirect_uri: window.location.origin,
audience: authConfig.audience // <-- 追加してたとこ
}
})
)
しかし、ふと疑問が。
「では単一のページ (SPA) から複数の対向 API 実行したかったらどうするんだ?」
(当然発生するケース)
で、それ自体は簡単だったのですが、今度はそれを localhost
で検証する場合に若干面倒だということがわかったので、その解消方法について備忘録がてら残しておこうと思います。
複数の対向 API を実行したい場合に何を変更すればよいか?
例えば前回の例だと http://localhost:3000
にて vite で起動したサーバーから、 http://localhost:8080
のみに API実行してました。
今回は、 http://locahlhost:8080
, http://locahlhost:8081
の2箇所に API 実行したいと思います。
で、結論から書くと、実装自体は非常にシンプルです。以下でできます。
app
.use(hljsVuePlugin)
.use(createRouter(app))
.use(
createAuth0({
domain: authConfig.domain,
clientId: authConfig.clientId,
authorizationParams: {
redirect_uri: window.location.origin,
// audience: authConfig.audience <-- ここを削除
}
})
)
↓はベタなコードですいません。サンプルの改造に力入れてもしょうがないんで
<template>
<div>
{{ token }}
<hr/>
Response from 8080: {{ response1 }}
<hr/>
Response from 8081: {{ response2 }}
</div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue';
import { useAuth0 } from '@auth0/auth0-vue'
import { ref } from 'vue'
import axios from 'axios'
const { getAccessTokenSilently } = useAuth0()
const token = ref('')
const response1 = ref({})
const response2 = ref({})
const options = ref({})
import authConfig from "../../auth_config.json";
onMounted(async () => {
token.value = await getAccessTokenSilently({
authorizationParams: {
audience: authConfig.audience_1
}
})
options.value = {
headers: {
Authorization: `Bearer ${token.value}`
}
}
var temp = await axios.get('http://localhost:8080/authorized', options.value)
response1.value = temp.data.message
token.value = await getAccessTokenSilently({
authorizationParams: {
audience: authConfig.audience_2
}
})
options.value = {
headers: {
Authorization: `Bearer ${token.value}`
}
}
temp = await axios.get('http://localhost:8081/authorized', options.value)
response2.value = temp.data.message
})
</script>
getAccessTokenSilently の AuthorizationParams
を書いてあげるだけですね。
しかしながら、これを単に実行すると Consent Required
というエラーになり、2回目の API (to localhost:8081
がエラーになるはずです。
で、これをどうやって解消するんだ?...って話です。
解決策は https
化して、かつ localhost
でなくアクセスすれば OK らしい
本現象の根本原因は こちら のようです。
どうやら初回はログイン済みセッションから OAuth 同意画面を SKIP できているようですが、その次の同意画面をSKIP できないということなのかなと解釈しました。
(first party, third party ってのは OAuth の用語なのか Auth0 の用語なのかよくわかってませんが。なんにしてももうちょっと勉強しないとです...)
では上記のページに記載があるように /etc/hosts
とかにエントリ追加して localhost
じゃなくせばいいじゃない?となるんですが、今度はこちらが問題となります。
Why do I get auth0-spa-js must run on a secure origin?
これをサマリすると、 auth0-spa-js
が動くためには、以下の URL じゃなきゃだめだよと言ってます。
-
https
なURLでの接続 -
localhost
的なニュアンスのなにか
これと先程の課題の AND を取ると、
「 https
かつ localhost
じゃない URL でアクセスすればいいじゃない」ということになりますね。
ということで、以下の対応をしました。
/etc/hosts
にエントリ追加
どうせならさっきのページに書かれた感じでエントリ追加してみましょう。
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 myapp.example <-- 追加
255.255.255.255 broadcasthost
::1 localhost
mkcert
を使って https
化
viteでhttpsなlocalhostを起動する が大変参考になりました。ありがとうございます。
やったことは以下です。
% brew install mkcert
% cd /path/to/SPA のある場所
% mkcert -install
Created a new local CA 💥
Sudo password:
The local CA is now installed in the system trust store! ⚡️
% mkcert localhost
Created a new certificate valid for the following names 📜
- "localhost"
The certificate is at "./localhost.pem" and the key at "./localhost-key.pem" ✅
It will expire on 1 May 2027 🗓
% ls *.pem
localhost-key.pem localhost.pem
ここで作成されたファイルを、 SPA の vite.config.js
に読み込みます。
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import fs from 'fs' // <-- 追加
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
// ここから下を追加
server: {
https: {
key: fs.readFileSync('./localhost-key.pem'),
cert: fs.readFileSync('./localhost.pem'),
}
}
})
以下も実施。
npm install --save-dev @types/node
最後に Auth0 Dashboard で、SPA に関する以下の URL を書き換えておきます。
(もともとは http://localhost:3000
になっているはず)
- Allowed Callback URLs
- Allowed Logout URLs
- Allowed Web Origin
ここまで完了したら、8080, 8081 の API と、SPA の vite を起動し、ブラウザから https://myapp.example:3000/#/practice
に接続します。
Consent Required
が回避できているのがわかります。
まとめ
ということで、複数の対向 API を持つ SPA を localhost
で開発する際に発生する Consent Requied
問題が発生することを、以下にて回避することができました。
- audience 定義場所の変更
- hosts へのエントリ追加
- vite サーバーの https 化
次はユーザアクセスのブロックや RBAC 周りを勉強していこうと思います。