Blog

September 3, 2026

公開前に自社の認証サーバーを監査しました。バグにはパターンがありました。

自社の認証サーバーを攻撃者の目で読み込み、結果を文書にまとめました。番号付きの 16 セクションで、SAML から SCIM、管理 API、バックアップツールまでを扱い、すべての指摘に深刻度を付けています。最も深刻な 8 件は一晩で修正しましたが、テストスイートはその晩の前も後も 367 件中 367 件が成功と報告していました。8 件は無関係なバグではありませんでした。サブシステムをまたいで繰り返された、3 つの癖だったのです。

August 5, 2026

パスワードを 5 回間違えるとロックするはずの仕組みが、誰一人ロックしていなかった

パスワードを 5 回間違えるとアカウントはロックされます。チェックは正しく、しきい値も正しかったのに、1 万回の誤ったパスワードを送っても一度も発動しませんでした。一斉に送りさえすれば。カウンターは保護のない読み込み・変更・書き込みだったため、同時に届いた試行が互いのインクリメントを上書きし、数値はほとんど増えなかったのです。修正は、インクリメント操作を持たないキーバリューストアでアトミックなカウンターを作る方法そのものです。そしてそこから得た発想の転換が、誰かが並列で数えていると想定せよ、ということでした。

August 3, 2026

2012 年、OAuth 2.0 の筆を握っていた男が降りた。その理由は予言のように読める。

シングルサインオンは 20 年以上前に決着した標準です。それでも SAML は今なお、商談を止めたり営業への問い合わせを強いたりする項目であり続けています。エンタープライズ認証がいかにして高額なアップセルになったのか。その世界を築いたのは誰で、それを警告したのは誰だったのか。その堀は実際どれほど広く、何でできているのか。そして、その半分を静かに干上がらせつつあるひとつの力について。

July 31, 2026

すべてのアラートが発火できることを証明しようとしたら、大半は発火できませんでした

監視は、障害のときにしか実行されないコードです。壊れていることに気づくわけにはいかない、まさにその瞬間にだけ動きます。そこで私たちは、すべてのアラートルールに対して本物のシグナルを流し、通知が実際にキャプチャ用のリレーに届くまで合格としないハーネスを作りました。最初の実行で、看板となるエラー率アラートが完全に死んでいることがわかり、さらに悪いものも見つかりました。保持期間の設定が、気づかないうちにログへ即時期限切れを刻んでいたのです。そのため、取り込みは正常に見えるのに、ある種類のアラートはまるごと空のデータに対して評価されていました。

July 30, 2026

画像を CDN に移したのに、オリジンが配信し続けていた

100 MB を超えるドキュメント用スクリーンショットを Cloudflare R2 に移し、アプリが実行時に自分のホスト名から導き出す CDN ベースの裏に置きました。ブラウザ上では問題なく動きましたが、オリジンのトラフィックは少しも減りませんでした。クローラーが見るページは 127.0.0.1 上でプリレンダリングされており、そこではホスト名が何の手がかりにもならないからです。解決策は、HTML がビルドから持ち出し、エッジがリクエストごとに埋めるプレースホルダーです。そしてそうせざるを得ない理由は、読み取り専用のファイルシステムにあります。

July 29, 2026

危険なデフォルトを、1 行もデータ移行せずにオフにした話

JIT(ジャストインタイム)プロビジョニングはデフォルトでオンになっていました。そのため、フェデレーションされた ID プロバイダーは、ある人物が存在すると主張するだけで、顧客のテナントにアカウントを作成できました。このデフォルトをオフにするのは 1 単語の変更です。本当の問題は、そのカラムを一度も書き込んだことのない保存済みのすべての接続について、動作を黙って変えることなくオフにすることでした。それを解決した仕掛けは、デフォルトが API の一部である理由も説明してくれます。

July 28, 2026

多数のテナントに対応する BFF と、Cookie を持たずに届く唯一のリクエスト

Backend for Frontend(BFF)は OAuth トークンをブラウザから取り除き、ブラウザには不透明な Cookie だけを持たせます。1 つの BFF で多数のテナントを捌くのは、ほとんどが配管の問題です。ただしバックチャネルログアウトが来るまでは。これは Cookie もセッションもブラウザもないサーバー間の POST で、テナントを特定する手がかりは、まだ検証していないトークンの中のクレームだけです。

July 27, 2026

「許可」と答え続けたのに、私たちを落としたアドミッション Webhook

未署名のイメージが絶対に動かないよう、Kubernetes クラスターに署名を検証するアドミッション Webhook を追加しました。数時間後、ある Deployment には 2,242 個の ReplicaSet ができていて、3 秒ごとに新しいものが生まれ、利用可能な Pod は 1 つもありませんでした。Webhook のログを見ると、すべてのリクエストを許可していました。被害の原因は、「mutating admission webhook」という言葉のうち、私たちが読み飛ばすようになっていた 1 語にありました。

