Exchange の ID トークンを検証する

重要

従来の Exchange ユーザー ID トークンとコールバック トークンは、Microsoft の Secure Future Initiative の一環として、2024 年 10 月にすべてのExchange Online テナントでオフになります。これにより、組織は現在の脅威の状況に対応するために必要なツールが提供されます。 Exchange ユーザー ID トークンは、引き続き Exchange オンプレミスで機能します。 入れ子になったアプリ認証は、今後のトークンに推奨される方法です。 詳細については、 入れ子になったアプリ認証と従来の Exchange トークンに関するブログ記事を参照してください。

使用している Outlook アドインから Exchange のユーザー ID トークンを送信できますが、要求を信頼する前に、トークンを検証して適切な Exchange サーバーからのものであることを確認する必要があります。 Exchange のユーザー ID トークンは、JSON Web トークン (JWT) です。 JWT の検証に必要な手順は、「RFC 7519 JSON Web Token (JWT)」に記載されています。

ID トークンの検証およびユーザーの一意識別子の取得は 4 つのステップで進めることをお勧めします。 まず、Base 64 URL 形式でエンコードされた文字列から、JSON Web トークン (JWT) を抽出します。 次に、トークンが整形式であること、使用する Outlook アドイン向けのトークンであること、有効期限が切れていないこと、および認証メタデータ ドキュメントの有効な URL を抽出できることを確認します。 その後、Exchange サーバーから認証メタデータ ドキュメントを取得し、ID トークンに添付されている署名を検証します。 最後に、ユーザーの Exchange ID と認証メタデータ ドキュメントの URL を連結して、ユーザーの一意の識別子を計算します。

JSON Web トークンを抽出する

getUserIdentityTokenAsync から返されたトークンは、トークンのエンコードされた文字列表現です。 この形式では、すべての JWT にピリオドで区切られた 3 つの部分があります (RFC 7519 ごと)。 形式は次のようになります。

{header}.{payload}.{signature}

ヘッダーとペイロードは、各部分の JSON 表現を取得するために、Base64 でデコードされる必要があります。 署名は、バイナリ シグネチャを含むバイト配列を取得するために、Base64 でデコードされる必要があります。

トークンの内容の詳細については、「Exchange の ID トークンの内部」を参照してください。

デコードされた 3 つのコンポーネントがあれば、トークンの内容の検証を進めることができます。

トークンの内容を検証する

トークンの内容を検証するには、次のチェックする必要があります。

  • ヘッダーを確認し、次のことを確認します。

    • typ claim が に JWT設定されています。
    • alg claim が に RS256設定されています。
    • x5t 要求が存在します。
  • ペイロードを確認し、次のことを確認します。

    • amurl 内の appctx 要求は、承認されたトークン署名キー マニフェスト ファイルの場所に設定されます。 たとえば、Microsoft 365 の予想 amurl される値は です https://outlook.office365.com:443/autodiscover/metadata/json/1。 詳細については、次のセクション 「ドメインの確認 」を参照してください。
    • 現在の時刻は、 と exp 要求で指定された時刻のnbf間です。 nbf クレームは、トークンが有効と考えられる最も早い時刻を指定し、exp クレームはトークンの有効期限を指定します。 サーバー間のクロック設定には、ある程度の変動を許可することをお勧めします。
    • aud claim は、アドインに必要な URL です。
    • version 要求内の appctx 要求は に ExIdTok.V1設定されます。

ドメインを確認する

前のセクションで説明した検証ロジックを実装する場合は、要求のドメインがユーザーの amurl 自動検出ドメインと一致することも必要です。 そのためには、 Exchange の自動検出を使用または実装する必要があります。

  • Exchange Onlineの場合は、 が既知のドメイン (https://outlook.office365.com:443/autodiscover/metadata/json/1) であるか、geo 固有または特殊なクラウド (Office 365 URL と IP アドレス範囲) に属していることをamurl確認します。

  • アドイン サービスにユーザーのテナントとの既存の構成がある場合は、これが amurl 信頼されているかどうかを確立できます。

  • Exchange ハイブリッド展開の場合は、OAuth ベースの自動検出を使用して、ユーザーに想定されているドメインを確認します。 ただし、ユーザーは自動検出フローの一部として認証する必要がありますが、アドインはユーザーの資格情報を収集して基本認証を行うべきではありません。

アドインでこれらのオプションのいずれかを使用して を amurl 検証できない場合は、アドインのワークフローに認証が必要な場合に、適切な通知をユーザーに適切にシャットダウンするように選択できます。

ID トークンの署名を検証する

JWT に必要なクレームが含まれていることを確認したら、トークンの署名の検証を進めることができます。

公開署名キーを取得する

最初のステップでは、Exchange サーバーがトークンの署名に使用した証明書に対応する公開キーを取得します。 鍵は認証メタデータ ドキュメントに記載されています。 このドキュメントは、amurl クレームで指定された URL でホストされている JSON ファイルです。

認証メタデータ ドキュメントには、次の形式を使用します。

{
    "id": "_70b34511-d105-4e2b-9675-39f53305bb01",
    "version": "1.0",
    "name": "Exchange",
    "realm": "*",
    "serviceName": "00000002-0000-0ff1-ce00-000000000000",
    "issuer": "00000002-0000-0ff1-ce00-000000000000@*",
    "allowedAudiences": [
        "00000002-0000-0ff1-ce00-000000000000@*"
    ],
    "keys": [
        {
            "usage": "signing",
            "keyinfo": {
                "x5t": "enh9BJrVPU5ijV1qjZjV-fL2bco"
            },
            "keyvalue": {
                "type": "x509Certificate",
                "value": "MIIHNTCC..."
            }
        }
    ],
    "endpoints": [
        {
            "location": "https://by2pr06mb2229.namprd06.prod.outlook.com:444/autodiscover/metadata/json/1",
            "protocol": "OAuth2",
            "usage": "metadata"
        }
    ]
}

使用可能な署名キーは keys 配列にあります。 keyinfo プロパティの x5t 値がトークンのヘッダーの x5t 値と一致することを確認することにより、正しいキーを選択します。 公開キーは keyvalue プロパティの value プロパティ内にあり、Base64 でエンコードされたバイト配列として格納されます。

正しい公開キーを取得したら、署名を検証します。 署名されたデータは、エンコードされたトークンの最初の 2 つの部分です (ピリオドで区切られる)。

{header}.{payload}

Exchange アカウントの一意 ID を計算する

認証メタデータ ドキュメント URL とアカウントの Exchange 識別子を連結して、Exchange アカウントの一意識別子を作成します。 この一意の識別子がある場合は、それを使用して、Outlook アドイン Web サービス用のシングル サインオン (SSO) システムを作成します。 SSO の一意の ID の使用の詳細については、「Exchange の ID トークンを使用してユーザーを認証する」を参照してください。

ライブラリを使用してトークンを検証する

一般的な JWT の解析と検証を行うことができるライブラリは数多くあります。 Microsoft には、Exchange ユーザー ID トークンの検証に使用できるライブラリが用意 System.IdentityModel.Tokens.Jwt されています。

重要

Exchange Web Services マネージ API は推奨されなくなりました。ただし、Microsoft.Exchange.WebServices.Auth.dll はまだ使用可能ですが、現在は廃止され、Microsoft.IdentityModel.Extensions.dll などのサポートされていないライブラリに依存しているためです。

System.IdentityModel.Tokens.Jwt

System.IdentityModels.Tokens.Jwt ライブラリはトークンを解析し、検証も実行できますが、ユーザー自身で appctx クレームを解析して公開署名キーを取得する必要があります。

// Load the encoded token
string encodedToken = "...";
JwtSecurityToken jwt = new JwtSecurityToken(encodedToken);

// Parse the appctx claim to get the auth metadata url
string authMetadataUrl = string.Empty;
var appctx = jwt.Claims.FirstOrDefault(claim => claim.Type == "appctx");
if (appctx != null)
{
    var AppContext = JsonConvert.DeserializeObject<ExchangeAppContext>(appctx.Value);

    // Token version check
    if (string.Compare(AppContext.Version, "ExIdTok.V1", StringComparison.InvariantCulture) != 0) {
        // Fail validation
    }

    authMetadataUrl = AppContext.MetadataUrl;
}

// Use System.IdentityModel.Tokens.Jwt library to validate standard parts
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
TokenValidationParameters tvp = new TokenValidationParameters();

tvp.ValidateIssuer = false;
tvp.ValidateAudience = true;
tvp.ValidAudience = "{URL to add-in}";
tvp.ValidateIssuerSigningKey = true;
// GetSigningKeys downloads the auth metadata doc and
// returns a List<SecurityKey>
tvp.IssuerSigningKeys = GetSigningKeys(authMetadataUrl);
tvp.ValidateLifetime = true;

try
{
    var claimsPrincipal = tokenHandler.ValidateToken(encodedToken, tvp, out SecurityToken validatedToken);

    // If no exception, all standard checks passed
}
catch (SecurityTokenValidationException ex)
{
    // Validation failed
}

ExchangeAppContext クラスは次のように定義されます。

using Newtonsoft.Json;

/// <summary>
/// Representation of the appctx claim in an Exchange user identity token.
/// </summary>
public class ExchangeAppContext
{
    /// <summary>
    /// The Exchange identifier for the user
    /// </summary>
    [JsonProperty("msexchuid")]
    public string ExchangeUid { get; set; }

    /// <summary>
    /// The token version
    /// </summary>
    public string Version { get; set; }

    /// <summary>
    /// The URL to download authentication metadata
    /// </summary>
    [JsonProperty("amurl")]
    public string MetadataUrl { get; set; }
}

このライブラリを使用して Exchange トークンを検証し、GetSigningKeys の実装を持つ例については、「Outlook-Add-In-Token-Viewer」を参照してください。

関連項目