Création d’un complément Office Node.js qui utilise l’authentification unique

Les utilisateurs peuvent se connecter à Office et votre complément Web Office peut tirer parti de cette procédure de connexion pour autoriser les utilisateurs à accéder à votre complément et à Microsoft Graph sans obliger les utilisateurs à se connecter une deuxième fois. Pour obtenir une vue d’ensemble, consultez la rubrique Activer l’authentification unique dans un complément Office.

Cet article vous guide tout au long du processus d’activation de l’authentification unique (SSO) dans un complément. L’exemple de complément que vous créez comporte deux parties : un volet Office qui se charge dans Microsoft Excel et un serveur de niveau intermédiaire qui gère les appels à Microsoft Graph pour le volet Office. Le serveur de niveau intermédiaire est créé avec Node.js et Express et expose une SEULE API REST, /getuserfilenames, qui retourne une liste des 10 premiers noms de fichiers dans le dossier OneDrive de l’utilisateur. Le volet Office utilise la getAccessToken() méthode pour obtenir un jeton d’accès pour l’utilisateur connecté au serveur de niveau intermédiaire. Le serveur de niveau intermédiaire utilise le flux On-Behalf-Of (OBO) pour échanger le jeton d’accès contre un nouveau jeton avec accès à Microsoft Graph. Vous pouvez étendre ce modèle pour accéder à toutes les données Microsoft Graph. Le volet Office appelle toujours une API REST de niveau intermédiaire (en passant le jeton d’accès) lorsqu’il a besoin de services Microsoft Graph. Le niveau intermédiaire utilise le jeton obtenu via OBO pour appeler les services Microsoft Graph et retourner les résultats au volet Office.

Cet article fonctionne avec un complément qui utilise Node.js et Express. Pour voir un article similaire sur un complément basé sur ASP.NET, reportez-vous à Créer un complément Office ASP.NET qui utilise l’authentification unique.

Conditions préalables

  • Node.js (la dernière version LTS)

  • Git Bash (ou un autre client Git)

  • Un éditeur de code - Nous vous recommandons Visual Studio Code

  • Au moins quelques fichiers et dossiers stockés sur OneDrive Entreprise dans votre abonnement Microsoft 365

  • Build de Microsoft 365 qui prend en charge l’ensemble de conditions requises IdentityAPI 1.3. Vous pouvez bénéficier d’un abonnement Microsoft 365 E5 développeur, qui inclut un bac à sable pour les développeurs, par le biais du Programme pour les développeurs Microsoft 365. Pour plus d’informations, consultez le FAQ. Le bac à sable développeur inclut un abonnement Microsoft Azure que vous pouvez utiliser pour les inscriptions d’applications dans les étapes ultérieures de cet article. Si vous préférez, vous pouvez utiliser un abonnement Microsoft Azure distinct pour les inscriptions d’applications. Obtenez un abonnement d’essai sur Microsoft Azure.

Configurer le projet de démarrage

  1. Clonez ou téléchargez le référentiel sur Complément Office NodeJS SSO.

    Remarque

    Il existe deux versions de l’échantillon :

    • Le dossier Begin est un projet de démarrage. L’interface utilisateur et d’autres aspects du complément qui ne sont pas directement liés à l’authentification unique ou à l’autorisation sont déjà terminés. Les sections suivantes de cet article vous guident tout au long de la procédure d’exécution de cette dernière.
    • Le dossier Complete contient le même exemple avec toutes les étapes de codage de cet article terminées. Pour utiliser la version terminée, suivez simplement les instructions de cet article, mais remplacez « Begin » par « Complete » et ignorez les sections Coder côté client et Code côté serveur de niveau intermédiaire .
  2. Ouvrez une invite de commandes dans le dossier Begin .

  3. Saisissez npm installdans la console pour installer toutes les dépendances détaillées dans le fichier package.json.

  4. Exécutez la commande npm run install-dev-certs. Sélectionnez Oui lorsque vous êtes invité à installer le certificat.

Utilisez les valeurs suivantes pour les espaces réservés pour les étapes d’inscription d’application suivantes.

Espace réservé Valeur
<add-in-name> Office-Add-in-NodeJS-SSO
<fully-qualified-domain-name> localhost:3000
Autorisations de Microsoft Graph profile, openid, Files.Read

Inscrire le complément auprès de Plateforme d'identités Microsoft

