🍪

API認証をCookie方式に刷新(開発日記 No.053)

に公開

関連リンク

はじめに

こんにちは!昨日は note-converter のAPIクライアント周りのリファクタリングやドキュメント整備を進めました。しかし、以前から抱えていた note.com API連携におけるCSRFトークン取得の問題が解決していませんでした。そこで今日は、この問題に本格的に取り組み、API連携の安定化を目指します。具体的には、note.comのAPI利用方法を再検証し、実装を修正することにしました。

背景と目的

note-converter プロジェクトでは、LLMの調査結果などを自動でnote.comに下書き投稿する機能を目指しています。しかし、これまでの実装では、note.comのWebページ構造の変更などにより、ログイン処理やCSRFトークンの取得が不安定になるという課題がありました。特にCSRFトークンの取得ロジックは複雑で、根本的な解決が必要だと感じていました。

今回の目的は、より安定した認証方法を見つけ出し、APIクライアントの実装を修正することで、note.comとの連携を確実なものにすることです。

検討内容

まず、現状の実装(メールアドレスとパスワードでのログイン、そしてCSRFトークン取得)に問題がある可能性を考え、他のアプローチを探ることにしました。調査を進める中で、shimayuz/note-mcp-server という素晴らしいリポジトリを発見しました。

このリポジトリの実装を詳しく見てみると、私が試みていたメール/パスワードでのログインとは異なり、ブラウザから取得したCookie(具体的には note_gql_auth_token_note_session_v5)を使って認証を行っていることがわかりました。

このCookieベースの認証方式を採用すれば、以下のようなメリットがあると考えました。

  1. 認証フローの簡素化: 複雑なCSRFトークン取得処理が不要になる可能性がある。
  2. 安定性の向上: Webページの構造変更の影響を受けにくくなる可能性がある。

この発見に基づき、現在のメール/パスワード認証方式から、Cookieベースの認証方式へ切り替える方針を固めました。従来の認証方式も後方互換性のために残しつつ、Cookie認証を優先的に利用するように実装を修正することにしました。

実装内容

検討した方針に基づき、以下の実装修正を行いました。

1. NoteClient クラスの修正

  • __init__ メソッドを修正し、Cookie認証情報 (note_gql_auth_token, _note_session_v5) を受け取れるようにしました。
  • Cookie値を設定するための setup_cookie_auth メソッドを追加しました。
  • 認証フローを見直し、Cookie情報があればそれを優先的に利用し、なければ従来のメール/パスワード認証を試みるように変更しました。
  • Cookie認証の場合、CSRFトークン取得ロジックを簡略化しました(完全に不要になるか、あるいはより簡単な方法で取得できる可能性があるため)。
  • test_connection メソッドを改善し、Cookie認証が正しく機能しているかも検証できるようにしました。

2. 設定ファイルの更新 (.env.example, config.py)

  • .env.example にCookie認証用の環境変数 (NOTE_AUTH_TOKEN, NOTE_SESSION_V5) を追加し、認証方法についての説明を追記しました。
  • config.py を修正し、これらの新しい環境変数を読み込めるようにしました。
  • get_note_api_config 関数を更新し、Cookie認証と従来の認証の両方に対応できるようにしました。設定の有効性チェックロジックも更新し、どちらかの認証情報が設定されていればOKとしました。

3. 統合テストコードの実装 (tests/integration/test_note_api_posting.py)

note.com APIとの実際の連携を確認するため、新しい統合テストファイルを作成しました。

  • テスト実行条件:
    • 環境変数 TEST_USE_REAL_API=true が設定されている場合のみ実行されるようにしました。これにより、意図しないAPIアクセスを防ぎます。
    • Cookie認証情報または従来の認証情報のいずれかが設定されている場合にのみテストが実行されるようにチェック処理を追加しました。
  • テストケース:
    • test_api_availability: APIへの基本的な接続と認証情報の有効性を確認します。
    • test_user_notes_retrieval: 認証されたユーザーの記事一覧を取得できるかテストします。
    • test_create_draft: 新しい下書き記事を作成できるかテストします。
    • test_update_draft: 作成した下書き記事を更新できるかテストします。(test_create_draft で作成した記事IDを利用)

4. 動作確認

.env ファイルに必要なCookie情報(ブラウザの開発者ツールから取得)と TEST_USE_REAL_API=true を設定し、以下のコマンドでテストを実行しました。

cd Docs/note-converter
pytest tests/integration/test_note_api_posting.py -v

