TL;DR
- Svelte向けのAmplify UIはSSRモードでも問題なく利用できる
Amplify UI
ようやくSvelteでもAmplify UIが利用できるようになりました。Auth周りのUIや状態管理を丸投げ出来て嬉しいです。
使い方については上記のドキュメントを読めば良いのですが、上記ではおそらく暗黙的に非SSRモードで利用されています。
AmplifyのSSRモード
「SSRモード」は多分正式名称じゃないのですが、意味するところがわかりやすいと思って使っています
まず大前提として、AmplifyはSSRモードではCookieにクレデンシャルを保持します。そうでない場合はLocalStorageに保持されます。SSRモードは以下のように有効化します(デフォルトは無効)。
import outputs from '../../amplify_outputs.json';
import { Amplify } from 'aws-amplify';
// ssr mode
Amplify.configure(outputs, { ssr: true });
これで何が変わるかというと、JavaScriptを利用せずともクレデンシャルを伴ったリクエストを行えるようになります。つまり単純なアンカーリンクによるページ遷移の際にも認証情報が載ります。
これにより、サーバーは、認証情報に応じてSSRを実行出来るようになります。これで設定完了…、というわけではありません。サーバー側に認証情報の検証ロジックが必要です。
Next.js向けには公式ライブラリとドキュメントがあります。
SvelteKitにはないので、上記を参考にSvelteKitに移植したのが以下です。
上記ではこれまで、Amplify UIを用いずに自前でログイン画面等を実装していたのですが、この度オフィシャルでサポートされるようになったのでAmplify UIに差し替えました。本記事では、その過程で理解した、Amplify UIをSSRモード下で利用する例を示します。
Amplify UI on SSR
といっても大した違いはなく…。通常、Amplify UIでは<Authenticator>でログイン後の要素を囲います。これにより、ログイン状態(=認証情報がLocalStorageにある状態)ならばその子要素を、そうでなければログイン画面を表示します。
<Authenticator>
<PrivatePage />
</Authenticator>
ただしSSRモードでは、認証ページの出し分けは、JavaScriptではなく認証情報をCookieとして受け取ったサーバー側が実施するため、/signinページに以下のようにログイン画面を設置して、ログイン後に別ページへ遷移させる…が自然な設計となります。
<script lang="ts">
import { Hub } from 'aws-amplify/utils';
import { goto } from '$app/navigation';
import { Authenticator } from '@aws-amplify/ui-svelte';
import '@aws-amplify/ui-svelte/styles.css';
// handle callback
// doc: https://docs.amplify.aws/react/build-a-backend/auth/concepts/external-identity-providers/#required-for-multi-page-applications-complete-external-sign-in-after-redirect
Hub.listen('auth', ({ payload }) => {
switch (payload.event) {
case 'signedIn':
goto('/dashboard');
break;
}
});
</script>
<Authenticator /> <!-- ログイン周りのUI -->
signoutは、本来であればCookieを無効化するページへリダイレクトさせるのが一番安全なお作法と思いますが、AmplifyのSSRモードでセットされるCookieはHttpOnlyではないため、JavaScriptで消すことが出来ます。なので非SSRモードと同じく以下でよいです。(この挙動は本記事を書いていて気づきました)
async function handleSignOut(e: Event) {
await signOut();
goto('/');
}
つまり、SSRモードでも従来と同じAuthenticatorの使い方をしても壊れないわけですが、それではSSRではないですね。
サーバー側で、リクエストの認証情報を利用して何かを出し分ける例は下記を参考にしてください(Amplify UIに関係ないので割愛しています)。
終わりに
Amplify UIの正式サポートにより、SvelteKitをAmplifyで動かす際の障壁がまた一つ減りました。本記事のとおりSSRモードでもそれなりに動くようですが、随所に荒削りさを感じます。なので当面は非SSRモードで運用するのが安全と考えています。