Vous devez créer une inscription d’application dans Azure qui représente votre serveur web. Cela permet la prise en charge de l’authentification afin que les jetons d’accès appropriés puissent être émis au code client dans JavaScript. Cette inscription prend en charge l’authentification unique dans le client et l’authentification de secours à l’aide de la bibliothèque d’authentification Microsoft (MSAL).

  1. Connectez-vous au Portail Azure avec les informations d’identification d’administrateur de votre location Microsoft 365. Par exemple : MyName@contoso.onmicrosoft.com.

  2. Sélectionner les inscriptions d’applications. Si vous ne voyez pas l’icône, recherchez « Inscription de l’application » dans la barre de recherche.

    Page d’accueil Portail Azure.

    La page Inscriptions d'applications s’affiche.

  3. Sélectionnez Nouvelle inscription.

    Nouvelle inscription dans le volet inscriptions d'applications.

    La page Inscrire une application s’affiche.

  4. Sur la page Inscrire une application, définissez les valeurs comme suit.

    • Définissez le Nom sur <add-in-name>.
    • Définissez Types de comptes pris en chargesur Comptes dans n’importe quel annuaire organisationnel (n’importe quel annuaire Azure AD - multilocataire) et comptes Microsoft personnels (par exemple, Skype, Xbox).
    • Définissez URI de redirection pour utiliser l’application monopage (SPA) de plateforme et l’URI sur https://<fully-qualified-domain-name>/dialog.html.

    Inscrire un volet d’application avec le nom et le compte pris en charge terminés.

  5. Sélectionner Inscription. Un message s’affiche indiquant que l’inscription de l’application a été créée.

    Message indiquant que l’inscription de l’application a été créée.

  6. Copiez et enregistrez les valeurs de l’ID d’application (client) et de l’ID d’annuaire (locataire). Vous utiliserez les deux plus tard.

    Volet Inscription d’application pour Contoso affichant l’ID client et l’ID d’annuaire.

Ajouter une clé secrète client

Parfois appelé mot de passe d’application, une clé secrète client est une valeur de chaîne que votre application peut utiliser à la place d’un certificat pour s’identifier elle-même.

  1. Dans le volet gauche, sélectionnez Certificats & secrets. Ensuite, sous l’onglet Secrets client , sélectionnez Nouvelle clé secrète client.

    Volet Certificats & secrets.

    Le volet Ajouter une clé secrète client s’affiche.

  2. Ajoutez une description pour votre clé secrète client.

  3. Sélectionnez une expiration pour le secret ou spécifiez une durée de vie personnalisée.

    • La durée de vie de la clé secrète client est limitée à deux ans (24 mois) ou moins. Vous ne pouvez pas spécifier une durée de vie personnalisée supérieure à 24 mois.
    • Microsoft vous recommande de définir une valeur d’expiration inférieure à 12 mois.

    Ajoutez un volet de clé secrète client avec la description et expire.

  4. Sélectionnez Ajouter. Le nouveau secret est créé et la valeur est affichée temporairement.

Importante

Enregistrez la valeur du secret à utiliser dans le code de votre application cliente. Cette valeur de secret n’est plus jamais affichée une fois que vous avez quitté ce volet.

Exposer une API web

  1. Dans le volet gauche, sélectionnez Exposer une API.

    Le volet Exposer une API s’affiche .

    Volet Exposer une API d’une inscription d’application.

  2. Sélectionnez Définir pour générer un URI d’ID d’application.

    Bouton Définir dans le volet Exposer une API de l’inscription de l’application.

    La section permettant de définir l’URI de l’ID d’application s’affiche avec un URI d’ID d’application généré au format api://<app-id>.

  3. Mettez à jour l’URI de l’ID d’application sur api://<fully-qualified-domain-name>/<app-id>.

    Modifiez le volet URI d’ID d’application avec le port localhost défini sur 44355.

    • L’URI de l’ID d’application est prérempli avec l’ID d’application (GUID) au format api://<app-id>.
    • Le format d’URI de l’ID d’application doit être : api://<fully-qualified-domain-name>/<app-id>
    • Insérez entre fully-qualified-domain-nameapi:// et <app-id> (qui est un GUID). Par exemple : api://contoso.com/<app-id>.
    • Si vous utilisez localhost, le format doit être api://localhost:<port>/<app-id>. Par exemple : api://localhost:3000/c6c1f32b-5e55-4997-881a-753cc1d563b7.

    Pour plus d’informations sur l’URI de l’ID d’application, consultez Attribut identificateur de manifeste d’applicationUris.

    Remarque

    Si un message d’erreur s’affiche indiquant que le domaine appartient déjà à quelqu’un et que c’est vous qui en êtes le propriétaire, suivez la procédure décrite dans Quickstart  : Ajouter votre nom de domaine personnalisé à l’aide du Portail Azure Active Directory pour l’inscrire, puis répétez cette étape. (Cette erreur peut également se produire si vous n’êtes pas connecté avec les informations d’identification d’un administrateur dans la location Microsoft 365. Consultez l’étape 2. Déconnectez-vous et reconnectez-vous avec les informations d’identification d’administrateur et répétez le processus de l’étape 3.)

