【図解】SAML・OAuth 2.0・OpenID Connectの違いとは?使い分けと、SAMLでシングルサインオンするしくみを初心者向けに解説

OpenID Connect の記事の最後で、次は SAML・OAuth・OpenID Connect の違いを整理すると書きました。Entra ID でエンタープライズアプリのシングルサインオンを設定しようとすると、方式の選択肢に SAML と OpenID Connect が並んでいます。この記事では、3つが何に答えるしくみなのかを並べたうえで、このシリーズでまだ扱っていなかった SAML のしくみを、仕様と Microsoft(Entra ID)のドキュメントで確かめながら、最初の準備から一歩ずつ図にしました。

この記事でわかること
  1. OAuth 2.0 は認可、OpenID Connect と SAML は認証(サインイン)のしくみ
  2. SAML と OpenID Connect で、片方でしかできない(難しい)こと
  3. SAML の登場人物(IdP・SP)と、アサーションに入っているもの
  4. SAML でシングルサインオンするときの流れと、アプリが確かめること
  5. Entra ID で SAML のシングルサインオンを設定するときに交換する値
  6. 新しいアプリは OpenID Connect、SAML はアプリや相手が求めるときに選ぶ

まずはたとえで:紹介状・名札・部屋の鍵

会社の受付で身分証を見せると、受付が3種類のものを出してくれるとします。1つ目は、取引先の会社あてに「この人は営業部の田中さんで、何時に本人確認をしました」と書いて封をし、印を押した紹介状です。2つ目は、社内の会議に出るための名札です。3つ目は、決まった部屋に入るための鍵です。

社員本人確認受付(IdP・OP)紹介状 = SAML アサーションあて先の会社(Audience)有効な時間(NotOnOrAfter)封と印(XML 署名)名札 = ID トークン(OIDC)この会議用(aud)今日だけ(exp)受付の印(署名)部屋の鍵 = アクセストークン入れる部屋(scope)見るのは部屋(API)誰の鍵かは書いていない3つとも受付(IdP・OP)が出す違うのは、誰に見せるか・何に使うかSAML は XML、OIDC は JSON で書くSAML と OIDC は「この人は誰か」を伝え、OAuth は「何をしてよいか」を渡す
図1 紹介状(SAML)・名札(OpenID Connect)・部屋の鍵(OAuth 2.0)

SAML のアサーションは紹介状、OpenID Connect の ID トークンは名札、OAuth 2.0 のアクセストークンは部屋の鍵にあたります。紹介状と名札は「この人は誰か」を相手に伝えるもので、鍵は「どこに入ってよいか」を渡すものです。紹介状と名札は、伝える中身はよく似ていますが、書き方が違います。SAML は XML で書き、OpenID Connect は JSON(JWT)で書きます。

3つの違い

答える問いが違う

OAuth 2.0(RFC 6749)は、アプリが API を使うための権限を、利用者に代わって受け取るしくみです(OAuth 2.0 の記事)。答えるのは「このアプリに何をさせてよいか」で、これを認可と呼びます。OpenID Connect と SAML が答えるのは「誰がサインインしたか」で、これは認証です。どちらも、1回のサインインで複数のアプリを使えるようにするシングルサインオン(SSO)に使われます。

OAuth 2.0答える問い何をさせてよいか出すものアクセストークン形式仕様では決めていない見る相手API(リソースサーバ)仕様RFC 6749(2012年)OpenID Connect答える問い誰がサインインしたか出すものID トークン形式JWT(JSON)見る相手アプリ(RP)仕様OIDC Core 1.0(2014年)SAML 2.0答える問い誰がサインインしたか出すものアサーション形式XML見る相手アプリ(SP)仕様OASIS SAML 2.0(2005年)認可(権限を任せる)認証(サインイン・シングルサインオン)OIDC と SAML は同じ問いに答える。OAuth は別の問い(認可)に答える
図2 OAuth 2.0・OpenID Connect・SAML が答える問い
項目OAuth 2.0OpenID ConnectSAML 2.0
目的認可(API を使う権限)認証(サインイン)認証(サインイン)と属性の受け渡し
出すものアクセストークンID トークン(+アクセストークン)アサーション
形式仕様では決めていない(Entra ID は JWT)JWT(JSON)XML
署名形式によるJWS(RS256 など)XML 署名
設定の共有この RFC では決めていないDiscovery(JSON)メタデータ(XML)
SPA・モバイル使える(PKCE を使う)向いている扱いにくい
仕様IETF の RFC 6749(2012年)OpenID Foundation の OIDC Core 1.0(2014年)OASIS の SAML 2.0(2005年)

