paint-brush
でも、でも、でも、合法って難しい@dbozhinovski
511 測定値
511 測定値

でも、でも、でも、合法って難しい

Darko Bozhinovski8m2024/08/19
Read on Terminal Reader

長すぎる; 読むには

いいえ、そうではありません。退屈で、官僚的で、解決済みの問題です...しかし、それを総括的に難しいと言わないでください。
featured image - でも、でも、でも、合法って難しい
Darko Bozhinovski HackerNoon profile picture


いいえ、そうではありません。退屈で、官僚的で、解決済みの問題です...しかし、それを総括的に難しいと言わないでください。


私は「PHP でパスワードをハッシュするために MD5 を使用した」年です。確かに、 2012 年当時でさえ、それはひどいアイデアでした。しかし、当時、認証を「難しい」と考えたことはありませんでした。それ自体はかなり簡単な試練でした。電子メールまたはユーザー名を取得し、パスワードを取得し、それをハッシュし (「神が意図したように」MD5 を使用)、特にセキュリティに敏感な場合は、パスワードに [ソルト] を追加します。これらすべてをどこか (通常はデータベース) に保存します。これで、サインアップが完了しました。


最近では、その話は変わってきました。「認証は難しい」という話は、HackerNews や Reddit をクリックするだけでいつでも聞ける話のように思えます。でも、本当にそうでしょうか? 私の意見では、認証の構築は難しくありません。誰でも学べます (この分野の仕事に携わる人は誰でも基本を学ぶべきです)。本当の課題は、MFA、ユーザー管理、パスワードのリセット、数百の OAuth プロバイダーのそれぞれ、異なるプロバイダーからのアカウントの統合など、追加機能にあります。これは、千切れ死にのようなものです。認証は解決済みの問題なので、車輪の再発明は時間の無駄です。しかし、だからといって「認証は難しい」という包括的な発言が正しい、あるいはそれに近いということではありません。実験して、基本を理解し、そこから構築する必要があります。複雑さは、作成するものの規模 (または潜在的な規模) に応じて増大するだけです。


では、認証は実際どれくらい難しいのでしょうか? 詳しく見ていきましょう。


昔々…

PHP と md5 に関する話の続きですが、ログイン機能の構築は、同様の一連の手順に従いました。電子メールとパスワードを取得し、ストレージに電子メールが存在するかどうかを確認し、その電子メール用に保存されているソルトとともにパスワードをハッシュし、結果のハッシュをデータベースに保存されているハッシュと比較し、すべて正常に機能する場合は、 setcookieを介して Cookie を設定します (ここではまだ PHP の世界ですが、全体的なロジックは他のエコシステムとそれほど異なっていません)。


サインアウトはさらに簡単で、サーバー上の Cookie を無効にするだけで完了です。サーバーが次のリクエストで Cookie を検出しない場合は、ログインしていないことになります。そのため、認証されたルートを実行することも、全体としては簡単な作業でした。権限に関しては、物事が複雑になる可能性がありましたが、私が構築する必要があったアプリでは、管理者とユーザーだけであることがほとんどでした。これは、アプリのロールの数を増やす必要がある場合に、ユーザー レコードと一緒に、または権限テーブルに保存するだけで済みました。


正直に言うと、私はSuperTokensで働いています。しかし、この記事は、認証がいかに難しいかという、ありふれた話に対する個人的な不満から生まれたものです。言い換えれば、私は「私のものを売り込もうとしている」わけではありません。好きなものを使ってください。


自分で巻く - 「現代的」なアプローチ

メールアドレス/パスワードとソーシャル認証

今日の状況にたどり着くには、最初から始めましょう... 驚くかもしれませんが、これらのコンポーネントがあれば、電子メール/パスワード + ソーシャル ログイン PoC を作成するのに十分であることに同意していただけると思います。


  1. サインアップ、サインイン、サインアウトなどのルートを処理するサーバー。
  2. ユーザーレコードを保存するための何らかのストレージ(メモリ内配列も使用可能)
  3. ビュー - ログイン、サインアップ、認証された「ダッシュボード」画面。
  4. ソーシャル認証のハンドラー


Express と Passport を使用すると、車輪の再発明は行わないため、非常に退屈で繰り返しの多い 150 行のコードになります: https://github.com/supertokens/auth-express/blob/master/index.mjs 。次のセクションでは、コードで何が起こっているかを表面的に説明します。概念をすでに理解している場合は、先に進んでください。Express アプリは、いずれにせよ PoC です。


簡単に分析してみましょう:

画面上にものをレンダリングする