実行結果は以下のようになり、すべてのテストが成功しました!

======================== test session starts ========================
...
tests/integration/test_note_api_posting.py::TestNoteAPIPosting::test_api_availability PASSED
tests/integration/test_note_api_posting.py::TestNoteAPIPosting::test_user_notes_retrieval PASSED
tests/integration/test_note_api_posting.py::TestNoteAPIPosting::test_create_draft PASSED
tests/integration/test_note_api_posting.py::TestNoteAPIPosting::test_update_draft PASSED

======================== 4 passed in 12.34s ========================

これにより、新しいCookie認証方式が正しく機能し、note.com APIとの間で記事の取得、作成、更新が問題なく行えることが確認できました。

技術的なポイント

今回の修正における技術的なポイントは以下の通りです。

  • Cookie認証の採用: note.comの認証において、note_gql_auth_token_note_session_v5 という2つのCookieが重要であることを特定し、これらをリクエストヘッダーに含めることで認証を実現しました。これにより、従来のログイン処理やCSRFトークン取得処理の複雑さを回避できました。
  • 柔軟な認証方式: config.py で認証情報を読み込む際に、Cookie情報があればそれを優先し、なければ従来のメール/パスワード情報を利用する、というフォールバック機構を実装しました。これにより、ユーザーはどちらかの方法で認証情報を設定すればよくなり、利便性が向上しました。
  • 実践的な統合テスト: pytest を使用し、実際のnote.com APIと通信する統合テストを実装しました。環境変数 TEST_USE_REAL_API でテストの実行を制御し、安全性を確保しつつ、API連携の確実性を検証できるようにしました。テスト間で記事IDを引き継ぐなど、一連の操作フローをテストできるように工夫しました。

所感

長らく悩みの種だったnote.com APIのCSRFトークン問題に、ようやく解決の糸口が見えました!shimayuz/note-mcp-server リポジトリの存在は本当にありがたく、Cookie認証というアプローチを発見できたことに感謝しています。

最初は「なぜ自分の実装だとCSRFトークンがうまく取得できないんだろう?」と試行錯誤していましたが、根本的に認証のアプローチが異なっていたことに気づいたときは、目から鱗が落ちる思いでした。Cookieを使う方法は、一度設定してしまえば非常にシンプルで、今後のメンテナンスも楽になりそうです。

実装自体は、既存のクラス構造に新しい認証方法を追加する形だったので、比較的スムーズに進みました。設定ファイルの更新や、両方の認証方式に対応するためのロジック追加も、今後の拡張性を考えると良い判断だったと思います。

そして、何より嬉しかったのは、統合テストがすべてパスした瞬間です!実際に自分のコードがnote.comと通信し、記事の作成や更新を成功させたのを確認できたときは、大きな達成感がありました。これで、note-converter のコア機能である自動投稿プロセスを安定して動かすための基盤が整いました。

今後の課題

今回の修正でAPI連携は安定しましたが、まだ改善の余地はあります。

  1. GraphQLベースAPIの検討: 参考にしたリポジトリではGraphQL APIも利用されていました。現在はRESTベースのAPI(と思われるエンドポイント)を使用していますが、将来的にはGraphQL APIの利用も検討し、より効率的なデータ取得や更新を目指したいです。
  2. 認証情報の安全な管理: 現在はCookie情報を環境変数に直接設定していますが、これらの情報の有効期限や、より安全な管理方法(例えば、キーチェーンや専用の認証管理ツールとの連携など)について検討が必要です。有効期限が切れた場合の再取得・再設定フローも考慮する必要があります。
  3. エラーハンドリングの強化: APIからの予期せぬレスポンスやネットワークエラーなど、様々なエラーケースに対するハンドリングをより堅牢にしたいです。具体的なエラーメッセージの表示や、一時的な問題に対するリトライロジックの実装などが考えられます。

まとめ

今回は、note.com APIの認証方法を従来のメール/パスワード方式からCookieベースの方式へと刷新しました。shimayuz/note-mcp-server を参考に実装を進め、NoteClient クラスや設定ファイルを修正し、新たに統合テストコードも整備しました。

この結果、これまで不安定だったCSRFトークン取得の問題を解決し、note.com APIとの連携を大幅に安定させることができました。統合テストも成功し、記事の取得・作成・更新が問題なく行えることを確認しました。

これにより、note-converter プロジェクトの本来の目的である「LLM調査結果の自動記事化」に向けて、大きな一歩を踏み出すことができました。

GitHubで編集を提案

Discussion