OpenID Connect は OAuth 2.0 の上に作られた「ID の層」なので、サインインと同時にアクセストークンももらえます。SAML は OAuth 2.0 とは別に作られたしくみで、SAML のアサーションはアプリ(SP)あてのものです。SAML でサインインしたアプリが API を呼ぶには、別にアクセストークンが要ります。Microsoft は、SAML のアサーションを OAuth 2.0 のアクセストークンに引き換える流れ(SAML bearer assertion flow)も用意していますが、これは別の流れとして扱われています。

サインインの結果の届け方が違う

もう1つの大きな違いは、サインインの結果がアプリにどう届くかです。SAML でよく使う HTTP POST のやり方では、署名つきのアサーションそのものが、ブラウザを通ってアプリに届きます。OpenID Connect の認可コードフローでは、ブラウザを通るのは認可コードだけで、ID トークンはアプリのサーバが Entra ID から直接受け取ります。

SAML(HTTP POST で届ける)IdP(Entra ID)ブラウザアプリ(SP)アサーション(署名つき)POST で渡す中身はそのままOpenID Connect(認可コードフロー)OP(Entra ID)ブラウザアプリ(RP)認可コードコードを渡すコードを引き換える(サーバどうし)ID トークンSAML はアサーションそのものがブラウザを通る。だから署名が欠かせない
図3 サインインの結果の届け方

ブラウザを通るものは、途中で書き換えられるおそれがあります。そのため SAML のプロファイル(使い方の決まり)は、HTTP POST で届けるアサーションには署名を必須にしています。アプリ(SP)は、署名と中身の両方を確かめてから使います。SAML には、アサーションを裏でサーバどうしで取りに行く「アーティファクト」という方式もありますが、Entra ID はこれに対応していません。

SAML と OpenID Connect、片方でしかできないこと

SAML と OpenID Connect は、どちらも「誰がサインインしたか」をアプリに伝えるしくみです。ブラウザで Web アプリにシングルサインオンするだけなら、どちらでもできます。差が出るのはその外側で、「API も呼ぶか」「どんな種類のアプリか」「つなぐ相手が何に対応しているか」の3つです。

OIDC ならできる(SAML では難しい)API のトークンも一緒にもらうSAML は別の流れで引き換えが要るSPA・モバイルアプリのサインインSAML はブラウザが ACS に POST する前提Microsoft のライブラリで組み込むMSAL などは OIDC 用。SAML 用はないMicrosoftマルチテナントのアプリSAML は単一テナントかギャラリーだけMicrosoftSAML ならできる(OIDC では難しい)SAML にしか対応しない相手とつなぐ企業向け SaaS・既存の IdPIdP から要求なしで送るOIDC はアプリに要求を出し直させるアサーションを暗号化するSAML アプリで設定できる(P1・P2)Microsoft暗号化は、仕様では OIDC のID トークンもできる(JWE)ブラウザで Web アプリにシングルサインオンするだけなら、どちらでもできる差が出るのは「API・アプリの種類・つなぐ相手」。SAML を選ぶ理由の多くは相手の都合
図4 SAML と OpenID Connect で、片方でしかできない(難しい)こと
やりたいことOpenID ConnectSAML理由
Web アプリへのシングルサインオンできるできるどちらも「誰か」を署名つきでアプリに伝える
サインインと一緒に API のトークンをもらうできる(1回の要求で ID トークンとアクセストークン)できない。別の流れで引き換えるOIDC は OAuth 2.0 の上に作られている。SAML のアサーションはアプリ(SP)あて
SPA・モバイルアプリのサインイン向いている扱いにくいSAML は、サーバの ACS URL へのブラウザの POST が前提。Microsoft も SPA・モバイルには OIDC が必要としている
IdP の画面(マイアプリなど)から開くIdP がアプリに転送し、アプリが要求を出し直す要求なしでアサーションを送れるSAML は要求なしの応答を決めている。OIDC はアプリに要求を出させる
SAML にしか対応しない SaaS や IdP とつなぐできないできるSAML だけに対応するアプリや IdP がある
中身を暗号化する仕様ではできる(JWE)できる。Entra ID では SAML アプリに設定できる(P1・P2)Entra ID の管理画面のトークンの暗号化は、SAML のアプリだけが対象
Entra ID でマルチテナントのアプリにするできるできないEntra ID の SAML は、単一テナントかギャラリーのアプリだけ
Microsoft のライブラリで組み込むMSAL・Microsoft.Identity.Web があるないMicrosoft は SAML の開発用ライブラリを出していない

並べてみると、SAML にしかない機能は多くありません。SAML の強みは、企業向けの SaaS や既存の IdP で広く使われていて、相手がすでに対応していることです。逆に、API を呼ぶアプリや、SPA・モバイルアプリをこれから作るなら、OpenID Connect(と OAuth 2.0)でないと組み立てにくくなります。この使い分けは、後の「どれを選ぶか」でもう一度まとめます。

SAML の基本の形(OASIS SAML 2.0)

