Cet article fait suite à deux précédents articles sur la configuration des rôles sous Azure Active Directory et leurs utilisations depuis une API développée sous le Framework Java Spring Boot. L’objectif était de permettre l’affectation de rôles applicatifs à des groupes d’utilisateurs, paramétrés sous Azure Active Directory, pour accéder à des routes sécurisées de nos API Java. Si ce n’est déjà fait je vous invite à les lire avant de poursuivre:

Dans le cas présent nous allons nous intéresser à une manière simple de développer et déployer localement une infrastructure orientée Web, mais de façon à être au plus proche d’une mise en production actuelle.

Dans l’article dédié à l’API Java, l’application Web était émulée par le simulateur d’appel REST Postman. Nous allons ici développer une Web App ainsi qu’une SPA, à l’aide du Framework vue.js, en plus de la Web API déjà réalisée précédemment.

Notre cas d’utilisation va mixer l’ensemble des éléments vu jusqu’alors, c’est à dire l’accès sécurisée à la Web App via une identification de l’utilisateur depuis Azure AD. Puis l’accès à la Web API depuis la Web App à l’aide du token d’accès JWT retourné par Azure. On s’appuiera sur le principe obo (on-behalf-of) pour le transfert de token. Des informations seront enfin retransmises à la SPA pour afficher des données utilisateurs réclamées auprès de la Web API Java, mais aussi de l’API Microsoft Graph. Et si tout se passe comme il faut vous devriez avoir à l’écran quelque chose de ce genre (avec vos informations bien entendu) :

Le workflow aura alors cette forme :

L’ensemble des codes sources de cet article sont accessibles depuis le dépôt GitHub d’Ingéniance : https://github.com/INGENIANCE/OAuth2-With-AzureAD

Définition de l’architecture

Notre infrastructure utilise le protocole OAuth 2.0 pour l’identification des utilisateurs et s’appuis sur le fournisseur d’accès Azure Active Directory de Microsoft pour l’obtention d’un token JWT. Dans cette optique et pour être conforme au protocole de sécurité, la demande de jeton d’accès doit se faire côté serveur au niveau de notre application Web pour sécuriser les paramètres d’appel vers Azure.

Chaque composant de notre infrastructure sera contenu dans un conteneur Docker, et un reverse-proxy supporté par NGINX aura pour fonction d’orienter les requêtes dans notre sous-réseau Docker. Cela aura pour tâche d’éviter la problématique des appels cross-domaines (ou CORS) qui apparaîtrons forcément lors de la communication avec la plateforme Cloud de Microsoft.

La structure de cette architecture devrait permettre d’utiliser les applications enregistrées dans Azure lors de l’article sur l’ajout des rôles applicatifs sans en changer la configuration (enfin presque).

Concernant Docker, il est utilisé pour trois fonctions :

  • Construire les images et les conteneurs de nos composants.
  • Isoler nos composants via un sous réseau accessible uniquement par les conteneurs référencés.
  • La construction des binaires de nos composants via des images préenregistrées pour éviter d’avoir à installer les outils nécessaires à leur génération.

Ce dernier point est d’ailleurs très important pour une mise en production sur une chaîne de déploiement continue tel que l’on peut en rencontrer en entreprise. Ces actions sont généralement effectuées par un orchestrateur qui se charge de distribuer les binaires sur les serveurs de destination et doit donc s’abstraire de la technique utilisée par les composants pour leur construction et leur utilisation.

Notre architecture devrait donc ressembler au schéma ci-dessous :

Chaque composant englobé dans le sous-réseau my_network est un conteneur Docker, que ce soit le reverse-proxy NGINX, le Front-end en Vue.js ou les deux API Java. Dans le cadre de l’identification des utilisateurs, les appels vers Azure AD ne se feront que depuis la Web App côté serveur pour sécuriser les données clients (ID client et Secret client).

Développement de la Web App

Nous ne sommes pas là pour dérouler l’ensemble du code. Pour cela vous pouvez regarder le contenu du projet depuis le dépôt GitHub: https://github.com/INGENIANCE/OAuth2-With-AzureAD et vous amusez à en exécuter le code en lançant la commande docker-compose up -d à la racine du projet.