Ajouter une étendue

  1. Dans la page Exposer une API , sélectionnez Ajouter une étendue.

    Sélectionnez le bouton Ajouter une étendue.

    Le volet Ajouter une étendue s’ouvre.

  2. Dans le volet Ajouter une étendue , spécifiez les attributs de l’étendue. Le tableau suivant montre des exemples de valeurs pour et complément Outlook nécessitant les profileautorisations , openid, Files.ReadWriteet Mail.Read . Modifiez le texte pour qu’il corresponde aux autorisations dont votre complément a besoin.

    Field Description Values
    Nom de l'étendue Nom de votre étendue. Une convention de nommage d’étendue courante est resource.operation.constraint. Pour l’authentification unique, cette valeur doit être définie sur access_as_user.
    Qui peut donner son consentement Détermine si le consentement de l’administrateur est requis ou si les utilisateurs peuvent donner leur consentement sans approbation de l’administrateur. Pour découvrir l’authentification unique et les exemples, nous vous recommandons de définir cette option sur Administrateurs et utilisateurs.

    Sélectionnez Administrateurs uniquement pour obtenir des autorisations à privilèges plus élevés.
    Administration nom d’affichage du consentement Brève description de l’objectif de l’étendue visible uniquement par les administrateurs. Read/write permissions to user files. Read permissions to user mail and profiles.
    Administration description du consentement Description plus détaillée de l’autorisation accordée par l’étendue que seuls les administrateurs voient. Allow Office to have read/write permissions to all user files and read permissions to all user mail. Office can call the app's web APIs as the current user.
    Nom d’affichage du consentement de l’utilisateur Brève description de l’objectif de l’étendue. Affiché aux utilisateurs uniquement si vous définissez Qui peut donner son consentement aux administrateurs et aux utilisateurs. Read/write permissions to your files. Read permissions to your mail and profile.
    Description du consentement de l’utilisateur Description plus détaillée de l’autorisation accordée par l’étendue. Affiché aux utilisateurs uniquement si vous définissez Qui peut donner son consentement aux administrateurs et aux utilisateurs. Allow Office to have read/write permissions to your files, and read permissions to your mail and profile.
  3. Définissez l’étatsur Activé, puis sélectionnez Ajouter une étendue.

    Définissez l’état sur activé et sélectionnez le bouton Ajouter une étendue.

    La nouvelle étendue que vous avez définie s’affiche dans le volet.

    Nouvelle étendue affichée dans le volet Exposer une API.

    Remarque

    La partie domaine du nom de l’étendue affiché juste sous le champ de texte devrait automatiquement correspondre à l’URI d’ID d’application définie à l’étape précédente avec /access_as_user ajouté au bout (par exemple, api://localhost:6789/c6c1f32b-5e55-4997-881a-753cc1d563b7/access_as_user).

  4. Sélectionnez Ajouter une application cliente.

    Sélectionnez Ajouter une application cliente.

    Le volet Ajouter une application cliente s’affiche .

  5. Dans l’ID client , entrez ea5a67f6-b6f3-4338-b240-c655ddc3cc8e. Cette valeur pré-autorise tous les points de terminaison d’application Microsoft Office. Si vous souhaitez également pré-autoriser Office lorsqu’il est utilisé à l’intérieur de Microsoft Teams, ajoutez 1fec8e78-bce4-4aaf-ab1b-5451cc387264 (Microsoft Teams desktop et Teams mobile) et 5e3ce6c0-2b1f-4285-8d4b-75ee78787346 (Teams sur le web).

    Remarque

    L’ID ea5a67f6-b6f3-4338-b240-c655ddc3cc8e pré-autorise Office sur toutes les plateformes suivantes. Vous pouvez également entrer un sous-ensemble approprié des ID suivants si, pour une raison quelconque, vous souhaitez refuser l’autorisation à Office sur certaines plateformes. Si vous le faites, laissez de côté les ID des plateformes à partir desquelles vous souhaitez refuser l’autorisation. Les utilisateurs de votre complément sur ces plateformes ne pourront pas appeler vos API web, mais d’autres fonctionnalités de votre complément fonctionneront toujours.

    • d3590ed6-52b3-4102-aeff-aad2292ab01c (Microsoft Office)
    • 93d53678-613d-4013-afc1-62e9e444a0a5 (Office sur le web)
    • bc59ab01-8403-45c6-8796-ac3ef710b3e3 (Outlook sur le web)
  6. Dans Étendues autorisées, cochez la api://<fully-qualified-domain-name>/<app-id>/access_as_user case.

  7. Sélectionnez Ajouter une application.

    Volet Ajouter une application cliente.

Ajouter des autorisations Microsoft Graph

  1. Dans le volet gauche, sélectionnez Autorisations d’API.

    Volet Autorisations de l’API.

    Le volet Autorisations de l’API s’ouvre.

  2. Sélectionnez Ajouter une autorisation.

    Ajout d’une autorisation dans le volet Autorisations de l’API.

    Le volet Demander des autorisations d’API s’ouvre.

  3. Sélectionnez Microsoft Graph.

    Bouton Demander des autorisations d’API avec Microsoft Graph.

  4. Sélectionnez Autorisations déléguées.

    Bouton Demander des autorisations d’API avec autorisations déléguées.

  5. Dans la zone de recherche Sélectionner des autorisations , recherchez les autorisations dont votre complément a besoin. Par exemple, pour un complément Outlook, vous pouvez utiliser profile, openid, Files.ReadWriteet Mail.Read.

    Remarque

    L’autorisation User.Read est peut-être déjà répertoriée par défaut. Comme il est recommandé de demander uniquement les autorisations nécessaires, nous vous recommandons de décocher la case pour cette autorisation si votre complément n’en a pas réellement besoin.

  6. Cochez la case pour chaque autorisation telle qu’elle apparaît. Notez que les autorisations ne restent pas visibles dans la liste lorsque vous sélectionnez chacune d’elles. Après avoir sélectionné les autorisations dont votre complément a besoin, sélectionnez Ajouter des autorisations.

    Volet Demander des autorisations d’API avec certaines autorisations sélectionnées.

  7. Sélectionnez Accorder le consentement de l’administrateur pour [nom du locataire] . Sélectionnez Oui pour la confirmation qui s’affiche.

Configurer la version du jeton d’accès

Vous devez définir la version du jeton d’accès acceptable pour votre application. Cette configuration est effectuée dans le manifeste de l’application Azure Active Directory.

Définir la version du jeton d’accès

La version du jeton d’accès peut changer si vous avez choisi un type de compte autre que Comptes dans un annuaire organisationnel (n’importe quel annuaire Azure AD - Multilocataire) et des comptes Microsoft personnels (par exemple, Skype, Xbox). Procédez comme suit pour vous assurer que la version du jeton d’accès est correcte pour l’utilisation de l’authentification unique Office.

  1. Dans le volet gauche, sélectionnez Manifeste.

    Sélectionnez Manifeste Azure.

    Le manifeste de l’application Azure Active Directory s’affiche.

  2. Entrez 2 comme valeur pour la propriété accessTokenAcceptedVersion.

    Valeur de la version du jeton d’accès acceptée.

  3. Sélectionnez Enregistrer.

    Un message s’affiche sur le navigateur indiquant que le manifeste a été mis à jour avec succès.

    Message de manifeste mis à jour.

Félicitations ! Vous avez terminé l’inscription de l’application pour activer l’authentification unique pour votre complément Office.

Configurer le complément

  1. Ouvrez le dossier \Begin dans le projet cloné dans votre éditeur de code.

  2. Ouvrez le .ENV fichier et utilisez les valeurs que vous avez copiées précédemment à partir de l’inscription de l’application Office-Add-in-NodeJS-SSO . Définissez les valeurs comme suit :

    Nom Valeur
    CLIENT_ID ID d’application (client) à partir de la page de vue d’ensemble de l’inscription d’application.
    CLIENT_SECRET Clé secrète client enregistrée à partir de la page Certificats & Secrets .

    Les valeurs ne doivent pas se trouver entre des guillemets. Quand vous avez terminé, votre modèle doit ressembler à ce qui suit :

    CLIENT_ID=8791c036-c035-45eb-8b0b-265f43cc4824
    CLIENT_SECRET=X7szTuPwKNts41:-/fa3p.p@l6zsyI/p
    NODE_ENV=development
    SERVER_SOURCE=<https://localhost:3000>
    
  3. Ouvrez le fichier manifeste de complément « manifest\manifest_local. xml », puis faites défiler la page jusqu’à la fin du fichier. Juste au-dessus de la </VersionOverrides> balise de fin, vous trouverez le balisage suivant.

    <WebApplicationInfo>
      <Id>$app-id-guid$</Id>
      <Resource>api://localhost:3000/$app-id-guid$</Resource>
      <Scopes>
          <Scope>Files.Read</Scope>
          <Scope>profile</Scope>
          <Scope>openid</Scope>
      </Scopes>
    </WebApplicationInfo>
    
  4. Remplacez l’espace réservé « $app-id-guid$ » aux deux endroits du balisage par l’ID d’application que vous avez copié lors de la création de l’inscription de l’application Office-Add-in-NodeJS-SSO . Les symboles « $ » ne font pas partie de l’ID. Ne les incluez donc pas. Il s’agit du même ID que celui utilisé pour le CLIENT_ID dans . Fichier ENV.

    Remarque

    La <valeur ressource> est l’URI d’ID d’application que vous définissez lors de l’inscription du complément. La <section Étendues> est utilisée uniquement pour générer une boîte de dialogue de consentement si le complément est vendu via AppSource.

  5. Ouvrez le fichier \public\javascripts\fallback-msal\authConfig.js. Remplacez l’espace réservé « $app-id-guid$ » par l’ID d’application que vous avez enregistré à partir de l’inscription de l’application Office-Add-in-NodeJS-SSO que vous avez créée précédemment.

  6. Enregistrez les modifications du fichier.

Code du côté client

Appeler l’API REST de notre serveur web

  1. Ouvrez le fichier public\javascripts\ssoAuthES6.js dans votre éditeur de code. Il dispose déjà d’un code qui garantit que les promesses sont prises en charge, même dans le contrôle Webview Trident (Internet Explorer 11), et un Office.onReady appel pour affecter un gestionnaire au seul bouton du complément.

    Remarque

    Comme leur nom l’indique, ssoAuthES6.js utilise la syntaxe JavaScript ES6, car l’utilisation de async et de await illustre le mieux la simplicité de l’API SSO. Lorsque le serveur localhost est démarré, ce fichier est transpilé en syntaxe ES5 afin que l’exemple prend en charge Trident.

  2. Dans la fonction getFileNameList, remplacez TODO 1 par le code suivant. Tenez compte du code suivant :

    • La fonction getFileNameList est appelée lorsque l’utilisateur choisit le bouton Obtenir les noms de fichiers OneDrive dans le volet Office.
    • Il appelle la callWebServerAPI fonction en spécifiant l’API REST à appeler. Cette opération renvoie json contenant une liste de noms de fichiers à partir du OneDrive de l’utilisateur.
    • Le code JSON est passé à la writeFileNamesToOfficeDocument fonction pour répertorier les noms de fichiers dans le document.
    try {
        const jsonResponse = await callWebServerAPI('GET', '/getuserfilenames');
        if (jsonResponse === null) {
            // Null is returned when a message was displayed to the user
            // regarding an authentication error that cannot be resolved.
            return;
        }
        await writeFileNamesToOfficeDocument(jsonResponse);
        showMessage('Your OneDrive filenames are added to the document.');
    } catch (error) {
        console.log(error.message);
        showMessage(error.message);
    }
    
  3. Dans la fonction callWebServerAPI, remplacez TODO 2 par le code suivant. Tenez compte du code suivant :

    • La fonction appelle getAccessToken qui est notre propre fonction qui encapsule l’utilisation de l’authentification unique Office ou de secours MSAL si nécessaire pour obtenir le jeton. Si elle retourne un jeton Null, un message a été affiché pour une condition d’erreur d’authentification qui ne peut pas être résolue. La fonction retourne donc également la valeur Null.
    • La fonction utilise l’API fetch pour appeler le serveur web et, si elle réussit, retourne le corps JSON.
    const accessToken = await getAccessToken(authSSO);
    if (accessToken === null) {
        return null;
    }
    const response = await fetch(path, {
        method: method,
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + accessToken,
        },
    });
    
    // Check for success condition: HTTP status code 2xx.
    if (response.ok) {
        return response.json();
    }
    
  4. Dans la fonction callWebServerAPI, remplacez TODO 3 par le code suivant. Tenez compte du code suivant :

    • Ce code gère le scénario dans lequel le jeton d’authentification unique a expiré. Si c’est le cas, nous devons appeler Office.auth.getAccessToken pour obtenir un jeton actualisé. Le moyen le plus simple consiste à effectuer un appel récursif qui entraîne un nouvel appel à Office.auth.getAccessToken. Le retryRequest paramètre garantit que l’appel récursif n’est tenté qu’une seule fois.
    • La TokenExpiredError chaîne est définie par notre serveur web chaque fois qu’il détecte un jeton expiré.
     // Check for fail condition: Is SSO token expired? If so, retry the call which will get a refreshed token.
    const jsonBody = await response.json();
    if (
        authSSO === true &&
        jsonBody != null &&
        jsonBody.type === 'TokenExpiredError'
    ) {
        if (!retryRequest) {
            return callWebServerAPI(method, path, true); // Try the call again. The underlying call to Office JS getAccessToken will refresh the token.
        } else {
            // Indicates a second call to retry and refresh the token failed.
            authSSO = false;
            return callWebServerAPI(method, path, true); // Try the call again, but now using MSAL fallback auth.
        }
    }
    
  5. Dans la fonction callWebServerAPI, remplacez TODO 4 par le code suivant. Tenez compte du code suivant :

    • La Microsoft Graph chaîne est définie par notre serveur web chaque fois qu’un appel Microsoft Graph échoue.
    // Check for fail condition: Did we get a Microsoft Graph API error, which is returned as bad request (403)?
    if (response.status === 403 && jsonBody.type === 'Microsoft Graph') {
        throw new Error('Microsoft Graph error: ' + jsonBody.errorDetails);
    }
    
  6. Dans la fonction callWebServerAPI, remplacez TODO 5 par le code suivant.

    // Handle other errors.
    throw new Error(
        'Unknown error from web server: ' + JSON.stringify(jsonBody)
    );
    
  7. Dans la fonction getAccessToken, remplacez TODO 6 par le code suivant. Tenez compte du code suivant :

    • authSSO effectue le suivi si nous utilisons l’authentification unique ou si nous utilisons msAL de secours. Si l’authentification unique est utilisée, la fonction appelle Office.auth.getAccessToken et retourne le jeton.
    • Les erreurs sont gérées par la handleSSOErrors fonction qui retourne un jeton si elle bascule vers l’authentification MSAL de secours.
    • L’authentification de secours utilise la bibliothèque MSAL pour connecter l’utilisateur. Le complément lui-même est un spa et utilise une inscription d’application SPA pour accéder au serveur web.
    if (authSSO) {
        try {
            // Get the access token from Office host using SSO.
            // Note that Office.auth.getAccessToken modifies the options parameter. Create a copy of the object
            // to avoid modifying the original object.
            const options = JSON.parse(JSON.stringify(ssoOptions));
            const token = await Office.auth.getAccessToken(options);
            return token;
        } catch (error) {
            console.log(error.message);
            return handleSSOErrors(error);
        }
    } else {
        // Get access token through MSAL fallback.
        try {
            const accessToken = await getAccessTokenMSAL();
            return accessToken;
        } catch (error) {
            console.log(error);
            throw new Error(
                'Cannot get access token. Both SSO and fallback auth failed. ' +
                    error
            );
        }
    }
    
  8. Dans la fonction handleSSOErrors, remplacez TODO 7 par le code suivant. Pour plus d’informations sur ces erreurs, reportez-vous à Résoudre les problèmes liés à SSO dans les compléments Office.

    switch (error.code) {
        case 13001:
            // No one is signed into Office. If the add-in cannot be effectively used when no one
            // is logged into Office, then the first call of getAccessToken should pass the
            // `allowSignInPrompt: true` option. Since this sample does that, you should not see
            // this error.
            showMessage(
                'No one is signed into Office. But you can use many of the add-ins functions anyway. If you want to log in, press the Get OneDrive File Names button again.'
            );
            break;
        case 13002:
            // The user aborted the consent prompt. If the add-in cannot be effectively used when consent
            // has not been granted, then the first call of getAccessToken should pass the `allowConsentPrompt: true` option.
            showMessage(
                'You can use many of the add-ins functions even though you have not granted consent. If you want to grant consent, press the Get OneDrive File Names button again.'
            );
            break;
        case 13006:
            // Only seen in Office on the web.
            showMessage(
                'Office on the web is experiencing a problem. Please sign out of Office, close the browser, and then start again.'
            );
            break;
        case 13008:
            // Only seen in Office on the web.
            showMessage(
                'Office is still working on the last operation. When it completes, try this operation again.'
            );
            break;
        case 13010:
            // Only seen in Office on the web.
            showMessage(
                "Follow the instructions to change your browser's zone configuration."
            );
            break;
    
  9. Remplacez TODO 8 par le code suivant. Pour les erreurs qui ne peuvent pas être gérées, le code bascule vers l’authentification de secours à l’aide de MSAL.

    default: //recursive call.
            // For all other errors, including 13000, 13003, 13005, 13007, 13012, and 50001, fall back
            // to MSAL sign-in.
            showMessage('SSO failed. Trying fallback auth.');
            authSSO = false;
            return getAccessToken(false);
    }
    return null; // Return null for errors that show a message to the user.
    