ここからは、標準(OASIS の SAML 2.0)で決まっている一般的な話です。SAML(Security Assertion Markup Language)は、組織どうしでセキュリティの情報をやり取りするための、XML の枠組みです。

登場人物と用語

SAML では、利用者を認証して「この人は誰か」を述べる側を IdP(アイデンティティプロバイダ)、その内容を受け取って使うアプリを SP(サービスプロバイダ)と呼びます。OpenID Connect の OP と RP にあたります。IdP と SP は、お互いを識別子(Entity ID)で見分けます。

IdP(アイデンティティプロバイダ)識別子(Entity ID)IdP の名前。Issuer に入るSSO サービスの URLAuthnRequest の送り先署名用の秘密鍵アサーションに署名利用者(ブラウザ)要求も応答もブラウザが運ぶSP(サービスプロバイダ)識別子(Entity ID)SP の名前。Audience に入るACS URLアサーションの受け口IdP の証明書(公開鍵)署名を確かめるメタデータ(XML)で設定を交換するバインディング:メッセージの運び方。要求は HTTP Redirect(URL に入れる)、応答は HTTP POST(フォーム)が多いRelayState:要求と一緒に送り、応答で戻ってくる値。サインイン後に開くページを伝えるのに使うSAML では、ID を出す側を IdP、アサーションを受け取るアプリを SP と呼ぶ
図5 SAML の登場人物と用語
用語意味
アサーションIdP が利用者について述べた XML の文書。SAML の中心になるもの
AuthnRequestSP が IdP に「この利用者を認証してほしい」と頼む要求
ResponseIdP の応答。成功するとアサーションが入っている
識別子(Entity ID)IdP や SP の名前。URL の形をしていることが多い
ACS URLAssertion Consumer Service の URL。SP がアサーションを受け取る窓口
バインディングSAML のメッセージを HTTP にどう載せるかの決まり(HTTP Redirect、HTTP POST など)
メタデータ識別子・URL・証明書などの設定を、IdP と SP の間で共有するための XML
RelayState要求と一緒に送り、応答で戻ってくる値。サインイン後に開くページを伝えるのに使う

アサーションの中身

アサーションには、3種類の文(ステートメント)を入れられます。いつ・どの方法で認証したかを示す認証の文、名前やメールなどを示す属性の文、そして認可の決定の文です。シングルサインオンでよく使うのは、認証の文と属性の文です。

Response(応答)ID・InResponseTo・Destination・Status(成功か)Assertion(アサーション)= IdP が「この人は誰か」を述べた文書Issuer出した IdP の識別子SignatureIdP の秘密鍵による XML 署名SubjectNameID:利用者を表す値SubjectConfirmation(bearer):Recipient=ACS URL・NotOnOrAfter・InResponseToConditionsNotBefore・NotOnOrAfter:使える時間AudienceRestriction:Audience=SP の識別子AttributeStatement属性:名前・メール・グループなどAuthnStatementAuthnInstant:いつ認証したかAuthnContextClassRef:どの方法で認証したか※ 文は3種類:認証(AuthnStatement)・属性(AttributeStatement)・認可の決定(使う場面は少ない)アサーションは「誰が・いつ・どう認証され・どの SP あてか」を、署名つきの XML で伝える
図6 アサーションの中身

このうち、アプリが特に気にするのが Subject と Conditions です。Subject の NameID が「誰か」を表し、SubjectConfirmation には、受け取り先の ACS URL(Recipient)、届けてよい期限(NotOnOrAfter)、どの要求への答えか(InResponseTo)が入ります。Conditions には、使ってよい時間と、どの SP あてか(Audience)が入ります。

OpenID Connect の ID トークンと並べると、名前は違っても、同じ役目のものがそろっています。

役目SAML アサーションID トークン(OIDC)出した相手Issueriss誰あてかAudienceaud利用者NameIDsub使える期限NotOnOrAfterexp要求との結びつきInResponseTononce認証した時刻AuthnInstantauth_time認証の方法AuthnContextClassRefacr・amr利用者の情報Attributename などのクレーム署名XML 署名JWS(RS256 など)書き方は違うが、アプリが確かめることはよく似ている
図7 SAML アサーションと ID トークンの対応

基本の流れ(SP から始める場合)

SAML の使い方の決まり(プロファイル)のうち、ブラウザでシングルサインオンするものを Web Browser SSO プロファイルと呼びます。利用者が先にアプリ(SP)を開く場合の、基本の流れは次のとおりです。

利用者(ブラウザ)SP(アプリ)IdP(SSO サービス)(A) アプリを開く(B) IdP へ転送(302・303)AuthnRequest を URL に入れる(C) AuthnRequest を届ける(D) 利用者を確かめるセッションがなければサインインさせる(E) アサーションを作って署名し、自動で送るフォームを返す(F) Response をブラウザへ(F) ACS URL に POSTResponse(アサーション入り)(G) 確かめて、使ってよいか判断SP のセッションを作る要求も応答もブラウザが運ぶ。SP と IdP は直接話さない
図8 SAML の基本の形(Web Browser SSO、SP から始める場合)