Je ne vous l’apprend sans doute pas, mais vous aurez besoin d’une instance Docker installée sur votre poste pour exécuter la commande. Docker est disponible sur toutes les plateformes. N’hésitez pas à aller consulter la documentation officielle.

Par contre il est intéressant de souligner les points clés de l’API qui ont orienté sont développement. Notre application Web va avoir plusieurs fonctions :

  • Demander les autorisations d’accès auprès d’Azure Active Directory pour authentifier l’utilisateur.
  • Distribuer les informations requises par l’utilisateur à la SPA.
  • Appeler la Web API à l’aide du token JWT pour obtenir des services supplémentaires.

Nous partons du principe que vous utilisez Maven pour gérer vos projets Java.

Microsoft propose un SDK Java pour la gestion des appels à Azure Active Directory. Nous l’avions déjà évoqué lors de la réalisation de la Web API qui sera également utilisée dans notre architecture. Cependant nous ne sommes pas en présence d’une ressource serveur mais d’une application Web, avec sa gestion des authentifications. Les dépendances à utiliser sont donc légèrement différentes :

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<!-- Azure AD starter dependency. -->
<dependency>
	<groupId>com.azure.spring</groupId>
	<artifactId>azure-spring-boot-starter-active-directory</artifactId>
</dependency>

Gestion des autorisations

La Web App doit pouvoir réorienter l’utilisateur vers les endpoints d’Azure en cas de demande d’accès. Pour cela nous nous appuyons sur Spring Security et la surcharge proposée par la librairie Azure (com.azure.spring.aad.webapp.AADWebSecurityConfigurerAdapter) :

protected void configure(HttpSecurity http) throws Exception {
    ((HttpSecurity)((HttpSecurity)((AuthorizedUrl)http.authorizeRequests().anyRequest()).authenticated().and()).oauth2Login().tokenEndpoint().accessTokenResponseClient(this.accessTokenResponseClient()).and().userInfoEndpoint().oidcUserService(this.oidcUserService).and().and()).logout().logoutSuccessHandler(this.oidcLogoutSuccessHandler()).and();
}

Celle-ci contient l’ensemble des endpoints permettant l’accès à la plateforme ainsi que les traitements nécessaires à la redirection. Bien entendu, quelques ajustements vont être nécessaires pour faire fonctionner cette configuration de sécurité avec notre architecture. Tout d’abord elle va devoir prendre en compte le traitement des appels cross-domaine. Elle va également devoir autoriser certains chemins pour la gestion des authentifications vers Azure depuis notre SPA. Enfin, et c’est ce dernier point le plus important, nous allons devoir mettre en place une gestion particulière des erreurs provoquées par les appels XHR sur les routes sécurisées de notre API.

