Le versionnement d'une API est une pratique essentielle pour maintenir et faire évoluer les services web sans perturber les utilisateurs existants. Il permet aux développeurs d'introduire des modifications, des améliorations, voire des changements incompatibles, tout en garantissant la compatibilité avec les versions précédentes. Dans cette section, nous allons explorer le processus de versionnement d'une API avec FastAPI, en prenant l'exemple d'un gestionnaire de tâches, et comment sécuriser les endpoints de l'API à l'aide du protocole OAuth2.
Lorsqu'une API évolue, il est crucial de fournir un moyen de différencier les différentes versions de l'API afin que les clients puissent choisir la version avec laquelle ils souhaitent interagir. Plusieurs approches de versionnement existent, mais dans cet exemple, nous utiliserons le versionnement par chemin d'URL, l'une des méthodes les plus courantes.
Implémentation du versionnement d'API
Prenons un exemple où nous voulons ajouter un nouveau champ priority à nos tâches. Par défaut, la valeur de ce champ sera "lower", mais elle pourra être modifiée pour répondre à des besoins spécifiques. Pour cela, nous allons suivre les étapes suivantes :
-
Création de la classe
TaskV2dans le modulemodels.py:
-
Création de la fonction
read_all_tasks_v2dans le moduleoperations.pypour lire toutes les tâches, en incluant le champpriority:
-
Dans le module
main.py, nous définissons le nouvel endpoint pour la version 2 de notre API :
Nous avons ainsi créé une nouvelle version de l'endpoint, qui inclut le champ priority. Cette approche permet de faire évoluer l'API en introduisant de nouvelles versions sans perturber les utilisateurs de la version précédente.
Tests et validation
Pour tester la nouvelle version de l'API, il est nécessaire de modifier le fichier tasks.csv afin d'y ajouter manuellement la nouvelle colonne priority. Par exemple :
Lancez ensuite le serveur avec la commande suivante :
En accédant à la documentation interactive à l'adresse http://localhost:8000/docs, vous pourrez tester le nouvel endpoint GET /v2/tasks, qui permet de lister toutes les tâches avec le nouveau champ priority. Assurez-vous également que l'endpoint GET /tasks (version 1) fonctionne toujours correctement.
Autres stratégies de versionnement
Le versionnement par URL que nous avons utilisé est la méthode la plus courante, mais il existe d'autres stratégies de versionnement, notamment :
-
Versionnement par paramètre de requête : l'information de version est passée en paramètre dans l'URL, comme dans l'exemple suivant :
https://api.example.com/resource?version=1. Cette méthode permet de garder l'URL de base uniforme à travers toutes les versions. -
Versionnement par en-tête : la version est spécifiée dans un en-tête personnalisé de la requête HTTP, tel que :
GET /resource HTTP/1.1
Host: api.example.com
X-API-Version: 1 -
Versionnement basé sur le consommateur : cette stratégie permet aux utilisateurs de choisir la version qu'ils souhaitent utiliser, et cette version est enregistrée lors de leur première interaction. À moins qu'ils ne la modifient, cette version sera utilisée lors de toutes leurs interactions futures.
Il peut également être pertinent d'utiliser un versionnement sémantique, où les numéros de version suivent un format du type MAJOR.MINOR.PATCH. Les changements majeurs (MAJOR) indiquent des modifications incompatibles, tandis que les changements mineurs (MINOR) et les correctifs (PATCH) sont rétrocompatibles.
Sécurisation de l'API avec OAuth2
Une fois que l'API est versionnée, il est important de la sécuriser pour éviter les accès non autorisés. OAuth2 est un cadre d'autorisation couramment utilisé qui permet d'assurer que seules les applications autorisées peuvent accéder aux ressources protégées. Dans cette section, nous allons montrer comment sécuriser les endpoints de notre API à l'aide d'OAuth2.
-
Création d'une base de données fictive d'utilisateurs : dans un premier temps, créons un dictionnaire contenant des utilisateurs et leurs mots de passe hachés.
-
Mécanisme de hachage : les mots de passe ne doivent pas être stockés en clair. Pour l'exemple, nous utilisons une fonction de hachage simplifiée, mais dans un environnement de production, un véritable mécanisme de hachage tel que bcrypt devrait être utilisé.
-
Gestion des utilisateurs : nous définissons une classe pour représenter un utilisateur et une fonction pour récupérer un utilisateur à partir de la base de données.
-
Création de fonctions pour générer et résoudre des tokens : enfin, nous définissons des fonctions pour générer et résoudre des tokens d'authentification.
-
Sécurisation des endpoints avec OAuth2 : nous utilisons maintenant le mécanisme d'OAuth2 pour protéger nos endpoints.
Ainsi, en utilisant OAuth2, nous avons sécurisé l'accès aux endpoints de l'API, permettant aux utilisateurs autorisés d'accéder uniquement aux données qu'ils sont censés voir.
Comment implémenter l'authentification sécurisée avec OAuth2 et JWT dans une application SaaS
L'authentification et l'autorisation sont des aspects cruciaux de toute application, en particulier dans un environnement SaaS où la sécurité des données des utilisateurs doit être primordiale. Utiliser OAuth2 avec des tokens JWT (JSON Web Tokens) est une solution moderne et robuste pour garantir que seules les personnes autorisées accèdent à des ressources protégées. Voici comment implémenter cette méthode dans votre application.
Lorsque vous créez un utilisateur dans un système, il est essentiel de vérifier si le nom d'utilisateur ou l'adresse e-mail existe déjà. Dans le cas où l’un de ces éléments est déjà présent dans la base de données, une réponse 409 est renvoyée pour indiquer qu'il y a un conflit et que la création de l'utilisateur est interdite. Afin de tester ce mécanisme, il suffit de démarrer le serveur à la racine du projet en exécutant la commande suivante :
Ensuite, vous pouvez vous rendre à l'adresse localhost:8000/docs pour vérifier les endpoints nouvellement créés dans la documentation Swagger et effectuer des tests. Un exemple de test consiste à vérifier la fonction add_user et l'endpoint /register/user. Voici un exemple de test à ajouter pour ces fonctionnalités :
Maintenant, voyons comment sécuriser cette application en utilisant OAuth2 et JWT.
Mise en place de l'authentification avec OAuth2 et JWT
-
Préparation de l'environnement
Avant de commencer, assurez-vous d’avoir installé les dépendances nécessaires à l'implémentation de l'authentification avec JWT. Si vous n'avez pas encore installé les packages du fichierrequirements.txt, exécutez cette commande :
Ensuite, pour intégrer OAuth2 avec JWT, vous allez définir des fonctions d’authentification, de création et de décodage des tokens. Ces fonctions seront regroupées dans un module appelé security.py.
-
Définir la fonction d'authentification
La première étape consiste à créer une fonction permettant de valider les utilisateurs, que ce soit par leur nom d'utilisateur ou par leur adresse e-mail. Cette fonction va interroger la base de données pour vérifier si un utilisateur existe et si le mot de passe est correct :
-
Création et décodage du token d'accès
Ensuite, il faut créer un token d'accès et définir la clé secrète, l'algorithme utilisé pour générer le token et sa durée de validité. Voici comment cela se fait :
De même, pour décoder le token et en extraire les informations, on utilise la fonction suivante :
-
Création des endpoints d'authentification
Une fois que nous avons les fonctions nécessaires, il est temps de les intégrer dans l'API. Nous utilisons l'APIRouter de FastAPI pour définir les endpoints qui gèrent la création du token d'accès et la récupération des informations de l'utilisateur. Le code suivant définit un endpoint qui retourne un token lorsque les informations d'identification sont valides :
-
Protéger les endpoints avec OAuth2
Une fois le token généré, vous pouvez créer des endpoints protégés qui nécessitent l’envoi du token dans l'en-tête de la requête. Par exemple, un endpoint qui renvoie les informations de l'utilisateur connecté :
-
Intégration dans l'application principale
Enfin, vous devez inclure ce module dans le serveur FastAPI en important le routeur dans le fichier principalmain.py:
Conclusion
Une fois ces étapes terminées, votre application SaaS sera protégée par OAuth2 avec des tokens JWT. Ces tokens offrent une méthode sûre et fiable pour authentifier les utilisateurs, en remplaçant les systèmes traditionnels basés sur des sessions et des mots de passe. Les utilisateurs devront s'authentifier via l'endpoint /token et ensuite utiliser le token pour accéder aux ressources protégées.
L'utilisation de JWT garantit une meilleure gestion des sessions, en permettant aux utilisateurs de se reconnecter à l'aide du même token sans avoir à entrer à nouveau leurs informations de connexion. Ce mécanisme permet également une meilleure scalabilité et sécurité dans les applications modernes.
Comment intégrer FastAPI avec gRPC pour créer une passerelle REST-gRPC
L’intégration de FastAPI avec gRPC permet de construire une passerelle performante et simple d’utilisation entre des clients HTTP et des services gRPC. Ce processus repose sur l’utilisation de fichiers .proto pour définir la structure des messages échangés entre le client et le serveur gRPC, ainsi que sur la mise en place d’un serveur gRPC basique avant de l’étendre pour inclure une interface HTTP avec FastAPI.
La première étape pour cette intégration consiste à définir le service gRPC dans un fichier .proto en utilisant la version proto3. Ce fichier contiendra les définitions des messages ainsi que des services gRPC, qui pourront ensuite être utilisées pour générer le code Python nécessaire. Par exemple, un fichier grpcserver.proto pourrait être structuré de la manière suivante :
Ce fichier définit un service GrpcServer avec une méthode RPC nommée GetServerResponse. Cette méthode prend un message de type Message en entrée et renvoie une réponse de type MessageResponse. La structure de ces messages est ensuite générée automatiquement à l’aide de l’outil grpc_tools.protoc, qui produit deux fichiers Python : grpcserver_pb2.py et grpcserver_pb2_grpc.py. Le premier contient les classes pour définir les messages, tandis que le second inclut les classes pour le service et la méthode RPC.
Une fois cette étape terminée, un serveur gRPC basique peut être mis en place. Cela nécessite la définition d’une classe serveur héritée de GrpcServerServicer, ainsi qu’une méthode GetServerResponse pour traiter les messages reçus et renvoyer une réponse adéquate :
Ce serveur écoute les requêtes et renvoie une réponse structurée selon les spécifications définies dans le fichier .proto.
Ensuite, pour lancer le serveur sur le port 50051, le script Python suivant peut être utilisé :
Une fois ce serveur gRPC en place, il est possible de créer une passerelle REST en utilisant FastAPI. Pour cela, nous définirons un fichier main.py où nous utiliserons FastAPI pour interagir avec le serveur gRPC. Le principal avantage d’utiliser FastAPI réside dans la simplicité de la création d’un serveur HTTP tout en tirant parti de la puissance de gRPC en arrière-plan.
Tout d’abord, il faut définir un schéma de réponse avec Pydantic pour assurer la validation des données envoyées depuis FastAPI vers le client :
Ensuite, un canal gRPC sécurisé sera établi pour communiquer avec le serveur gRPC en utilisant grpc.aio.insecure_channel. Une fois le canal établi, un point de terminaison HTTP peut être configuré pour interagir avec gRPC :
Ici, l’endpoint HTTP /grpc prend un paramètre message et envoie ce message au serveur gRPC via l’API. La réponse du serveur gRPC est ensuite renvoyée sous forme de réponse JSON au client HTTP.
Une fois le code en place, le serveur FastAPI peut être lancé avec la commande suivante :
Cela permettra d’accéder à la documentation interactive de l’API via l’interface Swagger à l’adresse http://localhost:8000/docs, où vous pourrez tester l’endpoint /grpc.
L’intégration de gRPC avec FastAPI permet ainsi de bénéficier des avantages des deux technologies : FastAPI pour sa simplicité d’utilisation et son excellent support pour les APIs REST, et gRPC pour sa rapidité et son efficacité pour les appels entre services.
Il est également essentiel de noter que, bien que nous ayons implémenté ici un RPC simple de type "unary", d’autres types de communication existent en gRPC, tels que les flux de messages (streaming) dans les deux sens, permettant une communication bidirectionnelle entre client et serveur. Pour étendre cette intégration, il est possible d’explorer l’implémentation de ces différents types d’appels, ce qui peut être utile pour des cas d’utilisation nécessitant des échanges continus de données.
Comment le modèle OSI garantit la fiabilité des communications et les différences entre TCP et IP
Comment maintenir la civilité en situation conflictuelle et l’importance de la preuve artistique dans la persuasion
Comment le gaz naturel influence-t-il le changement climatique et quelles stratégies pour sa gestion durable ?
Pourquoi les électeurs blancs non diplômés ont-ils voté massivement pour Trump en 2016 ?

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский