Überprüfen eines Exchange-IdentitätstokensValidate an Exchange identity token

Ihr Outlook-Add-In kann Ihnen ein Exchange-Benutzeridentitätstoken senden, bevor Sie der Anforderung jedoch vertrauen, müssen Sie das Token überprüfen, um sicherzustellen, dass es von dem erwarteten Exchange-Server stammt.Your Outlook add-in can send you an Exchange user identity token, but before you trust the request you must validate the token to ensure that it came from the Exchange server that you expect. Exchange-Benutzeridentitätstoken sind JSON Web Token (JWT).Exchange user identity tokens are JSON Web Tokens (JWT). Die erforderlichen Schritte zum Überprüfen eines JWT werden in RFC 7519 JSON Web Token (JWT) beschrieben.The steps required to validate a JWT are described in RFC 7519 JSON Web Token (JWT).

Es wird empfohlen, einen aus vier Schritten bestehenden Vorgang zum Überprüfen des Identitätstokens und Abrufen der eindeutigen ID des Benutzers zu verwenden.We suggest that you use a four-step process to validate the identity token and obtain the user's unique identifier. Extrahieren Sie zuerst das JSON Web Token (JWT) aus einer base64-codierten Zeichenfolge.First, extract the JSON Web Token (JWT) from a base64 URL-encoded string. Stellen Sie dann sicher, dass das Token wohlgeformt ist, dass es für Ihr Outlook-Add-In bestimmt und nicht abgelaufen ist und dass Sie eine gültige URL für das Dokument mit den Authentifizierungsmetadaten extrahieren können.Second, make sure that the token is well-formed, that it is for your Outlook add-in, that it has not expired, and that you can extract a valid URL for the authentication metadata document. Rufen Sie als Nächstes das Dokument mit den Authentifizierungsmetadaten vom Exchange-Server ab und überprüfen Sie die an das Identitätstoken angefügte Signatur.Next, retrieve the authentication metadata document from the Exchange server and validate the signature attached to the identity token. Berechnen Sie schließlich eine eindeutige ID für den Benutzer, indem Sie einen Hash für die Exchange-ID des Benutzers mit der URL des Authentifizierungsmetadaten-Dokuments erstellen.Finally, compute a unique identifier for the user by hashing the user's Exchange ID with the URL of the authentication metadata document.

Extrahieren des JSON Web TokenExtract the JSON Web Token

Das von getUserIdentityTokenAsync zurückgegebene Token ist eine codierte Zeichenfolgendarstellung des Tokens.The token returned from getUserIdentityTokenAsync is an encoded string representation of the token. In diesem Formula, RFC 7519 bestehen alle JWTs aus drei Teilen, die durch einen Punkt getrennt sind.In this form, per RFC 7519, all JWT's have three parts, separated by a period. Das Format ist wie folgt.The format is as follows.

{header}.{payload}.{signature}

Der Header und die Nutzlast sollten base64-entschlüsselt sein, um eine JSON-Darstellung jedes Teils zu erhalten.The header and payload should be base64-decoded to obtain a JSON representation of each part. Die Signatur sollte base64-entschlüsselt sein, um ein Bytearray mit der binären Signatur zu erhalten.The signature should be base64-decoded to obtain a byte array containing the binary signature.

Weitere Informationen zu den Inhalten des Tokens finden Sie unter Innenleben des Exchange-Identitätstokens.For more details on the contents of the token, see Inside the Exchange identity token.

Nachdem Sie die drei Komponenten entschlüsselt haben, können Sie mit der Überprüfung des Tokens fortfahren.Once you have the three decoded components, you can proceed with validating the content of the token.

Überprüfen der TokeninhalteValidate token contents

Zur Überprüfung der Tokeninhalte sollten Sie Folgendes überprüfen:To validate the token contents, you should check the following.

  • Überprüfen Sie den Header, und prüfen Sie, dass:Check the header and verify that:
    • Der typ-Anspruch auf JWT festgelegt ist.The typ claim is set to JWT.
    • Der alg-Anspruch auf RS256 festgelegt ist.The alg claim is set to RS256.
    • Der x5t-Anspruch vorhanden ist.The x5t claim is present.
  • Überprüfen Sie die Nutzlast, und prüfen Sie, dass:Check the payload and verify that:
    • Überprüfen Sie, dass die aktuelle Uhrzeit zwischen den in den Ansprüchen nbf und exp angegebenen Zeitangaben liegt.Check that the current time is between the times specified in the nbf and exp claims. Der nbf-Anspruch gibt die früheste Zeit an, zu der das Token als gültig betrachtet wird, und der exp-Anspruch gibt die Ablaufzeit für das Token an.The nbf claim specifies the earliest time that the token is considered valid, and the exp claim specifies the expiration time for the token. Es wird empfohlen, dass Sie eine gewisse Abweichung der Systemuhreinstellungen zwischen Servern berücksichtigen.It is recommended to allow for some variation in clock settings between servers.
    • Überprüfen Sie, ob der aud-Anspruch die erwartete URL für das Add-In ist.Check that the aud claim is the expected URL for your add-in.
    • Überprüfen Sie, ob der version-Anspruch innerhalb des appctx-Anspruchs auf ExIdTok.V1 festgelegt ist.Check that the version claim inside the appctx claim is set to ExIdTok.V1.
    • Überprüfen Sie, ob der amurl-Anspruch innerhalb des appctx-Anspruchs auf eine gültige URL festgelegt ist.Check that the amurl claim inside the appctx is set to a valid URL.

Überprüfen der IdentitätstokensignaturValidate the identity token signature

