Se connecter à l’API sécurisée avec Azure Active Directory

Lorsque vous créez des solutions SharePoint Framework, vous pouvez avoir besoin de vous connecter à votre API personnalisée pour récupérer des données ou communiquer avec les applications métier. La sécurisation des API personnalisées avec Microsoft Azure Active Directory (Azure AD) vous offre de nombreux avantages et vous pouvez y parvenir de plusieurs manières. Une fois que vous avez créé l’API, vous pouvez y accéder de plusieurs façons. Ces méthodes peuvent être plus ou moins complexes et chacune présente des considérations spécifiques.

Cet article traite des différentes approches et décrit le processus détaillé de la sécurisation d’une API avec Azure Active Directory et de la connexion à celle-ci.

Important

Lors de la connexion aux API sécurisées par Azure AD, nous vous conseillons d’utiliser les classes MSGraphClient et AadHttpClient qui sont désormais généralement disponibles. Pour plus d’informations sur les modèles recommandés, reportez-vous à Se connecter aux API sécurisées par Azure AD dans les solutions SharePoint Framework et à Utiliser MSGraphClient pour la connexion à Microsoft Graph.

Sécurisation d’une API avec Azure Active Directory

Si vous utilisez Office 365, la sécurisation des API personnalisées à l’aide d’Azure AD est une option architecturale que vous devez impérativement envisager. Tout d’abord, elle vous permet de sécuriser l’accès à l’API à l’aide des informations d’identification professionnelles existantes qui sont déjà gérées via Office 365 et Azure AD. Les utilisateurs ayant un compte actif peuvent travailler de façon transparente avec des applications qui utilisent des API sécurisées avec Azure Active Directory. Les administrateurs Azure AD peuvent gérer l’accès à l’API de façon centralisée, de la même façon qu’ils gèrent l’accès à toutes les autres applications inscrites avec Azure AD.

En tant que développeur API, l’utilisation d’Azure AD pour sécuriser votre API vous évite de gérer un ensemble propriétaire d’informations d’identification utilisateur et d’implémenter une couche de sécurité personnalisée pour votre API. En outre, Azure AD prend en charge le protocole OAuth, qui vous permet de vous connecter à l’API à partir d’une gamme de types d’application, allant des applications mobiles aux solutions côté client.

Lorsque vous créez des API personnalisées, vous pouvez sécuriser votre API avec Azure Active Directory de deux manières principales. Si vous hébergez l’API dans Microsoft Azure App Service, vous pouvez tirer parti de l’option Authentification App Service. Si vous souhaitez jouir d’une meilleure flexibilité d’hébergement pour votre API, par exemple, si vous voulez l’héberger sur votre propre infrastructure ou sur des conteneurs Docker, vous devez la sécuriser à l’aide de code. Dans ces conditions, l’implémentation dépend du langage de programmation et de l’infrastructure que vous utilisez.

Dans cet article, lors de l’explication de cette option, vous utiliserez le langage C# et l’API web ASP.NET comme infrastructure.

Sécuriser l’API en utilisant l’option Authentification Azure App Service

Lors du déploiement d’API personnalisées sur Azure App Service, vous pouvez tirer parti de l’option Authentification App Service pour sécuriser l’API à l’aide d’Azure Active Directory. L’avantage principal de l’utilisation de l’authentification App Service réside dans sa simplicité : en suivant les étapes de configuration disponibles sur le portail Azure, vous pourrez laisser l’Assistant préparer la configuration de l’authentification pour vous. Si vous choisissez la configuration de base, l’Assistant crée une application Azure AD dans un service Azure AD associé à l’abonnement actuel. Avec la configuration avancée, vous pouvez choisir l’application Azure AD qui sera utilisée pour sécuriser l’accès à l’App Service qui héberge l’API.

Paramètres de l’option Authentification App Service affichés dans le portail Azure

Après que l’authentification App Service a été configurée, les utilisateurs qui tentent d’accéder à votre API sont invités à se connecter avec leur compte professionnel appartenant au même service Azure AD que l’application Azure AD utilisée pour sécuriser l’API. Une fois connecté, vous pouvez accéder aux informations relatives à l’utilisateur actuel grâce à la propriété HttpContext.Current.User. Lorsque vous utilisez l’authentification Azure App Service, aucune configuration supplémentaire n’est requise dans votre application.

L’authentification Azure App Service est une fonctionnalité disponible uniquement dans Azure App Service. Tandis que cette fonctionnalité simplifie considérablement l’implémentation de l’authentification dans votre API, elle l’associe à l’exécution dans Azure App Service. Si vous voulez héberger l’API chez un autre fournisseur cloud ou dans un conteneur Docker, vous devez commencer par implémenter la couche d’authentification.

Sécurisation de l’API à l’aide de l’authentification ASP.NET

Si vous voulez bénéficier d’un maximum de flexibilité concernant l’endroit où est hébergée votre API et la manière dont elle est déployée, vous pouvez envisager d’implémenter la prise en charge de l’authentification Azure AD dans ASP.NET. Visual Studio facilite considérablement le processus d’implémentation, et une fois que l’Assistant Configuration d’authentification a terminé, votre API requiert que les utilisateurs se connectent à l’aide de leur compte professionnel.

Assistant de configuration de l’authentification Visual Studio

Pendant le processus de configuration, Visual Studio ajoute tous les paramètres et les références nécessaires à votre projet d’API web ASP.NET, notamment l’inscription d’une nouvelle application Azure AD pour sécuriser votre API.

Accès à une API sécurisée avec Azure AD à partir de solutions SharePoint Framework

Les solutions SharePoint Framework sont entièrement côté client et sont, par conséquent, incapables de stocker en toute sécurité les clés secrètes requises pour la connexion à l’API sécurisée. Pour assurer la communication sécurisée avec les solutions côté client, Azure AD prend en charge plusieurs mécanismes tels que les cookies d’authentification ou le flux implicite OAuth.

En règle générale, lorsque vous créez des solutions SharePoint Framework, vous utilisez la classe MSGraphClient pour vous connecter à Microsoft Graph et la classe AadHttpClient pour vous connecter à une API d’entreprise sécurisée avec Azure AD. Cependant, si vous travaillez avec une infrastructure JavaScript qui a son propre service pour exécuter des requêtes web, comme AngularJS ou jQuery, ou que votre solution est basée sur une version antérieure de SharePoint Framework, vous devez utiliser d’autres approches pour obtenir un jeton d’accès aux API sécurisées avec Azure AD.

Flux d’autorisation Azure AD

Office 365 utilise Azure Active Directory (Azure AD) pour sécuriser ses API, qui sont accessibles via Microsoft Graph. Azure AD utilise OAuth comme protocole d’autorisation. Quand une application termine le flux d’autorisation OAuth, elle obtient un jeton d’accès temporaire. Ce jeton permet d’accéder à des ressources spécifiques au nom de l’utilisateur à l’aide d’autorisations accordées à l’application par cet utilisateur.

Il existe différents types de flux OAuth selon les types d’application. Les applications web utilisent un flux OAuth pour rediriger Azure AD vers l’URL dans laquelle l’application est hébergée. La redirection est une mesure de sécurité supplémentaire pour vérifier l’authenticité de l’application.

Les applications clientes, telles que les applications iOS et Android, n’ont pas d’URL et ne peuvent pas utiliser la redirection. Elles suivent donc le flux OAuth sans redirection. Les applications clientes et les applications web utilisent un ID client connu publiquement et une clé secrète client privée connue uniquement d’Azure AD et de l’application.

Les applications web côté client sont semblables aux applications web, mais elles sont implémentées à l’aide d’un code JavaScript et s’exécutent dans le contexte d’un navigateur. Ces applications sont incapables d’utiliser une clé secrète client sans la révéler aux utilisateurs. Par conséquent, elles utilisent un flux d’autorisation appelé flux implicite OAuth pour accéder aux ressources protégées par Azure AD. Dans ce flux, le contrat entre l’application et Azure AD est établi sur la base de l’ID client publiquement connu et de l’URL de l’emplacement où l’application est hébergée. Il s’agit du flux que les composants WebPart côté client de SharePoint Framework doivent utiliser pour se connecter aux ressources sécurisées avec Azure AD.

Utiliser la classe AadTokenProvider pour extraire des jetons d’accès

Lorsque vous travaillez avec des bibliothèques JavaScript qui disposent de leurs propres services d’exécution de requêtes web, la méthode recommandée pour obtenir un jeton d’accès à une API sécurisée avec Azure AD est d’utiliser la classe AadTokenProvider disponible à partir de SharePoint Framework v1.6.0. Par rapport à d’autres solutions, la classe AadTokenProvider simplifie considérablement l’implémentation des flux implicites OAuth dans les solutions SharePoint Framework, ce qui vous permet de vous concentrer sur la création de votre application.

Notes

Il est recommandé de mettre régulièrement à jour vos solutions SharePoint Framework vers la version la plus récente de SharePoint Framework pour tirer parti des améliorations et des nouvelles fonctionnalités ajoutées par Microsoft.

Demander des autorisations pour accéder aux API sécurisées avec Azure AD