July 23, 2026

ログインがきっかり 10 秒止まっていた。犯人は自分たちのセキュリティヘッダーでした

再訪したユーザーは、ログイン画面が出るまで毎回きっかり 10 秒、「Loading…」を眺めていました。決め手はそのきりのいい数字です。SSO ライブラリが、X-Frame-Options: DENY と frame-ancestors 'none' を返す認証ホストに向けて、サイレントリニュー用の隠し iframe を開いていました。そのためフレームは読み込まれず、エラーも出ず、ライブラリはタイムアウトいっぱいまで待ち続けたのです。クリックジャッキング対策と OIDC のサイレントリニュー。それぞれは正しいのに、両者の継ぎ目で止まっていました。

July 22, 2026

HMAC にオートコンプリートを食われた:暗号化したメールアドレスで入力補完検索を実現する

保存時にすべてのメールアドレスを暗号化したところ、管理画面の検索ボックスがひっそりとオートコンプリートしなくなりました。エラーもログも出ません。ブラインドインデックスを使えば暗号文に対する完全一致検索は取り戻せますが、HMAC の役目はまさに、前方一致検索に必要な順序性を破壊することです。本記事では、すべてのプレフィックスをそれぞれ独立した値としてインデックスすることで入力補完を取り戻した設計と、検索可能暗号は暗号の問題ではなくシステムの問題だと教えてくれた 3 つの落とし穴を紹介します。

July 20, 2026

ES256 への移行ひとつで、正しい署名を台無しにする方法が 3 通り

JWT の署名を RS256 から ES256 に移行したところ、発行したトークンはどれも暗号学的には正しいのに、どれも拒否されました。それも 3 回、3 つの異なる理由で。JWS が生の R‖S を求めている場所に DER を渡したこと、128 トークンに 1 つが失敗する整数のパディング、そして足元で変わった base64 の方言です。壊れたバイト列の読み方と、署名の長さだけで犯人のレイヤーを言い当てる方法を紹介します。

July 20, 2026

トークン検証のたびにオリジンに届いていた。今、JWKS はエッジにある

私たちの JWT を 1 つ検証するためにサービスが読む 2 つのドキュメント、ディスカバリードキュメントと JWKS は、私たちが配信するものの中で最もリクエストが多く、最も秘密性の低いものです。それなのに、取得のたびにオリジンまで届いていました。Cloudflare でキャッシュするのは簡単な部分です。難しいのは、古くなった公開鍵のキャッシュが有効なトークンを決して拒否してはならないという点です。積極的にキャッシュした JWKS を安全にする、ローテーションに強い手順を紹介します。

July 18, 2026

Duende IdentityServer の最も安いライセンスでは SAML が使えません

Duende の LITE は年額 $5,750 ですが、クライアントアプリは 2 つまでで、SAML はまったく含まれていません。エンタープライズ SSO や 3 つ目のアプリが必要になった瞬間、年額 $12,500 の STANDARD に移ることになります。実際のプロダクトにとって Duende が本当はいくらかかるのか、そして誰も警告してくれないクライアント数への課金について見ていきます。

July 17, 2026

JWT 署名鍵の 3 つの人生

私たちの認証サーバーが発行するすべてのトークンには、1 つの秘密鍵が署名しています。その鍵は生涯で 2 度引っ越しました。プロセスの中で生まれ、出られない Vault へと追放され、そしてまったく別の、より小さく速い種類の鍵として生まれ変わったのです。どの引っ越しも、トークンが飛び交っている稼働中の発行者の上で行われました。鍵の保管場所とアルゴリズムを変えるには実際に何が必要なのか、そして「よりセキュア」なコミットに紛れ込んでいた静かなリグレッションについて書きます。

July 16, 2026

SAML の署名は有効だった。問題は最初からそこではなかった

あなたの SP はアサーションの署名を検証し、証明書をピン留めし、ユーザーをログインさせました。すべてのチェックに通りました。それでも私は、1 時間前に捕捉したログインをリプレイできました。手口は署名を破ることではありませんでした。署名がそもそもカバーしていないフィールドを削除することでした。

July 14, 2026

MFA を必須にしていたのに、クエリパラメーター 1 つで無効にできた

2 要素目の確認はログインページで行い、トークンエンドポイントでは一度も再確認していませんでした。そのため、正しいパスワードと手で書き換えた戻り先 URL があれば、MFA を素通りできたのです。その修正と、そこから学んだルールを紹介します。MFA はログイン画面の 1 ステップではなく、発行するセッションが持つ性質です。

