web-dev-qa-db-fra.com

Comment intégrer une annonce Azure dans une application Web React qui utilise également une API REST dans Azure

J'ai une application Web qui est React, et j'ai déjà configuré l'authentification Azure AD pour l'application Web elle-même. Son application de site 100% client, sans composants côté serveur.

J'ai utilisé ce composant: https://github.com/salvoravida/react-adal

Mon code est le suivant: adalconfig.js

import { AuthenticationContext, adalFetch, withAdalLogin } from 'react-adal';

export const adalConfig = {
  tenant: 'mytenantguid',
  clientId: 'myappguid',
  endpoints: {
    api: '14d71d65-f596-4eae-be30-27f079bf8d4b',
  },
  cacheLocation: 'localStorage',
};

export const authContext = new AuthenticationContext(adalConfig);

export const adalApiFetch = (fetch, url, options) =>
  adalFetch(authContext, adalConfig.endpoints.api, fetch, url, options);

export const withAdalLoginApi = withAdalLogin(authContext, adalConfig.endpoints.api);

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import DashApp from './dashApp';
import registerServiceWorker from './registerServiceWorker';
import 'antd/dist/antd.css';

import { runWithAdal } from 'react-adal';
import { authContext } from './adalConfig';

const DO_NOT_LOGIN = false;

runWithAdal(authContext, () => {

  ReactDOM.render(<DashApp />, document.getElementById('root'));

  // Hot Module Replacement API
  if (module.hot) {
    module.hot.accept('./dashApp.js', () => {
      const NextApp = require('./dashApp').default;
      ReactDOM.render(<NextApp />, document.getElementById('root'));
    });
  }

},DO_NOT_LOGIN);


registerServiceWorker();

dashapp.js

import React from "react";
import { Provider } from "react-redux";
import { store, history } from "./redux/store";
import PublicRoutes from "./router";
import { ThemeProvider } from "styled-components";
import { LocaleProvider } from "antd";
import { IntlProvider } from "react-intl";
import themes from "./settings/themes";
import AppLocale from "./languageProvider";
import config, {
  getCurrentLanguage
} from "./containers/LanguageSwitcher/config";
import { themeConfig } from "./settings";
import DashAppHolder from "./dashAppStyle";
import Boot from "./redux/boot";

const currentAppLocale =
  AppLocale[getCurrentLanguage(config.defaultLanguage || "english").locale];


const DashApp = () => (
  <LocaleProvider locale={currentAppLocale.antd}>
    <IntlProvider
      locale={currentAppLocale.locale}
      messages={currentAppLocale.messages}
    >
      <ThemeProvider theme={themes[themeConfig.theme]}>
        <DashAppHolder>
          <Provider store={store}>
            <PublicRoutes history={history} />
          </Provider>
        </DashAppHolder>
      </ThemeProvider>
    </IntlProvider>
  </LocaleProvider>
);
Boot()
  .then(() => DashApp())
  .catch(error => console.error(error));

export default DashApp;
export { AppLocale };

Jusqu'à ce moment, tout fonctionne bien, lorsque l'utilisateur n'est pas authentifié, il est redirigé vers login.live.com pour l'authentification, puis redirigé.

Cependant, j'ai également créé une autre webapp Azure pour héberger une API REST, cette API REST est déjà configurée dans Azure AD, afin que les utilisateurs qui essaient d'utiliser le reste) devra être authentifié.

Maintenant, la question est: comment configurer mon APP côté client pour consommer REST API qui est protégée par Azure AD.?

J'ai trouvé cela et regarde ce que je cherche, mais je ne sais pas comment l'intégrer dans mon code existant ci-dessus

https://github.com/AzureAD/Azure-activedirectory-library-for-js/issues/481

Mise à jour: Pour les lecteurs potentiels

Cette réponse ainsi que les instructions sur cette URL pour configurer les enregistrements d'applications m'ont aidé à résoudre le problème: https://blog.ithinksharepoint.com/2016/05/16/dev-diary-s01e06-Azure-mvc-web -api-angulaire-et-adal-js-et-401s /

13
Luis Valencia