Si votre solution SharePoint Framework nécessite des autorisations pour accéder à certaines ressources sécurisées avec Azure AD, comme des API d’entreprise, spécifiez ces ressources et les autorisations nécessaires dans la configuration de votre solution.

  1. Dans votre projet SharePoint Framework, ouvrez le fichier config/package-solution.json.

  2. Pour la propriété solution, ajoutez la propriété webApiPermissionRequests qui répertorie toutes les ressources et les autorisations correspondantes requises par votre solution.

    Vous trouverez par la suite un exemple de solution SharePoint Framework qui demande l’accès aux API d’entreprise :

    {
      "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
      "solution": {
        "name": "spfx-client-side-solution",
        "id": "5d16587c-5e87-44d7-b658-1148988f212a",
        "version": "1.0.0.0",
        "includeClientSideAssets": true,
        "skipFeatureDeployment": true,
        "webApiPermissionRequests": [
          {
            "resource": "Enterprise-API-Name",
            "scope": "user_impersonation"
          }
        ]
      },
      "paths": {
        "zippedPackage": "solution/spfx-api.sppkg"
      }
    }
    

    Notes

    Pour la valeur de la propriété resource, vous pouvez spécifier l’élément displayName ou objectId de l’application pour laquelle vous souhaiter demander des autorisations. L’élément displayName est non seulement plus lisible, mais il permet également de créer votre solution une seule fois, puis de la réutiliser sur plusieurs clients. Alors que l’élément objectId d’une application Azure AD est différent sur chaque client, l’élément displayName ne change pas.

  3. Quand cette solution est déployée sur le catalogue d’applications SharePoint, l’administrateur est invité à vérifier les autorisations demandées, puis à les accorder ou les refuser. Lisez l’article Gérer les demandes d’autorisation pour en savoir plus sur les différentes manières de gérer des demandes d’autorisation.

Acquisition d’un jeton d’accès

Vous trouverez ci-dessous un exemple de code expliquant comment utiliser la classe AadTokenProvider pour extraire un jeton d’accès pour une API d’entreprise sécurisée avec Azure AD et l’utiliser pour effectuer une requête web à l’aide de jQuery :

// ...
import * as $ from 'jquery';
import { AadTokenProvider } from '@microsoft/sp-http';

export default class OrdersWebPart extends BaseClientSideWebPart<IOrdersWebPartProps> {
  // ...

  public render(): void {
    this.context.statusRenderer.displayLoadingIndicator(this.domElement, 'orders');

    this.context.aadTokenProviderFactory
      .getTokenProvider()
      .then((tokenProvider: AadTokenProvider): Promise<string> => {
        // retrieve access token for the enterprise API secured with Azure AD
        // the parameter passed into getToken()is the Application ID URI
        return tokenProvider.getToken('https://contoso.azurewebsites.net');
      })
      .then((accessToken: string): void => {
        // call the enterprise API using jQuery passing the access token
        $.get({
          url: 'https://contoso.azurewebsites.net/api/Orders',
          headers: {
            authorization: `Bearer ${accessToken}`,
            accept: 'application/json'
          }
        })
        .done((orders: any): void => {
          this.context.statusRenderer.clearLoadingIndicator(this.domElement);
            this.domElement.innerHTML = `
            <div class="${ styles.orders}">
              <div class="${ styles.container}">
                <div class="${ styles.row}">
                  <div class="${ styles.column}">
                    <span class="${ styles.title}">Orders</span>
                    <p class="${ styles.description}">
                      <ul>
                        ${orders.map(o => `<li>${o.Rep} $${o.Total}</li>`).join('')}
                      </ul>
                    </p>
                    <a href="https://aka.ms/spfx" class="${ styles.button}">
                      <span class="${ styles.label}">Learn more</span>
                    </a>
                  </div>
                </div>
              </div>
            </div>`;
        });
      });
  }

  // ...
}

Vous commencez par récupérer une instance de AadTokenProvider à l’aide de la aadTokenProviderFactory. Vous devez ensuite utiliser la AadTokenProvider pour récupérer le jeton d’accès de votre API sécurisée avec Azure AD. Une fois que vous avez obtenu le jeton d’accès, exécutez la requête AJAX sur l’API d’entreprise, en incluant le jeton d’accès dans les en-têtes de la requête.

Utiliser ADAL JS pour traiter l’autorisation et récupérer le jeton d’accès