Coder l’API REST du serveur web

Le serveur web fournit des API REST que le client doit appeler. Par exemple, l’API /getuserfilenames REST obtient une liste de noms de fichiers à partir du dossier OneDrive de l’utilisateur. Chaque appel d’API REST nécessite un jeton d’accès par le client pour s’assurer que le client approprié accède à ses données. Le jeton d’accès est échangé contre un jeton Microsoft Graph via le flux On-Behalf-Of (OBO). Le nouveau jeton Microsoft Graph est mis en cache par la bibliothèque MSAL pour les appels d’API suivants. Il n’est jamais envoyé en dehors du serveur web. Pour plus d’informations, consultez Demande de jeton d’accès de niveau intermédiaire

Créer l’itinéraire et implémenter le flux On-Behalf-Of

  1. Ouvrez le fichier routes\getFilesRoute.js et remplacez par TODO 9 le code suivant. Tenez compte du code suivant :

    • Il appelle authHelper.validateJwt. Cela garantit que le jeton d’accès est valide et qu’il n’a pas été falsifié.
    • Pour plus d’informations, consultez Validation des jetons.
    router.get(
     "/getuserfilenames",
     authHelper.validateJwt,
     async function (req, res) {
       // TODO 10: Exchange the access token for a Microsoft Graph token
       //          by using the OBO flow.
     }
    );
    
  2. Remplacez TODO 10 par le code suivant. Tenez compte du code suivant :

    • Il demande uniquement les étendues minimales dont il a besoin, telles que files.read.
    • Il utilise msal authHelper pour effectuer le flux OBO dans l’appel à acquireTokenOnBehalfOf.
    try {
      const authHeader = req.headers.authorization;
      let oboRequest = {
        oboAssertion: authHeader.split(' ')[1],
        scopes: ["files.read"],
      };
    
      // The Scope claim tells you what permissions the client application has in the service.
      // In this case we look for a scope value of access_as_user, or full access to the service as the user.
      const tokenScopes = jwt.decode(oboRequest.oboAssertion).scp.split(' ');
      const accessAsUserScope = tokenScopes.find(
        (scope) => scope === 'access_as_user'
      );
      if (!accessAsUserScope) {
        res.status(401).send({ type: "Missing access_as_user" });
        return;
      }
      const cca = authHelper.getConfidentialClientApplication();
      const response = await cca.acquireTokenOnBehalfOf(oboRequest);
      // TODO 11: Call Microsoft Graph to get list of filenames.
    } catch (err) {
      // TODO 12: Handle any errors.
    }
    
  3. Remplacez TODO 11 par le code suivant. Tenez compte du code suivant :

    • Il construit l’URL de l’appel API Graph Microsoft, puis effectue l’appel via la getGraphData fonction .
    • Il retourne des erreurs en envoyant une réponse HTTP 500 avec des détails.
    • En cas de réussite, il retourne le json avec la liste des noms de fichiers au client.
    // Minimize the data that must come from MS Graph by specifying only the property we need ("name")
    // and only the top 10 folder or file names.
    const rootUrl = '/me/drive/root/children';
    
    // Note that the last parameter, for queryParamsSegment, is hardcoded. If you reuse this code in
    // a production add-in and any part of queryParamsSegment comes from user input, be sure that it is
    // sanitized so that it cannot be used in a Response header injection attack.
    const params = '?$select=name&$top=10';
    
    const graphData = await getGraphData(
      response.accessToken,
      rootUrl,
      params
    );
    
    // If Microsoft Graph returns an error, such as invalid or expired token,
    // there will be a code property in the returned object set to a HTTP status (e.g. 401).
    // Return it to the client. On client side it will get handled in the fail callback of `makeWebServerApiCall`.
    if (graphData.code) {
      res
        .status(403)
        .send({
          type: "Microsoft Graph",
          errorDetails:
            "An error occurred while calling the Microsoft Graph API.\n" +
            graphData,
        });
    } else {
      // MS Graph data includes OData metadata and eTags that we don't need.
      // Send only what is actually needed to the client: the item names.
      const itemNames = [];
      const oneDriveItems = graphData["value"];
      for (let item of oneDriveItems) {
        itemNames.push(item["name"]);
      }
    
      res.status(200).send(itemNames);
    }
    // TODO 12: Check for expired token.
    
  4. Remplacez TODO 12 par le code suivant. Ce code vérifie spécifiquement si le jeton a expiré, car le client peut demander un nouveau jeton et appeler à nouveau.

    } catch (err) {
       // On rare occasions the SSO access token is unexpired when Office validates it,
       // but expires by the time it is used in the OBO flow. Microsoft identity platform will respond
       // with "The provided value for the 'assertion' is not valid. The assertion has expired."
       // Construct an error message to return to the client so it can refresh the SSO token.
       if (err.errorMessage.indexOf('AADSTS500133') !== -1) {
         res.status(401).send({ type: "TokenExpiredError", errorDetails: err });
       } else {
         res.status(403).send({ type: "Unknown", errorDetails: err });
       }
    }
    