Notre fichier de configuration hérité de AADWebSecurityConfigurerAdapter devra alors être de cette forme :

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AADOAuth2LoginSecurityConfig extends AADWebSecurityConfigurerAdapter {

    @Bean
    public CustomAuthenticationEntryPoint authenticationEntryPoint() {
        return new CustomAuthenticationEntryPoint("/oauth2/authorization/azure");
    }

    /**
     * Add configuration logic as needed.
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // Uses CorsConfigurationSource bean defined below.
        http.cors();

        // Specific right access.
        http.authorizeRequests()
                .antMatchers("/login**").permitAll()
                .antMatchers("/logout").permitAll()
                .antMatchers("/oauth2/authorization**").permitAll();

        http.exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint());

        http.csrf()
                .disable();

        http.headers()
                .frameOptions().disable();

        super.configure(http);
    }

    /**
     * Apply CORS configuration before Spring Security.
     * By default, "http.cors" take a bean called corsConfigurationSource.
     *
     * @return a CORS configuration source.
     * @implNote https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#cors
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        return source;
    }
}
  • http.cors() va appeler corsConfigurationSource() pour initialiser les autorisations cross-domaine. Par commodité addAllowedOrigin est positionné sur "*", mais en production il est recommandé de ne mettre que les domaines autorisées. Ici nous aurions pu mettre "http://localhost".
  • http.authorizeRequests() définit les chemins publics qui nous sont utiles depuis la SPA pour authentifier les utilisateurs sans qu’ils soient bloqués par Spring Security.
  • http.exceptionHandling() va nous permettre de gérer les erreurs encourues lors de certaines requêtes.
  • super.configure(http) appelle la configuration de sécurité par défaut déclarée dans com.azure.spring.aad.webapp.AADWebSecurityConfigurerAdapter.

Comme évoqué un peu plus haut, http.exceptionHandling() permet de gérer les erreurs d’authentifications qui peuvent subvenir lors d’un appel Ajax depuis notre client en Vue.js. En effet, notre API n’est pas en mesure de détecter si la requête est un appel direct depuis un lien Web ou un appel asynchrone depuis du code Javascript. Or, un appel de ce type enclenche irrémédiablement une exception de type cross-origin.

Il existe cependant une convention qui demande de placer en entête d’une requête l’attribut X-Requested-With avec comme valeur XMLHttpRequest pour déclarer l’appel de type Ajax. A la réception de cette entête Spring Security retourne un statut HTTP de type 302 Redirect vers la page d’authentification Azure. Mais c’est ensuite au niveau d’Azure que l’erreur cross-origin intervient.

Le protocole OAuth 2.0 ne supporte pas par design les appels Ajax à cause du trop grand nombre de redirection que cela peut engendrer. La seule solution est qu’en cas d’accès non autorisé à un chemin de l’API via un appel comportant l’entête X-Requested-With, l’API doit répondre avec un statut HTTP de type 401 Unauthorized. Ce statut pourra alors être intercepté par le client web pour effectuer un appel vers la route de login. C’est là qu’intervient notre CustomAuthenticationEntryPoint.

/**
 * The Entry Point will not redirect to any sort of Login when headers
 * contains XMLHttpRequest (for Ajax request) - it will return the 401
 */
public class CustomAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
    private static final String XML_HTTP_REQUEST = "XMLHttpRequest";
    private static final String X_REQUESTED_WITH = "X-Requested-With";

    public CustomAuthenticationEntryPoint(String loginFormUrl) {
        super(loginFormUrl);
    }

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
            throws IOException, ServletException {
        if (XML_HTTP_REQUEST.equals(request.getHeader(X_REQUESTED_WITH))) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        } else {
            super.commence(request, response, exception);
        }
    }
}

Lors d’une erreur d’authentification, si l’appel contient l’entête X-Requested-With avec comme valeur XMLHttpRequest l’API se charge de retourner un statut HTTP 401 Unauthorized, évitant ainsi la redirection forcée de Spring Security vers la page de login Azure.

Flux On-Behalf-Of

Maintenant que la Web App est sécurisée, concentrons nous sur l’appel vers la Web API depuis la Web App. La dépendance Spring d’Azure va faire tout le travail pour nous, il suffit juste de renseigner dans le fichier d’environnement application.yml certaines informations relatives au compte Azure.

Pour plus d’information sur le traitement du flux On-Behalf-Of, n’hésitez pas à consulter la documentation Microsoft ainsi que les exemples d’utilisations.

azure:
  activedirectory:
    client-id: <Replace-with-your-WebApp-Client-ID>
    client-secret: <Replace-with-your-WebApi-URI-application-ID>
    tenant-id: <Replace-with-your-tenant-ID>
    authorization-clients:
      graph:
        scopes:
          - User.Read
          - Directory.Read.All
      myregistrationid:
        scopes:
          - <Replace-with-your-WebApi-URI-application-ID>/User.Read
    post-logout-redirect-uri: http://localhost

Pour chaque client définit dans le dépôt (ici graph et myregistrationid), la Web App se chargera de contacter Azure AD pour demander un token d’accès avec le token de l’utilisateur ainsi que l’ID client et le secret.

L’exemple de notre code prends en charge l’appel à deux API en simultanée: l’API Microsoft Graph et notre Web API.

/**
  * Get user data from Microsoft Graph API.
  * Required to be authentication through OAuth Graph client registration.
  *
  * @param authorizedClient OAuth authorized client from Graph registration
  * @return User data
  * @throws IOException
  */