SP は AuthnRequest を作り、ブラウザを IdP へ転送します(HTTP Redirect)。IdP は利用者を確かめ、すでに IdP にサインインしていればそのまま、まだならサインインさせます。IdP はアサーションを作って署名し、自動で送信されるフォームをブラウザに返します。ブラウザがそのフォームを SP の ACS URL に POST し、SP は中身を確かめてセッションを作ります。この流れでは、SP と IdP は直接通信しません。

SP が確かめること

Web Browser SSO プロファイルは、SP が受け取ったアサーションで確かめることを決めています。

署名IdP の証明書(公開鍵)で確かめる発行者Issuer が、信頼する IdP の識別子かあて先Audience に、自分(SP)の識別子がある受け取り先Recipient が、受け取った ACS URL と同じ期限NotOnOrAfter を過ぎていない要求との対応InResponseTo が、送った要求の ID と同じIdP から始める場合(要求なしで届く応答)は、InResponseTo が入らない。どれか1つでも合わないアサーションは捨て、セッションを作らない本物で、自分あてで、今届いた、自分の要求への答えのときだけ受け入れる
図9 SP がアサーションで確かめること
  • 署名:アサーション(または応答)の署名を、IdP の証明書の公開鍵で確かめます。
  • 受け取り先と期限:Recipient が、そのアサーションを受け取った ACS URL と同じか。NotOnOrAfter を過ぎていないか。
  • 要求との対応:InResponseTo が、自分が送った AuthnRequest の ID と同じか。OpenID Connect の nonce と似た役目です。
  • あて先と発行者:アサーションには SP の識別子を入れた Audience が必ず入ります。自分あてかどうかと、信頼している IdP が出したものか(Issuer)を確かめます。

どれか1つでも合わないアサーションは捨て、セッションを作りません。アプリを作る側は、これらの確認を自分で XML を読んで書くのではなく、SAML に対応した製品やライブラリの機能に任せます。

ここからは Microsoft(Entra ID)の場合です

ここからは、Entra ID を IdP にして、業務で使う SaaS アプリ(SP)に SAML でシングルサインオンする場合を見ていきます。Entra ID では、SaaS アプリを「エンタープライズアプリ」として登録し、そこで SAML を設定します。

誰が何を持つか

利用者(ブラウザ)SaaS アプリ(SP)Entra ID(IdP)管理者パスワードなどEntra ID にだけ入力Entra ID のセッションSSO に使う Cookieアプリのセッションサインイン後の CookieSP の識別子Entity ID(自分の名前)応答 URL(ACS)アサーションの受け口Entra ID の証明書公開鍵だけ。署名を確かめるログイン URL・識別子要求の送り先・Issuer利用者のアカウントNameID で結びつけるエンタープライズアプリ識別子・応答 URL を登録署名用の秘密鍵アプリごと・既定3年割り当て使える人・グループ属性とクレームNameID などの中身利用者の情報認証して ID を出すEntra 管理センターSAML の設定・割り当てアプリの管理画面Entra ID の値を登録通知メール証明書の期限が近い秘密鍵は Entra ID の中だけ。SP は証明書(公開鍵)だけを持って署名を確かめる
図10 誰が何を持つか(Entra ID と SaaS アプリの場合)

Entra ID は、アサーションに署名する秘密鍵を、エンタープライズアプリごとに持ちます。OpenID Connect や OAuth 2.0 のトークンは Entra ID で共通の証明書で署名されますが、SAML の署名用の証明書はアプリごとに作られるのが違いです。SaaS アプリは、その証明書(公開鍵)だけを持ち、届いたアサーションの署名を確かめます。

準備の流れ

サインインの前に、管理者が Entra ID とアプリの両方に値を登録します。お互いの「名前(識別子)」「受け口(URL)」「確かめる鍵(証明書)」を交換する作業です。