L’exemple doit gérer à la fois l’authentification de secours via MSAL et l’authentification unique via Office. L’exemple essaie d’abord l’authentification unique, et la authSSO valeur booléenne en haut du fichier suit si l’exemple utilise l’authentification unique ou a basculé vers l’authentification de secours.

Exécutez le projet

  1. Assurez-vous d’avoir des fichiers dans votre espace OneDrive afin de pouvoir vérifier les résultats.

  2. Ouvrez une invite de commandes dans la racine du dossier \Begin.

  3. Exécutez la commande npm install pour installer toutes les dépendances de package.

  4. Exécutez la commande npm start pour démarrer le serveur de niveau intermédiaire.

  5. Vous devez charger une version du complément dans une application Office (Excel, Word ou PowerPoint) pour le tester. Les instructions sont fonction de votre plateforme. Vous trouverez des liens vers des instructions sur Charger une version du complément Office pour le tester.

  6. Dans l’application Office, sur le ruban Accueil, sélectionnez le bouton Afficher le complément dans le groupe Node.js SSO pour ouvrir le complément du panneau des tâches.

  7. Cliquez sur le bouton Obtenir des noms de fichier OneDrive. Si vous êtes connecté à Office avec un compte Microsoft 365 Éducation ou professionnel, ou un compte Microsoft, et que l’authentification unique fonctionne comme prévu, les 10 premiers noms de fichiers et de dossiers de votre OneDrive Entreprise sont insérés dans le document. (La première fois, il peut s’agir de 15 secondes.) Si vous n’êtes pas connecté, ou si vous êtes dans un scénario qui ne prend pas en charge l’authentification unique ou si l’authentification unique ne fonctionne pas pour une raison quelconque, vous êtes invité à vous connecter. Une fois connecté, les noms des fichiers et des dossiers s’affichent.

