0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LovableとSupabaseでLineWorksでログインを試行錯誤した話

Posted at

Supabase Edge Functions と Lovable 環境での LineWorks 認証実装 ― 分割構成への検討

この記事では、Lovable(フロントエンド)と Supabase(バックエンド)を組み合わせ、LineWorks の OAuth 認証を実装する際の各要素とその課題、そして解決策として Edge Function を分割して実装した試行錯誤について解説します。

まだ完成しておらず、とりあえず一旦これで行ってみるという話です。


1. 背景と目的

  • 環境構成:

  • 目的:

    • Lovable と Supabase を組み合わせた環境下で、LineWorks を用いたログイン認証(OAuth)を実現する。
    • クライアント ID は公開しても問題ないが、Client Secret は秘匿が必要なため、Edge Functions 内で安全に取り扱う。
    • Edge Function を利用することで、サーバーサイドで Secret を隠蔽しつつ、認可コード取得とアクセストークンの発行を行う。
    • Implicit Flowは嫌!

先に結論

  • EdgeFunctionは機能ごとに小さく分割する
  • LineWorksで認証するので、ANON KEYによる認証は切る

2. OAuth 認証フローにおけるセキュリティ上の注意点

  • Client ID と Client Secret:

    • Client ID は公開情報として問題ないが、Client Secret はブラウザに露出してはいけない。
      → Edge Functions で認証フローを処理することで、Secret をサーバーサイドに留める。
  • OAuth フロー:

    • Implicit Flow はアクセストークンが直接ブラウザに返るためリスクがあるため、認可コードグラントフロー(可能なら PKCE)を利用する。
      → 認可コードを受け取り、サーバー側でトークン交換を行う。

3. 初期実装:単一の Edge Function での認可コード取得とトークン発行

最初は 1 つの Edge Function にて以下の処理を実装しました。
以下の2つの大きな機能を1つのEdgeFunctionで実装していました。

  1. 認可コード取得:

    • フロントエンドからボタンを押すと、Edge Function が呼び出され、LineWorks の認可エンドポイント(https://auth.worksmobile.com/oauth2/v2.0/authorize)へリダイレクトします。
    • ここで、client_id、redirect_uri、scope、response_type=code、state といったパラメータが付与されます。
  2. アクセストークン発行:

    • LineWorks 側でユーザー認証が成功すると、認可コードが Edge Function の redirect_uri に付与されて戻ります。
    • Edge Function はそのコードを用いてアクセストークンを取得します。

4. 問題点:リダイレクト時の Authorization ヘッダーと CORS の問題

  • ブラウザのリダイレクトとヘッダーつけられない問題:

    • LineWorksからのレスポンスはリダイレクトになります。通常のリダイレクト(HTTP 302)はブラウザ側で自動処理され、カスタムヘッダー(例えば Authorization ヘッダー)は付与されません。
      → そのため、Edge Function が「Authorization ヘッダー必須」の状態になっている場合、認可コード取得後のリダイレクト時にエラーが発生しました。
  • CORS の問題:

    • fetch を用いてリダイレクト処理を行おうとすると、LineWorks の認可エンドポイントが CORS 対応していないためエラーになるという課題もありました。
  • アクセストークンの返却先がフロントエンド問題
    EdgeFunctionにリダイレクトすると、最後にアクセストークンを画面に返したいとなった場合に「リクエストに対してレスポンスを返す」ことによる受け渡しができない。(EdgeFunctionに画面を介さずリダイレクトしてしまったため)
    Cookieをつけて画面のURLに遷移させたり、Queryにつけて新たに画面にアクセスしないといけない


5. 解決策:Edge Function の分割構成

これらの課題を解決するため、Edge Function を以下の 2 つに分割する構成を検討しました。
ユーザ情報を取得するものも含めると3つです。
(OAuth2.0じゃなくてOIDC使えばよかったな・・・・)

(1) 認可コード取得用 Edge Function

  • 役割:

    • ユーザーが「LineWorksでログイン」ボタンを押した際に実行され、認可エンドポイントへアクセス、最終的にはLovableのフロントエンドにリダイレクトします。
  • 特徴:

    • 認可コードを取得し、画面にリダイレクトする
    • EdgeFunctionではなくフロントエンドにリダイレクトすることで、リクエストの起点とレスポンスの終点を揃える。

(2) アクセストークン発行用 Edge Function

  • 役割:

    • フロントエンド側で、URL に含まれる codestate を検出した場合に自動実行され、認可コードを受け取ってアクセストークンを発行します。
  • 特徴:

    • この関数では、認可コードからアクセストークンを取得するために、必要なリクエストを LineWorks のトークンエンドポイントに送信します。
    • ここで、Edge Function 内でデフォルトの anon key を使用するか、JWT 検証を無効にして(--no-verify-jwt オプション)処理を進めることが検討されます。
    • 結果として、アクセストークンがフロントエンドに返却され、フロントエンドはそのトークンを用いて LineWorks の API を呼び出し、認証を完了させます。
      ※ただし、このLineWorksのAPI実行もフロントエンドから直接はできないので、また別のEdgeFunctionを使うことになります。

6. フロントエンドと連携する流れ

  1. ログインボタン押下:

  2. 認可コードの受け取り:

    • ユーザーが LineWorks で認証・同意すると、LineWorks は認可コードを付与して、事前に設定したリダイレクトURI(画面)に戻ります。
  3. アクセストークン発行:

    • 画面は URL のクエリから codestate を検出すると、自動的にアクセストークン発行用の Edge Function を呼び出す仕組みを実装します。
      • Edge Function は認可コードからアクセストークンを取得し、EdgeFunctionのレスポンスとしてアクセストークンを画面に返します。
  4. 認証完了:

    • フロントエンドは受け取ったアクセストークンを利用して LineWorks の API を呼び出し、認証が成功した状態を確立します。

7. まとめ

  • 目的:

    • Lovable + Supabase 環境下で、LineWorks を利用した認証を実装する。
  • 技術的なチャレンジ:

    • Client Secret を秘匿するため、Supabase Edge Functions を活用。
    • 単一の Edge Function で認可コード取得とアクセストークン発行を実装し、EdgeFunctionにリダイレクトすると Authorization ヘッダーが付かずエラーが発生。
  • 解決策:

    • Edge Function を 2 つに分割し、1 つは認可コード取得専用、もう 1 つはアクセストークン発行専用とする。
    • 画面はcodeとstateがあるかどうかで処理を分ける。(URL に codestate が含まれる場合に自動的にアクセストークン発行用 Edge Function を呼び出す処理を実装)

一旦これで進めてみて、何か不都合等があれば更新します!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?