Closed6

[Scrap] Next.js & Nest.js 認証付きのサイトを実装してみる

へぶんへぶん

目的

以下の記事を読んで、SSR の処理で 認証付きの API を叩くと良くないと書いてあったので、どんな感じなのか知りたくなった。
https://qiita.com/ryokkkke/items/1bd858a5d6f261a9342a

実装したい内容

  • ログイン API を実装する
  • 認証がないとレスポンスを受け取れない API を実装する
  • Next.js で API を叩けるようにして、動作確認する
  • (できれば AWS ECS に上げて動作確認したい)

前提

今回は Next.js 側の実装を確認したいので、Nest.js 側はサンプルコードを動作させることができればそれでいい。

手順

  1. Nest.js の JWT 認証付きのサンプルをローカルで動くようにする
  2. Next.js で認証用のページ・処理を実装
  3. Next.js で READ 用の認証必須のページを実装
へぶんへぶん

1. Nest.js の JWT 認証付きのサンプルをローカルで動くようにする

postgress を Docker で立ち上げて、env ファイルを編集して問題なく動作した。

へぶんへぶん

2. Next.js で認証用のページ・処理を実装

アクセス制御のやり方どうする?

https://zenn.dev/aiji42/articles/450ce962cc225a
https://zenn.dev/catnose99/articles/2169dae14b58b6

読み逃していたけど、公式にページがあった。
https://nextjs.org/docs/authentication

へぶんへぶん

そもそも JWT token どこに保存するのか問題

以下だと Cookie に載せてる。

https://medium.com/@ryanchenkie_40935/react-authentication-how-to-store-jwt-in-a-cookie-346519310e81
https://zenn.dev/marokanatani/articles/d0777a34641d22

以下の記事も参考になりそう
https://ritou.hatenablog.com/entry/2019/12/01/060000

以下だと、origin 周りをきっちりやっとくのが大事的な感じに書いてる。
https://postd.cc/web-storage-the-lesser-evil-for-session-tokens/

一番参考になりそうな情報を忘れてた。
https://www.slideshare.net/ockeghem/phpconf2021spasecurity

とりあえずの結論

保存すると言うよりかは Cookie に token をのせつつ、SSR 側でも cookie から token を参照するようにする。

へぶんへぶん

Cookie を使う

nookies っていう Next 用に Cookie を扱うためのヘルパーがあるみたい。
https://github.com/maticzav/nookies

上記の README.md に使用例が記載されているのでまずはそこから実装してみる。
以下のような流れになりそう。

Login 処理

TODO の取得

https://kroki.io っていうサイトを使った

login 処理の画像
TODO ページ取得の画像

title /api/login
skinparam monochrome true
skinparam ranksep 20
skinparam dpi 150
skinparam arrowThickness 0.7

actor client
entity "Next.js server" as next
entity "Nest.js server" as nest
client->next: "/api/login" with email, pass
next->nest: "/api/login" with email, pass
nest->next: Return "accessToken"
next->next: Set accessToken to cookies \n with httpOnly, secure
next->client: Return Response "201"
title TODO 一覧の表示
skinparam monochrome true
skinparam ranksep 20
skinparam dpi 150
skinparam arrowThickness 0.7

actor client
entity "Next.js server" as next
entity "Nest.js server" as nest
client->next : Request Todos page (auth-required)
next->next : Get "JWT" from "cookies"
next->nest : Request "/api/todos" with "JWT" 
note right: Check "JWT"
nest->next : Return "/api/todos" response
next->next: Build page html with response
next->client: Return Todos page
へぶんへぶん

上記の方法で実装して、Next.js サーバー側で cookies から JWT を取り出して Nest.js に API リクエストできた。

所感

  • 方式に依存するのかも知れないけど、以下のどちらで行なっても手軽な印象
    • SSR で API を叩く場合
    • useSWR などでクライアントで API を叩く場合
  • ログイン処理は Client から直接行うのではなく、Next.js のサーバーで行うのが筋がいい感じがした
    • httpOnly 属性つけれてセキュア
    • Next.js 側で Cookie に token の設定する責務を負うことで、モバイルクライアントと API を共通にできるメリットがある気がする
  • あとは Cross-Origin 周りの考慮をする
    • ECS に上げてみるか...

参考

以下の記事がとても参考になった 🙏
https://zenn.dev/uttk/articles/f48fc75120f018

このスクラップは2021/10/08にクローズされました