Remarque

Si vous étiez précédemment connecté à Office avec un ID différent et si certaines applications précédemment ouvertes Office le sont toujours, Office ne changera pas systématiquement votre identifiant même si cela semble être le cas. Dans ce cas, l’appel vers Microsoft Graph peut échouer ou des données de l’ID précédent peuvent être renvoyées. Afin d’éviter ce problème, veillez à fermer toutes les autres applications Office avant de cliquer sur Obtenir des noms de fichiers OneDrive.

Notes de sécurité

  • L’itinéraire /getuserfilenames dans getFilesroute.js utilise une chaîne littérale pour composer l’appel pour Microsoft Graph. Si vous modifiez l’appel de sorte qu’une partie de la chaîne provient d’une entrée utilisateur, nettoyez l’entrée afin qu’elle ne puisse pas être utilisée dans une attaque par injection d’en-tête de réponse.

  • Dans app.js le contenu suivant, une stratégie de sécurité est en place pour les scripts. Vous pouvez spécifier des restrictions supplémentaires en fonction des besoins de sécurité de votre complément.

    "Content-Security-Policy": "script-src https://appsforoffice.microsoft.com https://ajax.aspnetcdn.com https://alcdn.msauth.net " + process.env.SERVER_SOURCE,

Suivez toujours les meilleures pratiques en matière de sécurité dans la documentation Plateforme d'identités Microsoft.