Si vous utilisez une version plus ancienne que v1.6.0 de SharePoint Framework et que vous ne pouvez pas utiliser la AadTokenProvider, vous pouvez utiliser la bibliothèque de ADAL JS pour gérer le flux implicite OAuth et récupérer le jeton d’accès pour l’API spécifique sécurisée avec Azure AD. Pour les applications créées à l’aide d’AngularJS, ADAL JS propose un intercepteur de requêtes HTTP qui ajoute automatiquement les jetons d’accès requis aux en-têtes des requêtes web sortantes. En utilisant ce demandeur, les développeurs n’ont pas besoin de modifier les requêtes web adressées aux API sécurisées avec Azure Active Directory et peuvent à la place se concentrer sur la création de l’application.

Limitations lors de l’utilisation d’ADAL JS avec les composants WebPart côté client

La bibliothèque ADAL JS simplifie considérablement la mise en œuvre du flux OAuth pour Azure AD dans les applications web côté client. Cela dit, elle présente un certain nombre de limitations lorsqu’elle est utilisée avec des composants WebPart côté client pour SharePoint Framework. Ces limitations sont dues au fait que la bibliothèque ADAL JS est conçue pour être utilisée par les applications web côté client qui sont propriétaires de la page entière et la partagent pas avec d’autres applications.

Stockage partagé

Selon la configuration de la bibliothèque ADAL JS dans votre projet, elle stocke ses données dans le stockage local du navigateur ou dans le stockage de la session. Dans les deux cas, les informations stockées par ADAL JS sont accessibles à n’importe quel composant sur la même page. Par exemple, si un composant WebPart extrait un jeton d’accès pour Microsoft Graph, n’importe quel autre composant WebPart de la même page peut réutiliser ce jeton et appeler Microsoft Graph.

ADAL JS comme singleton

ADAL JS est conçue pour fonctionner comme un service singleton inscrit dans l’étendue globale de la page. Lors du traitement des rappels de flux OAuth dans des IFrames, le code ADAL JS utilise la référence de singleton inscrite à partir de la fenêtre principale pour résoudre le flux du jeton. Dans la mesure où chaque composant WebPart est inscrit avec une autre application Azure Active Directory, le fait de réutiliser la même instance d’ADAL JS entraine des résultats indésirables, à savoir que chaque composant WebPart utilise la même configuration que celle inscrite par le premier composant WebPart chargé sur la page.

Stockage basé sur les ressources

Par défaut, la bibliothèque ADAL JS stocke des informations, telles que le jeton d’accès actuel ou son délai d’expiration, dans un jeu de clés associées à la ressource concernée, par exemple Microsoft Graph ou SharePoint. Si plusieurs composants d’une même page accèdent à la même ressource avec des autorisations différentes, le premier jeton récupéré est fournis par ADAL JS à tous les composants. Si différents composants nécessitent un accès à la même ressource, ils peuvent rencontrer une erreur. Pour illustrer cette limitation, prenons l’exemple suivant.

Imaginez qu’une page comporte deux composants WebPart : un qui répertorie les réunions à venir et un qui crée une nouvelle réunion. Pour récupérer les réunions à venir, le composant WebPart qui les gère utilise un jeton d’accès Microsoft Graph doté d’autorisations permettant de lire les calendriers des utilisateurs. En revanche, le composant WebPart qui crée des réunions nécessite un jeton d’accès Microsoft Graph doté d’autorisations d’écriture dans les calendriers des utilisateurs.

Si le composant WebPart qui gère les réunions à venir est chargé en premier, ADAL JS récupère son jeton, qui fournit uniquement une autorisation de lecture. Le même jeton est ensuite fourni par ADAL JS au composant WebPart qui crée des réunions. Comme vous pouvez le constater, lorsque le composant WebPart tente de créer une nouvelle réunion, il rencontre une erreur de type « accès refusé ». En raison du stockage basé sur les ressources, ADAL JS ne récupère pas de nouveau jeton pour Microsoft Graph tant que le jeton extrait précédemment n’a pas expiré.

Traitement des rappels d’autorisation

Le flux implicite OAuth fonctionne sur le principe de redirections entre Azure Active Directory et l’application participant au flux. Quand le processus d’authentification démarre, l’application vous redirige vers la page de connexion à Azure Active Directory. Une fois l’authentification terminée, Azure AD vous redirige vers l’application et envoie le jeton d’identité dans le hachage URL pour que l’application le traite. Pour un composant WebPart placé sur une page SharePoint, ce comportement présente deux inconvénients.

Même si vous êtes connecté à SharePoint, vous devez vous authentifier séparément sur Azure AD afin que votre composant WebPart puisse accéder aux ressources sécurisées avec Azure Active Directory. Le composant WebPart ne représente qu’une petite partie de la page entière, mais le processus d’authentification requiert de quitter entièrement cette dernière, ce qui représente une expérience utilisateur médiocre.

Une fois l’authentification terminée, Azure AD vous redirige vers votre application. Il inclut le jeton d’identité que votre application doit traiter dans le hachage d’URL. Malheureusement, comme ce jeton d’identité ne contient pas d’informations d’origine, si une même page contient plusieurs composants WebPart, ils essaient tous de traiter le jeton d’identité à partir de l’URL.

Remarques sur l’utilisation de la bibliothèque ADAL JS pour communiquer avec les API sécurisées avec Azure AD

Hormis les limitations, vous devez tenir compte de plusieurs éléments avant d’implémenter ADAL JS dans votre solution SharePoint Framework vous-même.

ADAL JS est destinée à être utilisée pour les applications monopage

La bibliothèque ADAL JS est conçue pour être utilisée avec des applications d’une seule page. Par défaut, elle ne fonctionne donc pas correctement lorsqu’elle est utilisée avec les solutions SharePoint Framework. Toutefois, elle peut être utilisée avec succès dans des projets SharePoint Framework en appliquant un correctif.

Gérer toutes les exceptions d’authentification possibles vous-même

Lorsque vous utilisez ADAL JS et OAuth pour accéder aux API sécurisées avec Azure AD, le flux d’authentification est facilité par Azure. Toute erreur est gérée grâce à la page de connexion Azure. Une fois que l’utilisateur s’est connecté avec son compte professionnel, l’application tente de récupérer un jeton d’accès valide. Toutes les erreurs qui se produisent à ce stade doivent être explicitement gérées par le développeur de l’application, car la récupération de jetons d’accès n’est pas interactive et ne présente aucune interface utilisateur à l’utilisateur.

Enregistrer toutes les applications côté client dans Azure AD

Chaque application côté client qui souhaite utiliser ADAL JS doit être inscrite en tant qu’application Azure AD. L’URL de l’emplacement où se trouve l’application constitue une partie des informations d’inscription. Étant donné que l’application est entièrement côté client et qu’elle n’est pas capable de stocker en toute sécurité une clé secrète, l’URL fait partie du contrat entre l’application et Azure AD pour l’établissement de la sécurité. Cette exigence pose problème pour les solutions SharePoint Framework car les développeurs ne peuvent simplement pas connaître d’emblée toutes les URL où un composant WebPart particulier sera utilisé. En outre, en ce moment, Azure AD prend en charge la spécification de 10 URL de réponse au maximum, ce qui peut se révéler insuffisant dans certaines situations.

Mettre en œuvre le flux d’autorisation dans chaque composant WebPart

Pour qu’une application côté client puisse récupérer un jeton d’accès vers une ressource spécifique, elle doit authentifier l’utilisateur pour obtenir le jeton d’ID qui peut ensuite être échangé avec un jeton d’accès. Même si les solutions SharePoint Framework sont hébergées dans SharePoint, où les utilisateurs sont déjà connectés à l’aide de leurs comptes professionnels, les informations d’authentification de l’utilisateur actuel ne sont pas disponibles pour les solutions SharePoint Framework. Au lieu de cela, chaque solution doit demander explicitement à l’utilisateur de se connecter. Elles peuvent le faire soit en redirigeant l’utilisateur vers la page de connexion Azure, soit en affichant une fenêtre contextuelle avec la page de connexion. Cette dernière option est moins intrusive dans le cas d’un composant WebPart, qui constitue l’un des nombreux éléments d’une page. Si plusieurs composants WebPart SharePoint Framework côté client figurent sur la page, chacun d’eux gère son état séparément et nécessite que l’utilisateur se connecte de manière explicite à ce composant WebPart spécifique.

Configurer les zones de sécurité d’Internet Explorer

La récupération des jetons d’accès requis pour communiquer avec les API sécurisées avec Azure Active Directory est facilitée par les balises iframe masquées qui gèrent les redirections vers les points de terminaison Azure AD. Il existe une limitation connue dans Microsoft Internet Explorer où l’obtention de jetons d’accès dans le flux implicite OAuth échoue si les points de terminaison de connexion Azure AD et l’URL de SharePoint Online ne figurent pas dans la même zone de sécurité. Si votre organisation utilise Internet Explorer, vérifiez que le point de terminaison Azure AD et les URL de SharePoint Online sont configurés dans la même zone de sécurité. Pour conserver la cohérence, certaines organisations choisissent de transmettre ces paramètres aux utilisateurs finaux à l’aide de stratégies de groupe.

Ajouter le jeton d’accès à toutes les requêtes AJAX sur des API sécurisées avec Azure AD

Les API sécurisées avec Azure AD ne sont pas accessibles de manière anonyme. Elles requièrent à la place que l’application qui les appelle présente des informations d’identification valides. Lorsque vous utilisez le flux implicite OAuth avec les applications côté client, ces informations d’identification sont le jeton d’accès de support obtenu à l’aide d’ADAL JS. Si vous avez créé votre solution SharePoint Framework à l’aide d’AngularJS, ADAL JS garantit automatiquement que vous avez un jeton d’accès valide pour cette ressource particulière et l’ajoute à toutes les requêtes sortantes exécutées à l’aide du service $http AngularJS. Lorsque vous utilisez d’autres bibliothèques JavaScript, vous devez obtenir un jeton d’accès valide, l’actualiser si nécessaire et le joindre aux requêtes web sortantes vous-même.

Utiliser ADAL JS avec des composants WebPart côté client

Vous pouvez contourner les limitations d’ADAL JS pour implémenter OAuth dans votre composant WebPart côté client pour SharePoint Framework.

Important

Les instructions suivantes sont basées sur ADAL JS v1.0.12. Lors de l’ajout d’ADAL JS à vos projets d’infrastructure SharePoint, vérifiez que vous installez ADAL JS v1.0.12. Sinon, les instructions mentionnées dans cet article ne fonctionneront pas comme prévu.

Chargement d’ADAL JS dans votre composant WebPart

Les composants WebPart sont créées avec TypeScript et distribués sous forme de modules AMD. Leur architecture modulaire vous permet d’isoler les différentes ressources utilisées par le composant WebPart. La bibliothèque ADAL JS est conçue pour s’inscrire dans l’étendue globale, mais vous pouvez la charger dans un composant WebPart en utilisant le code suivant :

import * as AuthenticationContext from 'adal-angular';

Cette instruction importe la classe AuthenticationContext, qui expose les fonctionnalités d’ADAL JS à utiliser dans les composants WebPart. Malgré le nom du module, la classe AuthenticationContext fonctionne avec toutes les bibliothèques JavaScript.

Adapter ADAL JS aux composants WebPart de SharePoint Framework

La fonctionnalité ADAL JS est actuellement inadaptée pour les composants WebPart. Utilisez le correctif suivant pour qu’ADAL JS fonctionne dans votre composant WebPart.

WebPartAuthenticationContext.js

const AuthenticationContext = require('adal-angular');

AuthenticationContext.prototype._getItemSuper = AuthenticationContext.prototype._getItem;
AuthenticationContext.prototype._saveItemSuper = AuthenticationContext.prototype._saveItem;
AuthenticationContext.prototype.handleWindowCallbackSuper = AuthenticationContext.prototype.handleWindowCallback;
AuthenticationContext.prototype._renewTokenSuper = AuthenticationContext.prototype._renewToken;
AuthenticationContext.prototype.getRequestInfoSuper = AuthenticationContext.prototype.getRequestInfo;
AuthenticationContext.prototype._addAdalFrameSuper = AuthenticationContext.prototype._addAdalFrame;

AuthenticationContext.prototype._getItem = function (key) {
  if (this.config.webPartId) {
    key = this.config.webPartId + '_' + key;
  }

  return this._getItemSuper(key);
};

AuthenticationContext.prototype._saveItem = function (key, object) {
  if (this.config.webPartId) {
    key = this.config.webPartId + '_' + key;
  }

  return this._saveItemSuper(key, object);
};

AuthenticationContext.prototype.handleWindowCallback = function (hash) {
  if (hash == null) {
    hash = window.location.hash;
  }

  if (!this.isCallback(hash)) {
    return;
  }

  var requestInfo = this.getRequestInfo(hash);
  if (requestInfo.requestType === this.REQUEST_TYPE.LOGIN) {
    return this.handleWindowCallbackSuper(hash);
  }

  var resource = this._getResourceFromState(requestInfo.stateResponse);
  if (!resource || resource.length === 0) {
    return;
  }

  if (this._getItem(this.CONSTANTS.STORAGE.RENEW_STATUS + resource) === this.CONSTANTS.TOKEN_RENEW_STATUS_IN_PROGRESS) {
    return this.handleWindowCallbackSuper(hash);
  }
}

AuthenticationContext.prototype._renewToken = function (resource, callback) {
  this._renewTokenSuper(resource, callback);
  var _renewStates = this._getItem('renewStates');
  if (_renewStates) {
    _renewStates = _renewStates.split(',');
  }
  else {
    _renewStates = [];
  }
  _renewStates.push(this.config.state);
  this._saveItem('renewStates', _renewStates);
}