管理者SaaS アプリ(管理画面)Entra ID① エンタープライズアプリを追加ギャラリーから、または独自のアプリ② シングルサインオンで SAML を選ぶ③ アプリの管理画面で操作:SAML の設定を開く④ SP の識別子・ACS URL画面に表示される値を控える⑤ 基本的な SAML 構成に登録識別子・応答 URL・サインオン URL⑥ 署名用の証明書秘密鍵は Entra ID の中既定で3年有効⑦ 証明書・ログイン URL・識別子証明書は公開鍵だけ。秘密鍵は渡らない⑧ アプリの管理画面で操作:⑦を登録ログイン URL・識別子・証明書⑨ アプリの管理画面で操作:アカウントNameID と同じ値で利用者を用意⑩ 利用者・グループを割り当てる使える人を決めるEntra ID は SP の識別子と ACS URL を、SP は Entra ID の識別子・URL・証明書を持ったサインインの前に、お互いの「名前・受け口・確かめる鍵」を交換しておく
図11 準備の流れ(①〜⑩)
手順誰が・どこで何をするか鍵(物)はどうなるか・使う鍵
①管理者・Entra 管理センターエンタープライズアプリを追加するアプリの入れ物ができる。まだ鍵はない
②管理者・Entra 管理センターシングルサインオンの方式で SAML を選ぶ―
③管理者・アプリの管理画面SAML の設定ページを開く―
④アプリ → 管理者SP の識別子と ACS URL を表示するSP の名前と受け口を控える
⑤管理者・Entra 管理センター識別子・応答 URL・サインオン URL を登録するEntra ID が SP の名前と受け口を持つ
⑥Entra ID署名用の証明書を作る秘密鍵は Entra ID の中にだけある。既定で3年有効
⑦Entra ID → 管理者証明書・ログイン URL・識別子をダウンロード・コピーする証明書は公開鍵だけ。秘密鍵は渡らない
⑧管理者・アプリの管理画面⑦の値と証明書を登録するアプリが Entra ID の証明書(公開鍵)を持つ
⑨管理者・アプリの管理画面利用者のアカウントを用意するNameID と同じ値で、アプリ側の利用者と結びつける
⑩管理者・Entra 管理センター利用者・グループを割り当てる割り当てた人がこのアプリを使える

サインインの流れ

準備ができたら、利用者がアプリを開いたところから、サインインが終わるまでを見ます。Entra ID は、要求(AuthnRequest)を HTTP Redirect で受け取り、応答(Response)を HTTP POST でアプリに届けます。

利用者(ブラウザ)SaaS アプリ(SP)Entra ID(IdP)ブラウザ経由の要求(⑪〜⑭)Entra ID の中(⑮〜⑰)ブラウザ経由の応答(⑱〜㉒)⑪ ページを開くサインインが要るページ⑫ AuthnRequest を作るID を覚えておく⑬ Entra ID へ転送(302)SAMLRequest・RelayState⑭ GET ログイン URLSAMLRequest を届ける⑮ どのアプリか探すIssuer = 登録した識別子ACS URL = 登録した応答 URL⑯ サインインさせる多要素認証・割り当て⑰ アサーションを作るAudience・RecipientInResponseTo = ⑫の IDアプリ用の秘密鍵で署名⑱ 自動で送るフォームSAMLResponse(と RelayState)⑲ POST 応答 URL(ACS)SAMLResponse・RelayState⑳ アサーションを確かめる署名(⑧で登録した証明書)Issuer・Audience・Recipient・期限InResponseTo = ⑫の ID㉑ セッションを作るNameID で⑨のアカウントを探す㉒ ページを返すアサーションはブラウザを通って届く。SP は署名と「自分あて・今・この要求」を確かめる
図12 サインインの流れ(SP から始める場合、⑪〜㉒)
手順誰が・どこで何をするか鍵(物)はどうなるか・使う鍵
⑪利用者・ブラウザサインインが要るページを開くまだアプリのセッションはない
⑫アプリAuthnRequest を作り、その ID を覚えるID は⑳で InResponseTo と比べる
⑬アプリ → ブラウザEntra ID のログイン URL へ転送するSAMLRequest と RelayState を URL に入れる
⑭ブラウザ → Entra IDログイン URL を開き、要求を届ける要求には⑤で登録した識別子が Issuer として入る
⑮Entra IDどのアプリの要求かを探すIssuer と識別子、ACS URL と応答 URL が合うか
⑯Entra ID利用者をサインインさせる多要素認証や割り当てを確かめる
⑰Entra IDアサーションを作って署名する⑥のアプリ用の秘密鍵で署名する
⑱Entra ID → ブラウザ自動で送信されるフォームを返すアサーション入りの SAMLResponse がブラウザに来る
⑲ブラウザ → アプリ応答 URL(ACS)に POST するアサーションはそのまま運ばれる
⑳アプリアサーションを確かめる⑧で登録した証明書(公開鍵)で署名を確かめる
㉑アプリNameID で利用者を探し、セッションを作るCookie を発行する
㉒アプリ → ブラウザページを返す以降はアプリのセッションで使う

⑯で Entra ID にサインインしたあとは、Entra ID のセッションが残ります。ほかのアプリでも同じように⑪から始めると、⑯でサインインの画面を出さずに進めます。これがシングルサインオンです。

IdP から始める場合(マイアプリから開く)

SAML では、アプリからではなく、IdP から始めることもできます。Entra ID では、マイアプリの画面でアプリのタイルを選ぶ使い方です。このとき Entra ID は、要求なしでアサーションをアプリに送ります。