@GetMapping("/user-info")
public ResponseEntity<HashMap<String, Object>> getUserInfoFromGraphAPI(HttpServletRequest request, @RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient authorizedClient) throws IOException {
    // Create the auth provider
    SimpleAuthProvider authProvider = new SimpleAuthProvider(authorizedClient.getAccessToken().getTokenValue());

    IGraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();

    // Get user data from MS Graph API
    User user = graphClient.me()
            .buildRequest()
            .get();

    // Get user picture from MS Graph API
    InputStream photo = graphClient.me().photo().content()
            .buildRequest()
            .get();

    // Return a byte array of the picture
    byte[] imgStream = photo.readAllBytes();

    // Map user data for the entity response
    HashMap<String, Object> response = new HashMap<>();
    response.put("displayName", user.displayName);
    response.put("jobTitle", user.jobTitle);
    response.put("mail", user.mail);
    response.put("photo", imgStream);

    // Get data from REST API
    Authentication principal = SecurityContextHolder.getContext().getAuthentication();
    final OAuth2AuthorizedClient ingAuthorizedClient = this.oAuth2AuthorizedClientRepository.loadAuthorizedClient("myregistrationid", principal, request);
    ResponseEntity<String> restAPIResponse = this.getRestAPIData(ingAuthorizedClient);
    response.put("apiData", restAPIResponse.getBody());

    return new ResponseEntity<>(response, HttpStatus.OK);
}

Les appels à Azure AD sont gérés par l’annotation @RegisteredOAuth2AuthorizedClient pour chacune des routes menant aux API.

Microsoft met à disposition un site permettant de simuler les appels à l’API Graph. Ce dernier génère également le code source dans différents langages pour chacune des requêtes exécutées.

Client Web en Vue.js

Le scénario d’utilisation est simple. Lors de l’ouverture de l’URL http://localhost qui appelle notre SPA exposée sur le port 80 de notre sous-réseau docker, la SPA va tenter de collecter des informations auprès de notre Web App. Cependant, à la première connexion, aucun utilisateur n’est identifié ce qui va irrémédiablement se terminer par un statut HTTP 401 Unauthorized. Deux choses à prévoir ici :

  • Notre SPA va devoir émettre des appels Ajax avec un paramètre d’entête du type X-Requested-With ou sinon c’est l’exception cross-origin assurée.
  • Notre SPA doit pouvoir intercepter le statut HTTP et rediriger l’utilisateur sur une route d’identification, en l’occurrence une fournit par notre Web App.

L’un des composants les plus apprécié pour manipuler des appels REST est axios. Il va nous servir à consommer les routes exposées par notre Web App. Dans un premier temps vous devez l’installer dans votre projet. Pour cela lancez la commande suivante à la racine du client web :

npm i axios --save

Le composant est à instancier de cette manière dans le fichier services/api.js :

import axios from 'axios';

export default axios.create({
    baseURL: '/web-app',
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    }
 });

baseURL correspond au chemin exposé par NGINX pour venir attaquer notre Web App dans le sous-réseau Docker. Mais nous y reviendrons un peu plus tard.

Depuis le fichier main.js de notre application vue.js, nous allons maintenant y définir un intercepteur afin de manipuler toute réponse reçue après un appel XHR.

import api from './services/api';

[...]

Vue.prototype.$http = api;
api.defaults.timeout = 10000;

api.interceptors.response.use(
  response => {
    if ([200, 201].indexOf(response.status) !== -1) {
      return Promise.resolve(response);
    } else {
      return Promise.reject(response);
    }
  },
  error => {
    if ([401, 403].indexOf(error.response.status) !== -1) {
      // Go to login page if 401 Unauthorized or 403 Forbidden response returned from api
      window.location = '/login';
    }

    return Promise.reject(error.response);
  }
);

Comme vous pouvez le voir, en cas de réception d’un statut HTTP 401 ou 403, l’utilisateur est envoyé vers la page de login, qui est en réalité mappée par NGINX sur la route fournit par Spring Security de notre Web App pour se connecter à Azure.

Tout appel à la Web App depuis les fichiers .vue peut ensuite se faire de cette manière :