July 14, 2026

SCIM 税:プロビジョニングは配管であって、プレミアム機能ではない

SCIM は標準化された CRUD API で、その最も重要な操作は、退職した従業員のアカウントを無効にするものです。ベンダーはこれに 1 接続あたり月額 125 ドルの値をつけるか、SSO と並べてエンタープライズプランに置いています。SCIM 接続の提供に実際どれだけのコストがかかるのか、そしてデプロビジョニングに課金することがなぜセキュリティに課金することなのかをお話しします。

July 12, 2026

バックアップは、削除したユーザーをひっそりと蘇らせる

Azure Table Storage と DynamoDB には削除マーカーがありません。削除された行は単に消えるので、増分バックアップは削除をまったく認識できません。そのバックアップをリストアすると、オフボーディングしたユーザーが戻ってきます。ローテーションして捨てたはずのパスワードと一緒に。削除を第一級の扱いにしなければならない理由と、それを実現するたった 1 つのテーブルを紹介します。

July 11, 2026

私たちが出荷した IP 単位の制御は、すべてヘッダー 1 つで回避できた

私たちのレートリミッターとロックアウトカウンターは、クライアントの IP をキーにしていました。nginx の背後では、その IP はクライアントが自由に設定できるヘッダーから来ていました。つまりヘッダーを 1 つ変え続けるだけで、すべてのリクエストが新しい IP を手に入れ、IP 単位の制御はすべて崩れました。1 行で済む偽装と、Kubernetes 上では見た目以上に厄介な修正についてお話しします。

July 10, 2026

get と put しか知らないストアで、認証システムを丸ごと動かしている

Azure Table Storage が提供するのは、パーティションキーと行キー、それ以外はほぼ何もありません。JOIN もなく、セカンダリインデックスと呼べるものもなく、インクリメントもありません。それでも私たちはマルチテナントの認証システムをその上で動かしています。それを可能にしているパターンと、SQL と比べて何を手放すのかを紹介します。

July 9, 2026

パスワードリセットのフォームは、タダで撃てるメール砲台

メールアドレスごとのレート制限がない、認証不要のパスワードリセットのエンドポイントは、あなただけの問題ではありません。他人の受信箱に向ければ、あなたのリセットフォームはスパム砲台になり、そのツケはあなたの送信者レピュテーションに回ります。どのメールアドレスにアカウントがあるかを漏らさずに直す方法を書きます。

July 7, 2026

無料プランにすべての機能を入れました。競合がエンタープライズ向けに取っておく機能も含めて

ほとんどの認証ベンダーは、SSO、SCIM、MFA、監査ログをエンタープライズプランの柵の向こうに囲い込んでいます。私たちはそのすべてを $0 のプランに入れました。機能を無償で提供しても成り立つユニットエコノミクスを紹介します。壁は最初から機能ではなく、アクティブユーザー数とサポートなのです。

July 6, 2026

ID プロバイダーがあなたは誰かを教えてくれて、私たちはそれを信じた

シングルサインオンとは、ID プロバイダーを信頼することです。私たちはそれを 1 つ余計に信頼していました。戻ってきたフェデレーションユーザーをアサーション内のメールアドレスで特定していたので、どの接続も他人のアドレスを主張して、その人のアカウントに入れたのです。修正はバリデーションの追加ではありませんでした。アイデンティティの結合キーを、メールアドレスから、主張する側が偽造できないプロバイダーごとのサブジェクトに変えることでした。

July 6, 2026

ゼロまでスケールできても、1 は数えられない

Azure Container Apps なら、アイドル状態の認証クラスターに払い続けるお金をなくせるはずでした。私たちは移行のコストを見積もり、そして計画を打ち切りました。理由は価格でもコールドスタートでもなく、リーダー選出を行う認証バックプレーンが本当に必要とする唯一の数を、サーバーレスが持っていないからです。

July 3, 2026

SSO 税を金額で見る:Auth0、WorkOS、Clerk で SAML に実際いくらかかるのか

「機能税」を実際の請求書として示します。3 つの購入シナリオ(最初のエンタープライズ案件、数社の顧客、SSO が当然の前提になった段階)を各ベンダーの公開価格で試算しました。さらに、誰も警告してくれない静かな追加料金、つまり統合の途中で OAuth クライアントが足りなくなる問題も取り上げます。

July 1, 2026

サービスディスカバリーが自分の失敗を握りつぶし、自分自身をオフにしていました