La clé ici est adalApiFetch, définie dans adalConfig.js. Comme vous pouvez le voir, c'est un simple wrapper autour de adalFetch. Cette méthode (définie dans react-adal ) reçoit une instance ADAL (authContext), un identifiant de ressource (resourceGuiId), une méthode (fetch), une URL (url) et un objet (options). La méthode effectue les opérations suivantes:

  1. Utilisez l'instance ADAL (authContext) pour obtenir un jeton d'accès pour la ressource identifiée par resourceGuiId.
  2. Ajoutez ce jeton d'accès au champ headers de l'objet options (ou créez-en un s'il n'a pas été fourni).
  3. Appelez la méthode "fetch" donnée en passant url et l'objet options comme paramètres.

La méthode adalApiFetch (que vous avez définie dans adalConfig.js) appelle simplement adalFetch avec la ressource identifiée dans adalConfig.endpoints.api.

Ok, alors comment utilisez-vous tout cela pour faire une demande REST, et consommer la réponse dans votre application React? Utilisons un exemple. Dans le Dans l'exemple suivant, nous utiliserons l'API Microsoft Graph en tant qu'API protégée par Azure AD REST. Nous l'identifierons par son identifiant URI (" https: // graph .Microsoft.com "), mais gardez à l'esprit que cela pourrait tout aussi bien être l'ID de l'application Guid.

adalConfig.js définit la configuration ADAL et exporte quelques méthodes d'assistance:

import { AuthenticationContext, adalFetch, withAdalLogin } from 'react-adal';

export const adalConfig = {
tenant: '{tenant-id-or-domain-name}',
clientId: '{app-id-of-native-client-app}',
endpoints: {
    api: 'https://graph.Microsoft.com' // <-- The Azure AD-protected API
},
cacheLocation: 'localStorage',
};

export const authContext = new AuthenticationContext(adalConfig);

export const adalApiFetch = (fetch, url, options) =>
adalFetch(authContext, adalConfig.endpoints.api, fetch, url, options);

export const withAdalLoginApi = withAdalLogin(authContext, adalConfig.endpoints.api);

index.js encapsule indexApp.js avec la méthode runWithAdal de react-adal, qui garantit que l'utilisateur est signé avec Azure AD avant de charger indexApp.js:

import { runWithAdal } from 'react-adal';
import { authContext } from './adalConfig';

const DO_NOT_LOGIN = false;

runWithAdal(authContext, () => {

// eslint-disable-next-line
require('./indexApp.js');

},DO_NOT_LOGIN);

indexApp.js charge et rend simplement une instance de App, rien de spécial ici:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

App.js est un composant simple où la magie opère:

  • Nous définissons une valeur state. Dans ce cas, cela s'appelle apiResponse puisque nous affichons simplement la réponse brute de l'API, mais bien sûr, vous pouvez nommer cet état comme vous le souhaitez (ou avoir plusieurs valeurs d'état).
  • Pendant componentDidMount (qui est exécuté après que l'élément est disponible dans le DOM), nous appelons le adalApiFetch. Nous passons fetch (à partir de Fetch API comme paramètre fetch, et le point de terminaison pour la demande REST que nous voulons faire le /me endpoint dans Microsoft Graph, dans ce cas):
  • Dans la méthode render, nous affichons simplement cette valeur d'état dans un <pre> élément.
import React, { Component } from 'react';
import { adalApiFetch } from './adalConfig';

class App extends Component {

  state = {
    apiResponse: ''
  };

  componentDidMount() {

    // We're using Fetch as the method to be called, and the /me endpoint 
    // from Microsoft Graph as the REST API request to make.
    adalApiFetch(fetch, 'https://graph.Microsoft.com/v1.0/me', {})
      .then((response) => {

        // This is where you deal with your API response. In this case, we            
        // interpret the response as JSON, and then call `setState` with the
        // pretty-printed JSON-stringified object.
        response.json()
          .then((responseJson) => {
            this.setState({ apiResponse: JSON.stringify(responseJson, null, 2) })
          });
      })
      .catch((error) => {

        // Don't forget to handle errors!
        console.error(error);
      })
  }

  render() {
    return (
      <div>
        <p>API response:</p>
        <pre>{ this.state.apiResponse }</pre>
      </div>
    );
  }
}

export default App;
9