this.$http.get('/api/user-info')
    .then(response => {
      ...
    })

$http correspond à une variable globale définit dans main.js et contenant notre instance d’axios.

N’oubliez pas que le chemin absolu de notre appel corresponds en fait à : http://localhost/web-app/api/user-info

Si nous avons un login, nous ne devons pas oublier qu’il nous faut également un logout. Il suffit de définir une méthode dans les scripts vue.js qui redirigera l’utilisateur à la route par défaut configurée par Spring Security de notre Web App.

methods: {
  logout () {
    window.location = "/web-app/logout"
  }
}

Il ne nous reste qu’une action à faire, c’est d’ajouter l’entête X-Requested-With à nos appels REST. Nous aurions très bien pu le rajouter dans la définition des headers de notre instance d’axios, mais j’ai trouvé plus sympa d’utiliser notre reverse-proxy pour cela.

Reverse-proxy

NGINX est avant tout un serveur Web très performant, mais ce qui nous intéresse surtout ici ce sont ses fonctionnalités de proxy inverse. Il va nous permettre d’écouter les requêtes émises par nos différents composants pour les rediriger sur les endpoints qui nous intéresse de notre sous-réseau Docker. Notre reverse-proxy est également distribué depuis un conteneur Docker.

server {
    listen 80;

    location /login/oauth2 {
        rewrite ^(/.*)$ $1 break;
        proxy_pass http://web-app:9090;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Prefix /web-app;
        proxy_set_header Host $host;
        proxy_read_timeout 900s;
    }

    location /login {
        proxy_pass http://web-app:9090/oauth2/authorization/azure;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Prefix /web-app;
        proxy_set_header X-Requested-With "";
        proxy_set_header Host $host;
        proxy_read_timeout 900s;
    }

    location /web-app/ {
        rewrite /web-app/(.*) /$1 break;
        proxy_pass http://web-app:9090;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Prefix /web-app;
        proxy_set_header X-Requested-With "XMLHttpRequest";
        proxy_set_header Host $host;
        proxy_read_timeout 900s;
    }

    location / {
        rewrite ^(/.*)$ $1 break;
        proxy_pass http://vue-client;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
    }
}

Plusieurs points sont intéressants dans ce fichier de configuration :

  • N’importe quel appel non référencé est redirigé sur l’URL http://vue-client qui représente dans notre sous-réseau Docker notre client Web ou SPA en vue.js. Cela permet de protéger les API qui ne sont pas ouvertes au réseau public.
  • Les appels qui ont comme origine http://localhost/web-app seront retournées vers la Web App représentée dans le sous-réseau Docker par l’URL http://web-app:9090. L’entête X-Requested-With avec comme valeur XMLHttpRequest permet de définir ces requêtes comme des appels XHR.
  • Les autres points de configuration concernent l’authentification OAuth 2.0 via Azure AD et prennent en charge la redirection des endpoints liés au login.

Nginx est un outil très complet et nous ne voyons ici qu’une infime partie de ses fonctionnalités. Je vous invite à regarder la documentation pour vous familiariser avec.

Dockerisation et déploiement

Ne reste plus qu’à conteneuriser l’ensemble des composants et à lancer le déploiement de notre architecture, c’est à dire la Web App, la Web API, le client Web et le reverse-proxy.

La création d’un conteneur Docker s’effectue en 3 étapes :

  • La création de l’image source
  • La création du conteneur
  • L’association éventuelle du conteneur à un sous-réseau

Les fichiers Dockerfile fournis à la racine de chaque composant sont établis sur le principe du multistage pour alléger au maximum le poids des images utilisées pour les conteneurs. Prenons l’exemple du Dockerfile utilisé pour générer l’image de notre Web App.

## Stage 0: Build env.
FROM maven:3.6.0-jdk-11-slim AS BUILD
LABEL maintainer="Cyrille P."
ENV MAVEN_HOME .
# Copy the project files
COPY ./pom.xml ./pom.xml
# Build all dependencies for offline use
RUN mvn dependency:go-offline -B
# Copy your other files
COPY ./src ./src
# Build for release
RUN mvn clean package spring-boot:repackage -B -DskipTests