3 レプリカのクラスターが、何度も自分自身と意見を食い違わせていました。原因は私たち自身のコードにありました。ピアディスカバリーの処理に、マルチキャストが失敗するとディスカバリーを無効にする catch ブロックがあり、マネージド Kubernetes ではマルチキャストは必ず失敗するのです。ゴシップを丸ごと削除し、代わりに Blob のリースでリーダーを選出するようにした理由と、推測するしかないメンバーシップより Storage Explorer で開けるメンバーシップのほうが優れている理由を紹介します。

June 30, 2026

認証は自作か購入か:予期していなかった請求書

ログイン機能なら週末で作れます。請求書が届くのはその後です。署名検証、SCIM によるデプロビジョニング、MFA、監査ログ、鍵のローテーション、侵害時の責任、そしてティア 0 のシステムのオンコール。自作が正解になる場合も含めて、自作か購入かを正直に検討します。

June 28, 2026

OIDC か SAML か:本当に必要なのはどちらか

OIDC か SAML か。実際に選べることはほとんどありません。それぞれのプロトコルの正体、どちらがどんな場面で勝つのか、SAML の自前実装を危険にしている XML 署名の落とし穴、そして B2B プロダクトが結局は両方を必要とする理由を解説します。

June 26, 2026

あなたの言語で話すサポート。こちらから頼まなくても。

Authagonal のサポートシステムを紹介します。更新ボタン不要のリアルタイムメッセージング、顧客の最初のメッセージで言語を固定する透明な双方向 AI 翻訳、そしてメールになってもすべて翻訳されたまま続くスレッド。シンプルで、見た目が良く、しかも本当に使えます。

June 25, 2026

ハイフンひとつ、テナントふたつ、署名鍵はひとつ

私たちのテナントのうち 2 つが、人知れず同じテナントになっていました。データベースも、トークン署名鍵も同じで、名前だけが違う。原因は、ハイフンを取り除いてスラッグをサニタイズする 1 行のヘルパーで、一意の識別子を一意でないものに変えていました。情報が欠落する文字列変換がどのようにしてテナント間の乗っ取りになったのか、そしてなぜ皆さんより先に私たちが見つけられたのかをお話しします。

June 23, 2026

ユニットテストが緑でも、本番に出せるとは限らない

私たちは認証を売っているので、最も重要なテストは顧客になるテストです。1 回の Playwright 実行でテナントをサインアップし、すべての機能を設定し、本物のアプリをそこに向け、正しいクレームで本物のユーザーをログインさせ、さらにバックアップ、リストア、自己削除まで行います。徹底したエンドツーエンドテストが、本番リリースへの自信をどう支えているかを紹介します。

June 22, 2026

自社の管理コンソールには自社の SAML でログインしています。それで見つかったもの

私たちのスタッフ用コンソールは Authagonal 自身を通して認証しており、Entra の SSO と SCIM がプロビジョニングを担っています。自分が自分の顧客になると、どのテストスイートも書こうと思いつかないエッジケースが表に出てきます。そのうち重要だったものを紹介します。

June 22, 2026

Terraform の state をパブリックなインターネットから外す(VPN を立てずに)

Terraform の state は、クラウド全体の地図であり、大量のシークレットの置き場でもあります。そしてデフォルトでは、パブリックなエンドポイントの向こうに置かれています。私たちがゼロからリモート state をブートストラップし、プライベートエンドポイントの背後に置き、VPN ゲートウェイの税を払う代わりにゼロトラストのコネクター経由でアクセスするようにした方法を紹介します。その間、一度も自分たちを締め出すことはありませんでした。

June 21, 2026

パスワードリセットなしでユーザーを移行する

「全員がパスワードをリセットする」のは移行時の選択であって、物理法則ではありません。ID プロバイダーを乗り換えるときに、ユーザーの既存のパスワードハッシュを引き継いで切り替えを誰にも気づかせない方法と、それが本当にできない唯一のケースを紹介します。

June 20, 2026

機能税:コストゼロのスイッチを入れるためにお金を払うのはもうやめよう

認証業界が課金しているのはコストではなく、許可です。SSO、MFA、プロビジョニングといった、提供コストが実質ゼロの機能を、プランの壁や接続単位の料金の向こうに閉じ込めています。料金ページが、あなたに決して気づいてほしくない区別についてお話しします。

June 18, 2026

セルフホストの Duende を離れる:何が移行でき、何を運用しなくてよくなるのか

セルフホストの Duende IdentityServer からマネージドな認証へ移行する。SQL の設定と ASP.NET Identity から実際に何が移行できるのか、そして背負わなくてよくなる運用コストについて。

June 16, 2026

Auth0 から離れる:実際に移せるもの、そして Auth0 が渡してくれない唯一のもの

Auth0 からの移行に実際に何が伴うのかを実践的に見ていきます。簡単な部分、手間のかかる部分、そして Auth0 が本当に渡してくれない 1 つのものについてです。