利用者(ブラウザ)Entra ID(マイアプリ)SaaS アプリ(SP)❶ タイルを選ぶマイアプリの画面❷ サインイン済みか確かめるまだなら、ここでサインイン❸ アサーションを作るInResponseTo は入れないアプリ用の秘密鍵で署名❹ 自動で送るフォームSAMLResponse(とリレー状態)❺ POST 応答 URL(ACS)SAMLResponse❻ アサーションを確かめる署名・Issuer・AudienceRecipient・期限InResponseTo はない❼ セッションを作るリレー状態か既定のページへ❽ ページを返すサインオン URL を設定していると、タイルはアプリの画面に移り、最初の図(SP から始める流れ)になる要求(AuthnRequest)がなく、Entra ID から始まる。InResponseTo では照合できない
図13 IdP から始める場合の流れ(❶〜❽)
項目最初の図(SP から始める)この図(IdP から始める)
始まり利用者がアプリを開く利用者がマイアプリでタイルを選ぶ
AuthnRequestアプリが作って送る(⑫〜⑭)ない
InResponseTo入っていて、⑫の ID と比べる入っていない(入れてはいけない)
開くページRelayState で戻るリレー状態の値か、アプリが決めた既定のページ
Entra ID の設定サインオン URL を設定するサインオン URL を空にする

要求がないので、アプリは「自分が頼んだ答えか」を InResponseTo では確かめられません。署名・Audience・Recipient・期限の確認がより大事になります。アプリが SP から始める流れに対応していれば、そちらを使う設定にしておくと、図12の流れになります。

設定の手順(Entra ID)

エンタープライズアプリを追加し、SAML を選ぶ(図11の①②)

Microsoft Entra 管理センターで Entra ID ›› Enterprise apps ›› All applications を開き、アプリを追加します。ギャラリーにあるアプリは名前で探し、ない場合は Create your own application から、ギャラリーにないアプリとして作ります。作業にはクラウドアプリケーション管理者などのロールが要ります。

追加したアプリの Single sign-on を開き、方式で SAML を選びます。SAML のシングルサインオンを設定できるのは、単一テナントのアプリかギャラリーのアプリだけで、マルチテナントのアプリでは選べません。ギャラリーのアプリには、アプリごとの設定ガイドが用意されているので、値はそれに従います。

SP の値を Entra ID に登録する(図11の③〜⑤)

アプリの管理画面で SAML の設定ページを開き、SP の識別子(Entity ID)と ACS URL を確かめます。その値を、Entra ID の Basic SAML Configuration(基本的な SAML 構成)に写します。

Entra ID の SAML の設定SaaS アプリの SAML の設定Basic SAML ConfigurationSP の情報(アプリが表示)識別子(Entity ID)SP の Entity ID④→⑤応答 URL(ACS URL)ACS URL④→⑤サインオン URLSP から始めるときSP-initiated のログイン URL④→⑤SAML Certificates・Set up(アプリ名)IdP の情報(管理者が入力)証明書(Base64 など)IdP の証明書⑦→⑧ログイン URLIdP の SSO の URL⑦→⑧Microsoft Entra 識別子IdP の Entity ID(Issuer)⑦→⑧アプリのフェデレーションメタデータ URLメタデータの URL読み込めるアプリだけ⑦→⑧名前(識別子)・受け口(URL)・鍵(証明書)を、お互いに写し合う
図14 Entra ID と SaaS アプリで交換する値
Entra ID の項目入れる値
識別子(Entity ID)SP の Entity ID。AuthnRequest の Issuer と完全に一致させる。テナントの中で重複できない
応答 URL(ACS URL)SP の ACS URL。Entra ID はここにアサーションを POST する
サインオン URLSP から始めるときの、アプリのサインインページ
リレー状態・ログアウト URLアプリが求めるときだけ設定する

証明書と Entra ID の値をアプリに登録する(図11の⑥〜⑧)

Entra ID は、SAML を設定したアプリに、署名用の自己署名証明書を自動で作ります。有効期間は既定で3年で、署名は既定で SHA-256 を使います。SAML Certificates の欄から、証明書(Base64 または Raw)か、フェデレーションメタデータ XML をダウンロードします。Set up(アプリ名)の欄には、ログイン URL と Microsoft Entra 識別子が表示されます。

アプリの管理画面に、ログイン URL(IdP の SSO の URL)、Microsoft Entra 識別子(IdP の Entity ID)、証明書を登録します。アプリがメタデータを URL から読み込める場合は、「アプリのフェデレーションメタデータ URL」を渡すと、証明書が変わったときにアプリ側で取り直せます(アプリが対応している場合)。この URL は次の形です。

アプリのフェデレーションメタデータ URL の形(図11の⑦)

https://login.microsoftonline.com/{tenant-id}/federationmetadata/2007-06/federationmetadata.xml?appid={appId}