Nachdem Sie überprüft haben, dass das JWT die erforderlichen Ansprüche enthält, können Sie mit dem Überprüfung der Tokensignatur fortfahren.After you know that the JWT contains the required claims, you can proceed with validating the token signature.

Abrufen des öffentlichen SignaturschlüsselsRetrieve the public signing key

Der erste Schritt besteht darin, den öffentlichen Schlüssel abzurufen, der dem Zertifikat entspricht, das der Exchange-Serer zum Signieren des Tokens verwendet hat.The first step is to retrieve the public key that corresponds to the certificate that the Exchange server used to sign the token. Der Schlüssel befindet sich im Dokument mit den Authentifizierungsmetadaten.The key is found in the authentication metadata document. Dieses Dokument ist eine JSON-Datei, die an der im amurl-Anspruch angegebenen URL gehostet wird.This document is a JSON file hosted at the URL specified in the amurl claim.

Das Dokument mit den Authentifizierungsmetadaten verwendet das folgende Format.The authentication metadata document uses the following format.

{
    "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"
        }
    ]
}

Die verfügbaren Signaturschlüssel befinden sich im keys-Array.The available signing keys are in the keys array. Wählen Sie den richtigen Schlüssel aus, indem Sie sicherstellen, dass der x5t-Wert in der keyinfo-Eigenschaft dem x5t-Wert in der Kopfzeile des Tokens entspricht.Select the correct key by ensuring that the x5t value in the keyinfo property matches the x5t value in the header of the token. Der öffentliche Schlüssel befindet sich in der value-Eigenschaft in der keyvalue-Eigenschaft, und wird als base64-codiertes Bytearray gespeichert.The public key is inside the value property in the keyvalue property, stored as a base64-encoded byte array.

Überprüfen Sie die Signatur, nachdem Sie den richtigen öffentlichen Schlüssel gefunden haben.Once you have the correct public key, verify the signature. Die signierten Daten sind die ersten beiden Teile des codierten Tokens, getrennt durch einen Punkt:The signed data is the first two parts of the encoded token, separated by a period:

{header}.{payload}

Berechnen der eindeutigen ID für ein Exchange-KontoCompute the unique ID for an Exchange account

Sie können einen eindeutigen Bezeichner für ein Exchange-Konto erstellen, indem Sie die URL des Dokuments mit den Authentifizierungsmetadaten mit der Exchange-ID für das Konto mit einem Hash versehen.You can create a unique identifier for an Exchange account by hashing the authentication metadata document URL with the Exchange identifier for the account. Wenn Sie diesen eindeutigen Bezeichner haben, können Sie ihn verwenden, um ein SSO-System (Single Sign On, einmaliges Anmelden) für Ihren Outlook-Add-In-Webdienst zu erstellen.When you have this unique identifier, you can use it to create a single sign-on (SSO) system for your Outlook add-in web service. Ausführliche Informationen zur Verwendung des eindeutigen Bezeichners für SSO finden Sie unter Authentifizieren eines Benutzers mit einem Identitätstoken für Exchange.For details about using the unique identifier for SSO, see Authenticate a user with an identity token for Exchange.

Verwenden einer Bibliothek zum Überprüfen des TokensUse a library to validate the token

Es gibt eine Reihe von Bibliotheken, die eine allgemeine JWT-Analyse und -Überprüfung durchführen können.There are a number of libraries that can do general JWT parsing and validation. Microsoft bietet zwei Bibliotheken, die zum Überprüfen des Exchange-Benutzeridentitätstokens verwendet werden können.Microsoft provides two libraries that can be used to validate Exchange user identity tokens.

System.IdentityModel.Tokens.JwtSystem.IdentityModel.Tokens.Jwt

Die System.IdentityModels.Tokens.Jwt-Bibliothek kann das Token analysieren und auch die Überprüfung durchführen, Sie müssen aber den appctx-Anspruch selbst analysieren und den öffentlichen Signaturschlüssel abrufen.The System.IdentityModels.Tokens.Jwt library can parse the token and also perform the validation, though you will need to parse the appctx claim yourself and retrieve the public signing key.

// 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
}

Die ExchangeAppContext-Klasse ist wie folgt definiert:The ExchangeAppContext class is defined as follows:

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; }
}

Ein Beispiel, das diese Bibliothek zum Überprüfen von Exchange-Token verwendet und über eine Implementierung von GetSigningKeys verfügt, finden Sie unter Outlook-Add-In-Token-Viewer.For an example that uses this library to validate Exchange tokens and has an implementation of GetSigningKeys, see Outlook-Add-In-Token-Viewer.

Microsoft.Exchange.WebServicesMicrosoft.Exchange.WebServices

Die verwaltete API Exchange-Webdienste kann auch Exchange-Benutzeridentitätstoken überprüfen.The Exchange Web Services Managed API can also validate Exchange user identity tokens. Da sie Exchange-spezifisch ist, implementiert sie die gesamte erforderliche Logik zum Analysieren des appctx-Anspruchs und zum Überprüfen der Tokenversion.Because it is Exchange-specific, it implements all of the necessary logic to parse the appctx claim and verify the token version.

using Microsoft.Exchange.WebServices.Auth.Validation;

AppIdentityToken ValidateIdentityToken(string rawToken, string expectedAudience)
{
    try
    {
        AppIdentityToken appIdToken = AuthToken.Parse(rawToken) as AppIdentityToken;
        appIdToken.Validate(new Uri(expectedAudience));

        // No exception, validation succeeded
        return appIdToken;
    }
    catch (TokenValidationException ex)
    {
        throw new Exception(string.Format("Token validation failed: {0}", ex.Message));
    }
}

Siehe auchSee also