OAuth認証はあった!あるいはSASLのXOAUTH2/OAUTHBEARERについて

はじめに

本記事はDigital Identity技術勉強会 #iddance Advent Calendar 2025の12日目の記事です。

この手のネタは炎上が怖い?少しぐらい燃えても大丈夫です。みんなであったまりましょう。

ってことなので今年も逆張りクソ野郎行為をします。が翌日の13日はこのシリーズでは珍しく逆張りクソ野郎行為をしません。そちらもぜひよろしくお願いします。

メールの文脈で「OAuth認証」と呼ばれるものがある

SMTPIMAPのサーバーがユーザーを認証するための機能をとりまとめたフレームワークとしてSimple Authentication and Security Layer(SASL)というものがあります。一般に我々がMUA(mail user agent)SMTPIMAPのサーバーに接続し認証するときにユーザー名とパスワードで認証しますが、歴史的にはTLS上での LOGIN (Base64化したusername + password) あるいは PLAIN で認証を行ってきました。場合によっては CRAM-MD5DIGEST-MD5 などのchallenge-response方式での認証を行っていたり、 NTLMGSSAPI (Kerberos) を使っている設定もあるでしょう。認証を少しでも触ったことのある人からすれば LOGINPLAIN を使っている場合に当然気になることとしては通信路の安全性が保証されなかった場合(TLSを使っていなかった場合)パスワードが生で通信路に出て行っていることでしょう。そこでOAuthを使うと(以下このアドカレに興味を持つような人なら1000回くらい聞いてるアレ

というわけで、SASLにもOAuthのトークンを使って「認証」する方法があります。Gmail(とMicrosoft)がサポートしている方式としてXOAUTH2RFCになっている方式(だがGmailのサポートがない)方式としてOAUTHBEARERという方式があります。

どちらもBase64で認証されるべきユーザー識別子とBearerトークンをセットで渡しているという点ではだいたい同じといえるでしょう。Base64する前のClientが発する値はXOAUTH2における例では user=someuser@example.com^Aauth=Bearer ya29.vF9dft4qmTc2Nvb3RlckBhdHRhdmlzdGEuY29tCg^A^A 、OAUTHBEARERにおける例では n,a=user@example.com,^Ahost=server.example.com^Aport=143^Aauth=Bearer vF9dft4qmTc2Nvb3RlckBhbHRhdmlzdGEuY29tCg==^A^A で、認証されるべきユーザー識別子とBearerトークンが渡っていることが見て取れると思います。

あれ?OAuth認証ってダメなんじゃなかったっけ??メールはinsecure!SMTPをやめろ!!

最後の部分言いたいだけじゃないのっていうのは置いといて*1

例によってこのアドカレに興味持つ人はなんでOAuth認証がダメかって話は500回くらい聞いてると思いますがそうでない方向けにはTwitterOAuth認証って書くとやってくる人が丁寧に解説してる『OAuth認証とは何か?なぜダメなのか - 2020冬』という記事があるのでそちらに譲ります。

「OIDCと違ってIDトークンを返してこないからSMTPサーバーは誰が認証されたか確証が持てないじゃないか!メールにおけるOAuth認証はニセモノ!」ってなってしまうと思うのですが、例の記事における

ID連携のためには「●●でログイン」と言う認証イベントを実施したユーザーの情報を "安全に" やりとりする仕組みが必要

OpenID ConnectではOAuth認証で独自実装になり得る部分を標準化仕様としてサポートしているのでご利用ください

っていうところが重要です。

  • 一般にメールサーバーと認証を行うOAuthのAuthorization Serverはfirst party(同一の主体が動かしている、どころか同一システムであることが多い)
  • SASLが求めるのはユーザー識別子とBearerトークン(+α)を提示して認証されたかどうかを返すこと
    • というよりも接続が行われるかどうかを判定すること、認証失敗したら接続が不成立になる
    • SASLの方式の定義としてはResource Serverとの喋り方は定義している(このへんはOIDCにおいてID TokenやUserInfo Endpointが標準化されているのと似ている)
    • がResource ServerとAuthorization Serverの間でどういうやり取りが行われるかは実装依存

という性質から、MUA(メールソフト)、MTA/Mailbox(いわゆるメールサーバー)の視点から見ればこれは「OAuth認証」と呼んでも差し支えないものなのではないでしょうか?

一方で標準もちょっとお茶を濁しているところがある

XOAUTH2あるいはOAUTHBEARERを実装しているメールサーバーはOAuthにおけるResource Serverの立場で、クライアントはOAuthによってこのResource ServerのAPIへの認可を得ている(に過ぎない)、というのがOAuthが提供する機能です。また、Resource ServerとAuthorization Serverの間のやり取りについても、RFC 7628は The server validates the response とか The server fully validates the client response とか(どちらも"3.2. Server's Response")書いてあるものの、与えられたユーザー識別子とBearer tokenをどのように対応づけるかについては言及しておらず、RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token Usageにある方式に則って、とは書いてあるものの、RFC 6750はBearer Tokenというのが何であるかは書いてあってもBearer Tokenをユーザー識別子にこのように変換せよということは書いていません。そういう意味では

OAuth認証で独自実装になり得る部分を標準化仕様としてサポートして

いないと言えるかもしれません。

でもこの手のインターフェースが標準化されていてほしいのはthird partyでの認証連携のケースであって、メールのユースケースでは基本的にfirst partyだからセキュリティ境界である部分のMUA-MTA/Mailbox間だけどうにかなってればいい、ということで終わりなのかもしれないが…。

じゃあfirst-partyの中身については実際どう実装されてんの、OSSだったらわかるでしょ?

JPAAWG 8th General Meetingのセッション『メール送信時のトークンベース認証(XOAUTH2)とその可能性』Postfix/DovecotとKeycloakで接続する例が示されていますが、Keycloakに問い合わせる先のURLは…

introspection_url = http://localhost:8080/realms/mail/protocol/openid-connect/token/introspect

>>> openid-connect <<<

まとめ

OAuth認証あったかもしれない。いや実はその限りではないかも。

どちらにせよ、SASLのXOAUTH2やOAUTHBEARERが開く可能性はけっこう馬鹿にできなくて、OAuthのトークンを払い出す部分は別にID+パスワードじゃなくてもよくなる、という点は明確に嬉しい点です。ほら、MTA/MailboxがAuthorization Serverに対して「OAuth認証」してくれればAuthorization ServerはPasskeyでユーザーを認証できるようになるんですよ、嬉しくないですか?

参考

*1:本当はこういう意味で「SMTPをやめろ」というフレーズを用いているのではない。「SMTPをやめろ」とは何であるかはこの記事のスコープを逸脱するので詳細は割愛するが、最近は「Eメールはデジタルアイデンティティのアキレス腱」という(一部のスコープをカバーする)言い換えも使うようになった。私はSMTPに問題があるからっていってSMTPを使ってる人・持ち上げてる人を鍵垢でRTして晒し上げるタイプのインターネット論者じゃないんですよ…