証明書には期限があります。Entra ID は、期限の60日前・30日前・7日前に通知メールを送ります。通知先は既定ではアプリを追加した管理者だけで、5つまで追加できるので、担当者が替わっても届くよう配布リストを入れておくと安心です。更新するときは、新しい証明書を作って(まだ有効にしない)アプリに登録し、そのあとで Entra ID 側で有効にします。

利用者を用意して割り当てる(図11の⑨⑩)

多くのアプリでは、シングルサインオンを使う前に、アプリ側にも利用者のアカウントを作っておく必要があります。アプリは、アサーションの NameID を見て、どのアカウントでサインインさせるかを決めます。NameID に何を入れるか(ユーザー名、メールアドレスなど)は、Entra ID の「属性とクレーム」で、アプリが求める形に合わせます。

Entra ID 側では、アプリの Users and groups で、使う人やグループを割り当てます。アプリのプロパティで「割り当てが必要」を「はい」にしていると、割り当てのない人はサインインできません。グローバル管理者はこの確認の対象外なので、テストは実際に使う人のアカウントで行います。

テストして、要求と応答の中身を見る(図12の⑫〜⑳)

SAML の設定画面の「シングルサインオンのテスト」から、サインインを試せます。ここでは、Microsoft のドキュメントにある例で、要求と応答の中身を見ておきます。まず、アプリが送る AuthnRequest です。

AuthnRequest の例(図12の⑫)

<samlp:AuthnRequest
  xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
  ID="C2dE3fH4iJ5kL6mN7oP8qR9sT0uV1w"
  Version="2.0" IssueInstant="2013-03-18T03:28:54.1839884Z"
  xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
  <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://www.contoso.com</Issuer>
</samlp:AuthnRequest>

ID は、応答の InResponseTo に入って戻ってきます。Issuer は、Entra ID に登録した識別子と完全に一致している必要があります。要求に ACS URL(AssertionConsumerServiceURL)を入れる場合は、登録した応答 URL と同じでなければなりません。要求への署名は任意ですが、Entra ID 側で「署名された要求だけ受け付ける」設定にもできます。

次に、Entra ID が返すアサーションのうち、使える時間とあて先を示す部分です。

アサーションの Conditions の例(図12の⑰)

<Conditions NotBefore="2013-03-18T07:38:15.128Z" NotOnOrAfter="2013-03-18T08:48:15.128Z">
  <AudienceRestriction>
    <Audience>https://www.contoso.com</Audience>
  </AudienceRestriction>
</Conditions>

Audience には、AuthnRequest の Issuer と同じ値(アプリの識別子)が入ります。NotOnOrAfter は NotBefore の70分後です。Entra ID は、自分とアプリの時計のずれを見込んだ余裕を足さないので、アプリのサーバの時刻がずれていると、ここで失敗することがあります。アサーションの Issuer は https://sts.windows.net/ のあとにテナント ID が付いた値で、署名にはメタデータの IDPSSODescriptor にある鍵が使われます。

アサーションの AttributeStatement の例(図12の⑰)

<AttributeStatement>
  <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name">
    <AttributeValue>testuser@contoso.com</AttributeValue>
  </Attribute>
  <Attribute Name="http://schemas.microsoft.com/identity/claims/objectidentifier">
    <AttributeValue>3F2504E0-4F89-11D3-9A0C-0305E82C3301</AttributeValue>
  </Attribute>
  ...
</AttributeStatement>

name の属性には利用者のユーザー名(UPN)が、objectidentifier には Entra ID の中で変わらない利用者の ID が入ります。名前やメールアドレスは変わることがあるので、アプリで利用者を見分けるには変わらない値を使うのが安全です。

アサーションの AuthnStatement の例(図12の⑰)

<AuthnStatement AuthnInstant="2013-03-18T07:33:56.000Z" SessionIndex="_bf9c623d-cc20-407a-9a59-c2d0aee84d12">
  <AuthnContext>
    <AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef>
  </AuthnContext>
</AuthnStatement>

AuthnInstant は利用者が Entra ID で認証した時刻、AuthnContextClassRef は認証の方法です。複数の方法で認証したときは、いちばん強い方法が入ります。

どれを選ぶか

Entra ID は SAML も OpenID Connect も使えます。そのうえで Microsoft は、アプリが OpenID Connect と OAuth 2.0 に対応していればそちらを選び、対応していない既存のアプリには SAML を選ぶよう案内しています。

これから作るアプリのサインインOpenID ConnectSPA・モバイルアプリのサインインOpenID Connectサインインした人の代わりに API を呼ぶOAuth 2.0(アクセストークン)OIDC に対応していない既存の SaaSSAML取引先や規程が SAML を求めるSAMLEntra ID は SAML も OIDC も使える。ただし Microsoft は SAML の開発用ライブラリを出しておらず、新しく作るアプリには OIDC を勧めている迷ったら OIDC。SAML は、アプリや相手が SAML を求めるときに選ぶ
図15 どれを選ぶか