私の見方では、これに取り組む方法は 2 つあります。レンダリングから始めて認証ルートに進むか、その逆です。ほとんど偶然ですが、私は FE 中心の庶民になってしまいました (ご存知かもしれませんが、SQL はまだできます)。そこで、「画面上にものをレンダリングする」アプローチから始めます。


これは PoC なので、React のように凝ったことはしません。ejs を使ったシンプルな SSR で十分です: https://github.com/supertokens/auth-express/tree/master/views

ルートの追加

いくつかのpassport.jsの例に基づきますが、さらに簡略化すると、次のものが必要になります。

  1. いくつかの依存関係: npm i passport passport-local express-session 。それぞれについて簡単に見ていきましょう。

    1. Passport.js - Express および Node 用の OG 認証ミドルウェア。
    2. passport-local - Passport の認証戦略。特定の認証方法 (この場合は、ユーザー名 (電子メール) とパスワードを使用したローカル ログイン) の認証プロセスを処理するモジュール内の認証戦略。
    3. express-session - セッション データを管理するミドルウェア。HTTP リクエスト間でユーザー セッションを保存して保持できます。各クライアントに一意のセッション ID を割り当て、クライアント側の Cookie に保存して、サーバー上のセッション データを取得するために使用されます。
  2. ユーザーを保存する場所 (上記のリンクの例ではメモリ内配列を使用しています): https://github.com/supertokens/auth-express/blob/master/index.mjs#L13

  3. ユーザー検索の受信リクエストを処理するためのパスポート インスタンスと LocalStrategy インスタンスの構成: https://github.com/supertokens/auth-express/blob/master/index.mjs#L18

  4. パスポート ( https://github.com/supertokens/auth-express/blob/master/index.mjs#L60 ) とエクスプレスセッション ( https://github.com/supertokens/auth-express/blob/master/index.mjs#L69 ) を初期化します。


確かに冗長です。難しいでしょうか? 少なくとも、おもちゃとして実装するという意味では、難しいとは思いません。しかし、私たちはしばらく前にメール/パスワードの組み合わせの使用を終えました。今あるものにソーシャル プロバイダーを追加するのがどれだけ難しいか検証してみましょう。


ここでのプロバイダーの例として、私は単純な理由から GitHub を選択しました。完全に従うことに決めた場合、GitHub は始めるのが最も簡単なプロバイダーの 1 つだからです (Google を参考にしてください)。


完全に従おうと決めた場合は、GitHub キーを取得する方法を説明したリンクがこちらにあります: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-appところで、心配していたら、リポジトリ内のキーは有効ではありません ;)

PoC に GitHub OAuth2 を統合する

まず、もう 1 つの依存関係、 npm i passport-github2が必要です。passport -github2 はPassport の認証戦略であり、GitHub の OAuth2 API との統合を可能にします。