## Stage 1: Run env.
FROM openjdk:11.0.1-jre-slim
USER root
# copy over the built artifact from the maven image
COPY --from=BUILD /src/main/resources/application.yml ./
COPY --from=BUILD /target/*.jar ./web-app.jar
EXPOSE 9090
ENTRYPOINT ["java","-jar","/web-app.jar"]

On remarque deux étapes :

  • L’étape 0 qui permet de créer une image temporaire résultant de la compilation de notre application.
  • L’étape 1 qui génère l’image finale de notre Web App.

L’avantage d’utiliser ce procédé est de limiter le nombre de dépendances incluses dans l’image finale dont beaucoup auront servis uniquement à la compilation.

Pour compiler votre image il vous suffit de lancer la commande suivante à la racine du projet du composant :

docker build --tag web-app .

web-app correspond au nom de l’image que vous souhaitez lui affecter lors de sa compilation. Vient ensuite l’étape de création du conteneur :

docker run -d --name web-app -p 9090:9090 web-app

Enfin, on affecte notre conteneur à notre sous-réseau my_network.

docker network create my_network
docker network connect my_network web-app

Il serait rébarbatif de devoir effectuer toutes ces commandes à chaque fois que l’on souhaite lancer notre infrastructure. Heureusement Docker a également l’avantage de proposer des outils pour orchestrer la mise en route des services en s’appuyant sur les Dockerfile de chaque composant. Pour cela il faut passer par l’outil docker-compose. Celui-ci s’appui sur un fichier docker-compose.yml que vous trouverez à la racine du dépôt GitHub de cet article.

version: '3.8'

services:
  web-app:
    build: AAD-Spring-Boot-OAuth2-Client/
    image: web-app
    ports:
      - "9090:9090"
    networks:
      - my_network

  web-api:
    build: AAD-Spring-Boot-Resource-Server/
    image: web-api
    ports:
      - "9091:9091"
    networks:
      - my_network

  vue-client:
    build: AAD-Web-Client-Nginx/
    image: vue-client
    networks:
      - my_network

  reverse-proxy:
    build: AAD-Reverse-Proxy/
    image: aad-reverse-proxy
    depends_on:
      - web-app
      - web-api
      - vue-client
    ports:
      - "80:80"
    networks:
      - my_network

networks:
  my_network:

Puis, lancez la commande suivante :

docker-compose up -d

docker-compose se chargera de lancer les compilations de chaque image si elles ne sont pas déjà présentes (vous pouvez également forcer la compilation en rajoutant le paramètre --build), de monter les conteneurs et d’initialiser le sous-réseau. N’hésitez pas à aller consulter la documentation officielle pour vérifier les commandes disponibles.

Il ne vous reste plus qu’à ouvrir votre navigateur et lancer l’URL http://localhost pour tester votre architecture nouvellement déployée.

Azure Active Directory

En début d’article je vous avais indiqué qu’il n’était pas nécessaire de modifier la configuration mise en place dans l’article concernant la configuration d’Azure. Ce n’est pas tout à fait vrai, il faudra ajouter pour la Web App dans l’onglet Authentification deux URI de redirection correspondant à celles de notre architecture, en l’occurrence :

  • http://localhost/login/oauth2/code/azure
  • http://localhost/login/oauth2/code/myregistrationid

Conclusion

Dans cet article nous avons vu :

  • Comment déployer facilement une architecture orientée Web et sécurisée à l’aide d’Azure Active Directory.
  • Configurer nos API Java pour prendre en charge les appels XHR et éviter les erreurs cross-domaine.
  • Réaliser un appel sécurisé inter API via le flux obo.
  • Paramétrer le client Web pour intercepter les réponses de nos API Java.
  • Utiliser Nginx pour réorienter les requêtes Web vers notre sous-réseau Docker.
  • Utiliser Docker pour automatiser le déploiement de l’architecture.

Références


0 commentaire

Laisser un commentaire

Avatar placeholder

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Développer et déployer une application Web (Vue.js + Java) sous Dock…

par Cyrille P. temps de lecture : 16 min
0