新しく作るアプリなら、OpenID Connect が第一の候補です。Microsoft は OpenID Connect 向けに MSAL や Microsoft.Identity.Web などのライブラリを出していますが、SAML のアプリを作るためのライブラリは出していません。SPA やモバイルアプリはブラウザや端末の中で動くので、JSON と REST で扱える OpenID Connect が向いています。一方で、SAML は企業向けの SaaS で長く使われていて、アプリが SAML にしか対応していない場合や、取引先や調達の条件で SAML が求められる場合には、SAML を選びます。

よくある間違い

間違いどうするか
SAML のアサーションで API を呼ぼうとするアサーションはアプリ(SP)あて。API を呼ぶには OAuth 2.0 のアクセストークンを使う
署名だけ確かめて、Audience や期限を見ない別の SP あてや期限切れのアサーションを受け入れてしまう。Recipient・Audience・期限・InResponseTo も確かめる
証明書の期限を誰も見ていない期限が切れるとアプリにサインインできなくなる。通知先に配布リストを入れ、更新の手順を決めておく
新しく作るアプリに、なんとなく SAML を選ぶ新しいアプリは OpenID Connect を使う。SAML はアプリや相手が求めるときに選ぶ
IdP から始める流れにしたいのに、サインオン URL を入れたままにするマイアプリのタイルがアプリのサインインページに移り、SP から始める流れになる

うまくいかないとき

エラー・症状意味確かめること
AADSTS750054要求に SAML の要求(SAMLRequest)が入っていないアプリが HTTP Redirect で AuthnRequest を送っているか。IdP から始める流れにしか対応していないアプリに、サインオン URL を入れていないか
AADSTS50011応答 URL が登録と合わない要求の AssertionConsumerServiceURL が、応答 URL の一覧にあるか
AADSTS700016アプリが見つからない要求の Issuer と、登録した識別子(Entity ID)が完全に一致しているか
AADSTS50105利用者がアプリに割り当てられていないUsers and groups の割り当て。グループなら、利用者が直接のメンバーか
アプリ側で署名エラーアプリが持っている証明書と、署名に使われた証明書が違う証明書を更新したあと、新しい証明書をアプリに登録したか。期限が切れていないか
アプリ側で時刻のエラーアサーションの使える時間の外と判断されたアプリのサーバの時刻がずれていないか

企業での例

場面やること押さえどころ
社員が業務の SaaS に Entra ID のアカウントでサインインするギャラリーからアプリを追加し、設定ガイドに沿って SAML を設定する識別子・応答 URL・証明書の交換と、証明書の期限の通知先
AD FS で SAML 連携していたアプリを Entra ID に移すアプリ側の IdP の設定(Issuer・SSO の URL・証明書)を Entra ID の値に替えるIssuer は https://sts.windows.net/ にテナント ID が付いた形になる
自社で新しく社内ポータルを作るOpenID Connect でサインインを組み込むMicrosoft のライブラリが使える。SAML は選ばない
ポータルに、サインインした人の予定も出すOAuth 2.0 で Graph のアクセストークンをもらうサインイン(ID トークン)と API(アクセストークン)の役目を分ける

まとめ

項目内容
答える問いOAuth 2.0 は「何をさせてよいか」(認可)。OpenID Connect と SAML は「誰がサインインしたか」(認証)
片方でしかできないことWeb アプリのシングルサインオンはどちらでもできる。API のトークン・SPA とモバイル・マルチテナント(Entra ID)は OIDC。SAML だけの相手とつなぐ・IdP から要求なしで送る・管理画面での暗号化(Entra ID)は SAML
書き方OpenID Connect は JSON(JWT)の ID トークン。SAML は XML のアサーション
届け方SAML はアサーションがブラウザを通って POST で届く。署名が必須
SP が確かめること署名・Issuer・Audience・Recipient・期限・InResponseTo
Entra ID の設定識別子・応答 URL を登録し、ログイン URL・識別子・証明書をアプリに渡す。証明書はアプリごとで既定3年
選び方新しいアプリ・SPA・モバイルは OpenID Connect。API は OAuth 2.0。SAML はアプリや相手が求めるとき

参考にした資料

この記事は、次の標準と公式ドキュメントで内容を確かめて書きました。仕様や対応状況は変わることがあるので、最新の情報はリンク先で確かめてください。

あとがき

3つを並べてみると、SAML と OpenID Connect は「誰か」を伝える点では同じで、違うのは書き方と届け方なのだと分かりました。とくに SAML は、アサーションがブラウザを通って届くので、署名と Audience・Recipient・期限の確認がそのまま安全を支えている、というところは図にしてみてはっきりしました。次の記事からは、API の通信そのものを守る TLS の話に進みます。

コメント