AuthenticationContext.prototype.getRequestInfo = function (hash) {
  var requestInfo = this.getRequestInfoSuper(hash);
  var _renewStates = this._getItem('renewStates');
  if (!_renewStates) {
    return requestInfo;
  }

  _renewStates = _renewStates.split(';');
  for (var i = 0; i < _renewStates.length; i++) {
    if (_renewStates[i] === requestInfo.stateResponse) {
      requestInfo.requestType = this.REQUEST_TYPE.RENEW_TOKEN;
      requestInfo.stateMatch = true;
      break;
    }
  }

  return requestInfo;
}

AuthenticationContext.prototype._addAdalFrame = function (iframeId) {
  var adalFrame = this._addAdalFrameSuper(iframeId);
  adalFrame.style.width = adalFrame.style.height = '106px';
  return adalFrame;
}

window.AuthenticationContext = function() {
  return undefined;
}

Le correctif applique les modifications suivantes à ADAL JS :

  • Toutes les informations sont stockées dans une clé propre au composant WebPart (voir le remplacement des fonctions _getItem et _saveItem).
  • Les rappels sont traités uniquement par les composants WebPart qui les ont lancés (voir le remplacement de la fonction handleWindowCallback).
  • Lors de la vérification des données des rappels, l’instance de la classe AuthenticationContext du composant WebPart concerné est utilisée à la place du singleton enregistré globalement (voir _renewToken, getRequestInfo et l’enregistrement vide de la fonction window.AuthenticationContext).
Utilisation du correctif ADAL JS dans les composants WebPart de SharePoint Framework

Pour que la bibliothèque ADAL JS fonctionne correctement dans les composants WebPart de SharePoint Framework, vous devez la configurer d’une façon spécifique.

  1. Définissez une interface personnalisée qui étend l’interface Config ADAL JS standard pour exposer des propriétés supplémentaires sur l’objet de configuration.

    export interface IAdalConfig extends adal.Config {
      popUp?: boolean;
      callback?: (error: any, token: string) => void;
      webPartId?: string;
    }
    

La propriété popUp et la fonction callback sont toutes les deux déjà mises en œuvre dans ADAL JS, mais ne sont pas exposées dans les typages TypeScript de l’interface Config standard. Vous en avez besoin pour permettre aux utilisateurs de se connecter à votre composant WebPart à l’aide d’une fenêtre contextuelle au lieu de les rediriger vers la page de connexion d’Azure AD.

  1. Chargez le correctif ADAL JS, l’interface de configuration personnalisée et l’objet de configuration dans le composant principal de votre composant WebPart.

    import * as AuthenticationContext from 'adal-angular';
    import adalConfig from '../AdalConfig';
    import { IAdalConfig } from '../../IAdalConfig';
    import '../../WebPartAuthenticationContext';
    
  2. Dans le constructeur de votre composant, étendez la configuration d’ADAL JS en y ajoutant des propriétés supplémentaires et utilisez-la pour créer une nouvelle instance de la classe AuthenticationContext.

    export default class UpcomingMeetings extends React.Component<IUpcomingMeetingsProps, IUpcomingMeetingsState> {
      private authCtx: adal.AuthenticationContext;
    
      constructor(props: IUpcomingMeetingsProps, state: IUpcomingMeetingsState) {
        super(props);
    
        this.state = {
          loading: false,
          error: null,
          upcomingMeetings: [],
          signedIn: false
        };
    
        const config: IAdalConfig = adalConfig;
        config.webPartId = this.props.webPartId;
        config.popUp = true;
        config.callback = (error: any, token: string): void => {
          this.setState((previousState: IUpcomingMeetingsState, currentProps: IUpcomingMeetingsProps): IUpcomingMeetingsState => {
            previousState.error = error;
            previousState.signedIn = !(!this.authCtx.getCachedUser());
            return previousState;
          });
        };
    
        this.authCtx = new AuthenticationContext(config);
        AuthenticationContext.prototype._singletonInstance = undefined;
      }
    }
    

Tout d’abord, le code récupère l’objet de configuration ADAL JS standard et le convertit au type de l’interface de configuration nouvellement définie.

Puis, il transmet l’ID de l’instance de composant WebPart afin que toutes les valeurs ADAL JS puissent être stockées de façon à ne pas entrer en conflit avec d’autres composants WebPart de la page.

Il active ensuite l’authentification par fenêtre contextuelle et définit une fonction de rappel qui s’exécute à l’issue de l’authentification pour mettre à jour le composant.

Enfin, il crée une instance de la classe AuthenticationContext et réinitialise la valeur _singletonInstance définie dans le constructeur de la classe AuthenticationContext. Cette opération est nécessaire pour permettre à chaque composant WebPart d’utiliser sa propre version du contexte d’authentification ADAL JS.