いくつかのハンドラー ( https://github.com/supertokens/auth-express/blob/master/index.mjs#L122-L133 ) と構成 ( https://github.com/supertokens/auth-express/blob/master/index.mjs#L29-L45 ) を追加すれば、それで完了です。複雑ですか? おそらくそうではありません。官僚主義ですか? もちろんです。退屈ですか? まったくそうです。特に、何度も繰り返す場合はそうです。これは解決済みの問題です。車輪の再発明は、私たちが確立したように、多くの場合、時間の最適な使い方ではありません。


大きなアイデア

ここまで読んでいただければ、Auth の構築はそれほど難しくないということにおそらく同意していただけると思います。つまり、Auth は、JWT という神秘的な言語を話す白ひげの魔法使いだけが理解して実装できる魔法のものではありません。


いいえ、実際、開発者として、認証の仕組みの基本を理解するべきだと私は主張します。そして、私はしばしば、そうではないと主張する物語を見ます - 「私を信じてください、私たちがあなたのためにそれを処理します」というようなものです。そして、確かに、ほとんどの場合、独自の認証を展開するのは時間の無駄であることに同意します。しかし、それは構築するのがそれほど難しいものではなく、確かに神秘的なものではありません。本当に厄介なのは、認証とユーザーエクスペリエンスを取り巻くすべてのことです。


これを考えてみましょう。上記の例では、認証機能が動作しています。まあ、一応は。しかし、次のことは実行できません (記事の冒頭でも言及されています)。

  • 2FA、MFA
  • パスワードのリセット
  • 数百のOAuthプロバイダーのそれぞれが持つ特異性
  • ユーザー管理
  • 異なるプロバイダーからのアカウントの統合
  • 起こりうるあらゆるエッジケースと潜在的なセキュリティホールをカバーする
  • ...そして私は続ける


おそらく、これらをそれぞれ実装できるでしょう。そして、それぞれ単独では、単純なものと思われるかもしれません。しかし、積み重なると大きな負担になります。したがって、実装が必ずしも重要というわけではありません。実装を維持すること、実装に責任を持つこと、標準やセキュリティ違反を最新に保つことなどが重要になります。さらに、皆さんのうち、RfC を読むのが好きな人は何人いますか? ミートアップに参加していたら、手を挙げる人はそれほど多くないと思います。


私が言いたいのは、認証は全体として簡単ではないということです。もちろん、上で行ったように、PoC 用に何かを簡単にまとめることはできます。しかし、それは魔法ではありませんし、理解できないわけでもありません。どうか、そう言わないでください。そのような考え方 (およびマーケティング) は、私の意見では、業界全体に損害を与えます。


それで、当然の疑問は、いつ自分でロールすべきかということです。

おもちゃプロジェクト、インディーズ、教育活動

...ぜひ。むしろ、そうすることをお勧めします。実践することで多くのことを学べるので、なぜそうしないのでしょうか? インディーズ/おもちゃのプロジェクトやブログが成長してかなりのユーザー ベースやフォロワーを獲得したら、サービス、自己ホスト型ソリューション、または他のものに切り替えてください。結局のところ、その時点では製品があり、認証を維持するよりもその製品の構築に時間を費やす方が間違いなく効果的です。

スタートアップ

一般的に、製品を構築する場合は、独自の認証を導入しないでください。これは非常に退屈で煩雑な車輪の再発明です。選択できるオプションはたくさんあります。さらに、何かを構築しているわけですから、そうでしょう? 製品に認証がないのに、なぜこの会話をしているのでしょうか?

スケールアップ以上(定義は任意)

しないでください。スタートアップと同じ理由ですが、ここではより当てはまります。


おそらく、私が何を言いたいのかお分かりでしょう。「認証は難しい」というのは、包括的な発言として使われる場合、マーケティングの売り文句であると言えます。認証は理解でき、構築できますが、退屈で、維持するのは楽しくなく、解決済みの問題です。したがって、認証は商品と見なすことができます。つまり、棚から好きなフレーバー (いくつかのオプションを以下に示します) を選べる商品です。

セルフホストとFOSSの状況

自分のスタックを所有することに興味がある人(私のように)には、選択肢も豊富にあります。

認証ライブラリ

  • Passport.js(上記で詳しく説明)
  • Lucia - 開発者のエクスペリエンスと使いやすさに重点を置いた、最新の Web アプリケーション向けのシンプルで柔軟な認証ライブラリです。
  • Auth.js - さまざまなフレームワークやアプリケーションに簡単に統合できるように設計された、Node.js 用の軽量でカスタマイズ可能な認証ライブラリ。当初は Next 用のライブラリとして始まりました。

認証サーバー

  • Keycloak - シングル サインオン (SSO)、アイデンティティ ブローカー、ユーザー フェデレーションなどの機能を提供するオープン ソースのアイデンティティおよびアクセス管理サーバー。
  • SuperTokens (上記の免責事項を参照) - セキュリティとシンプルさを重視した、セッション管理、ソーシャル ログイン、電子メール/パスワード認証などの事前構築された機能を提供するオープンソースの認証ソリューションです。
  • FusionAuth - ユーザー管理、多要素認証 (MFA)、シングル サインオン (SSO) などの機能を提供する、開発者向けの柔軟な認証プラットフォームです。
  • Authelia - リバース プロキシを使用してアプリケーションを保護するように設計された、多要素認証 (MFA) と SSO を提供するオープン ソース認証サーバー。

ストレージ + 認証

  • Supabase - Firebase の代替として設計された、データベース、認証、リアルタイム機能を提供するオープンソースのバックエンド アズ ア サービス (BaaS) プラットフォーム。
  • Pocketbase - 最新の Web およびモバイル アプリケーションの開発を簡素化することを目的とした、データベース、認証、ファイル ストレージを組み合わせたオープン ソースのバックエンド ソリューションです。


したがって、Auth にサードパーティのソフトウェアを使用したくない場合であっても、ニーズと好みに応じて、既製のオープンソース ソフトウェアを選択して使用することができます。

要点: 認証は開発の「お役所仕事」

私が学んだ「大きな」教訓は、特に認証のように解決済みの問題の場合は、車輪の再発明を避けることです。車輪について学び、実験し、おもちゃの車輪を作り、理解してください。しかし、どうか、理解して構築するのが不可能なほど難しいものとして売り込まないでください。教育してください、門番をしないでください。