Remarques sur l’utilisation du flux implicite OAuth dans des composants WebPart côté client

Avant de créer des composants WebPart côté client pour l’infrastructure SharePoint qui communiquent avec des ressources sécurisées par Azure Active Directory, vous devez tenir compte de certaines contraintes. Les informations suivantes vous aident à déterminer si l’autorisation OAuth dans les composants WebPart est la solution adaptée pour votre solution et votre organisation.

Les composants WebPart de SharePoint Framework requièrent un haut degré de fiabilité

Contrairement aux Compléments SharePoint, les composants WebPart utilisent les mêmes autorisations que l’utilisateur. Toutes les tâches que l’utilisateur peut effectuer, peuvent également l’être par le composant WebPart. C’est pourquoi les composants WebPart peuvent uniquement être installés et déployés par les administrateurs du client. Ces derniers doivent ainsi vérifier que les composants WebPart qu’ils déploient proviennent d’une source fiable et ont été approuvés pour le client.

Les composants WebPart font partie de la page et, contrairement aux compléments SharePoint, ils partagent le DOM et les ressources avec d’autres éléments dans la page. Les jetons d’accès aux ressources sécurisées avec Azure AD sont récupérés via un rappel dirigé vers la page où se trouve le composant WebPart. Ce rappel peut être traité par n’importe quel élément de la page. En outre, une fois que les jetons d’accès des rappels sont traités, ils sont stockés en local ou dans la session, emplacements à partir desquels ils peuvent être récupérés par n’importe quel composant de la page. Un composant WebPart malveillant pourrait lire le jeton et l’exposer, lui ou les données qu’il a permis de récupérer, à un service externe.

L’URL fait partie du contrat de flux implicite OAuth

Important

Les informations contenues dans cette section ne s’appliquent pas si vous utilisez la AadTokenProvider car elle gère le flux implicite OAuth pour vous

Les applications côté client sont incapables de stocker une clé secrète client sans la révéler aux utilisateurs. Pour vérifier l’authenticité de l’application, l’URL où l’application est hébergée est utilisée dans le contrat de confiance entre Azure Active Directory et l’application. Par conséquent, l’URL de chaque page comportant des composants WebPart et utilisant le flux implicite OAuth doit être enregistrée par Azure Active Directory. Si une page n’est pas enregistrée, le flux OAuth échoue et le composant WebPart n’a pas accès à la ressource sécurisée.

Cette mesure de sécurité nécessaire est une limitation importante pour les organisations qui autorisent leurs utilisateurs à ajouter des composants WebPart aux pages. Nous vous recommandons de limiter le nombre d’emplacements dans lesquels des composants WebPart utilisant le flux implicite OAuth sont utilisés. Utilisez un petit nombre d’emplacements connus, tels que la page d’accueil ou des pages de destination spécifiques, et inscrivez-les auprès d’Azure AD.

Zones de sécurité d’Internet Explorer

Internet Explorer utilise des zones de sécurité pour appliquer des stratégies de sécurité aux sites web que vous visitez. Les sites web auxquels sont affectées des zones de sécurité différentes sont isolés les uns des autres et ne peuvent pas coopérer. Quand vous utilisez le flux implicite OAuth dans des composants WebPart côté client SharePoint Framework, la page de ces composants WebPart qui utilisent OAuth et la page de connexion à Azure AD (située à l’adresse https://login.microsoftonline.com)) doivent appartenir à la même zone de sécurité. Sans cette configuration, le processus d’authentification échoue et les composants WebPart ne peuvent pas communiquer avec les ressources sécurisées par Azure AD.

L’utilisateur doit se connecter régulièrement

Avec le flux OAuth classique, les applications web et les applications clientes obtiennent un jeton d’accès à courte durée de vie (60 minutes par défaut) et un jeton d’actualisation qui est valide pour une période plus longue. Lorsque le jeton d’accès expire, le jeton d’actualisation est utilisé pour en obtenir un nouveau. Cette méthode réduit la fréquence à laquelle les utilisateurs doivent s’authentifier auprès d’Azure Active Directory.

Dans la mesure où les applications côté client sont incapables de stocker des clés secrètes de façon sécurisée et où la divulgation d’un jeton d’actualisation constitue une grave menace, elles reçoivent uniquement le jeton d’accès dans le cadre du flux implicite OAuth. Lorsque ce jeton expire, l’application doit démarrer un nouveau flux OAuth qui peut requérir que l’utilisateur s’authentifie à nouveau.

Voir aussi