image
image
image
image
image
image

Aws jwt verify java

Autorisation JWT pour les API sans serveur sur AWS Lambda Les

fonctions sans serveur nous permettent d’écrire de petits points de terminaison d’API contenus pour nos applications. Dans cet article, nous allons apprendre à sécuriser notre point de terminaison d’API serverless avec une autorisation basée sur un jeton web json (JWT).

Tl; DR

Si vous voulez passer directement au code final, vous pouvez trouver le dépôt ici : https://github.com/tmaximini/serverless-jwt-authorizer

Lisez la suite pour une explication complète de ce qui se passe ici.

Étapes pour l’autorisation JWT

Voici à peu près les étapes que nous devons suivre pour sécuriser notre point de terminaison API :

  1. S’inscrire avec le nom d’utilisateur, le mot de passe, le hachage du mot de passe est stocké dans DB
  2. Login avec le nom d’utilisateur / Mot de passe
  3. Si le hachage du mot de passe correspond au passwordHash stocké pour l’utilisateur, générer un jeton JWT à partir de l’identifiant de l’utilisateur et de son
  4. Signez chaque demande avec ce jeton dans l’en-tête d’autorisation HTTP
  5. Fonction d’autorisation d’installation qui vérifie ce jeton (lors de la demande d’une route d’API sécurisée). La réponse de l’autorisateur peut être mise en cache pour un certain montant afin d’augmenter le débit de l’API.
  6. Authorizer génère un policyDocument qui autorise ou refuse l’accès au service

Planifier notre application

Nous allons avoir besoin d’une méthode et d’une méthode. Nous aurons également un point de terminaison protégé, qui retourne l’objet utilisateur actuel si l’utilisateur est correctement authentifié.

Il s’agit d’une fonction lambda supplémentaire, qui est définie comme un mécanisme d’autorisation API gatewa et qui sera appelée en arrière-plan chaque fois que nous essayons d’accéder au point de terminaison protégé.

Nous avons donc un total de 4 fonctions lambda :

Configurer notre application avec le cadre sans serveur

So Initalisons l’application. Vous trouverez le code final de l’exemple dans github. Nous pouvons exécuter pour démarrer un projet basé sur node.js. Assurez-vous d’avoir déjà configuré l’interface de ligne de commande AWS ou au moins d’avoir configuré un dossier, car c’est là que le serverless extraira vos informations.

Maintenant, nous allons mettre à jour le fichier généré. Nous allons y ajouter toutes nos fonctions à partir de l’étape 1 (register, login, me, verifyToken). Cela devrait ressembler à celui-ci :

Structure de dossiers pour les API sans serveur

La façon dont je le fais est d’avoir un seul fichier pour chaque Lambda. Bien sûr, vous pouvez exporter plusieurs fonctions à partir du même fichier, mais comme ça, je garde la raison et cela facilite le nommage (chaque fichier exporte une fonction de gestionnaire que j’utilise comme gestionnaire dans serverless.yml).

Toutes les fonctions d’assistance et les fonctions non lambda vont dans le dossier.

La couche de base de données

Maintenant, avant que nous peut autoriser un utilisateur, nous allons avoir besoin d’un moyen de créer un utilisateur et de l’enregistrer dans la base de données. Nous allons choisir DynamoDB comme base de données ici, car étant elle-même une base de données sans serveur, c’est un excellent choix pour le sans serveur. Bien sûr, vous pouvez également utiliser n’importe quelle autre base de données.

DynamoDB

Amazon DynamoDB est une base de données clé-valeur et de documents qui offre des performances de l’ordre de l’ordre de la milliseconde à n’importe quelle échelle

.

Dans notre cas, nous avons juste besoin d’une table users. J’ai choisi DynamoDB ici parce qu’il s’agit d’un choix célèbre et fiable pour les API sans serveur, notamment en raison de l’idée « payez au fur et à mesure, évoluez au fur et à mesure de votre croissance ».

Si vous voulez connaître les tenants et aboutissants de DynamoDB, je vous recommande de vous rendre sur https://www.dynamodbguide.com/ par @alexbdebrie.

Le modèle DB

lors de la conception d’un service ou d’un api J’aime bien commencer par le modèle de données. C’est particulièrement important avec DynamoDB où nous sommes limités par la conception à table unique. C’est pourquoi les experts DynamoDB vous conseillent de noter d’abord tous les modèles d’accès et les façons dont vous prévoyez d’interroger vos données. Sur cette base, vous allez modéliser votre table.

Dans notre cas, le schéma est assez simple pour l’instant, mais nous le gardons suffisamment générique pour pouvoir l’étendre plus tard. J’utilise ici le package dynamodb-toolbox pour définir mon modèle de données et simplifier l’écriture des requêtes.

Nous ne stockerons évidemment pas le mot de passe en texte clair dans notre base de données, nous utilisons donc bcrypt (la note de bas de page sur bcryptjs est le meilleur choix sur lambda) pour créer un puis supprimer le mot de passe original en texte brut de l’objet props avant de le diffuser dans notre utilisateur.

J’ai choisi l’adresse e-mail ici comme clé primaire et non l’id car c’est ce que j’utilise pour interroger des éléments uniques. Vous utilisez également l’ID utilisateur ou une combinaison de ces derniers.

Il est important de ne pas que DynamoDB ne puisse pas récupérer des éléments uniques par des propriétés non clés, par exemple dans l’exemple ci-dessus, je ne suis pas en mesure de dire . Je devrais d’abord les récupérer, puis filtrer à l’aide d’une FilterExpression.

L’avantage d’une base de données NoSQL telle que DynamoDB est que les colonnes et les champs sont dynamiques. Donc, si nous décidons d’envoyer plus de données à la méthode, elles seront toutes ajoutées à la base de données (nous devons cependant ajuster la base de données à partir de maintenant).

Définition des ressources dans serverless.yml

Lorsque nous avons choisi notre modèle de données et le nom de notre table, il est logique de revenir sur notre ressource DynamoDB et de la préparer, afin de ne pas avoir à effectuer de travail manuel à partir de la console AWS. Le framework serverless nous permet de définir des ressources et des autorisations directement à partir du fichier.

Nous aurons également besoin de quelques variables d’environnement secrètes. Un moyen simple de Les définir consiste simplement à créer un fichier secrets.json à la racine de votre projet (assurez-vous de l’ignorer !) et à les définir au format JSON.

Pour permettre à un utilisateur de s’inscrire à notre service, nous devons stocker ses données dans notre base de données. Avec notre modèle de données en place, nous pouvons désormais utiliser AWS DynamoDB DocumentClient avec notre boîte à outils dynamodb pour simplifier ce processus. Jetez un coup d’œil au code suivant : C’est

suffisant pour créer notre enregistrement d’utilisateur du côté de la base de données.

Ajoutons maintenant l’implémentation du point de terminaison lambda réel.

Lorsque nous sommes déclenchés par un message HTTP, nous voulons extraire les données de l’utilisateur du corps de la requête et les passer à la méthode à partir de notre lib/db.js.

Créons un fichier appelé qui ressemble à ceci :

Nous essayons de créer l’utilisateur, et si tout se passe bien, nous envoyons l’utilisateur avec un code d’état de réussite de 200, sinon nous envoyons une réponse d’erreur.

Ensuite, nous cherchons à implémenter la connexion.

Tout

d’abord, nous devons étendre notre fichier d’assistance lib/db.js avec une fonction qui récupère un utilisateur par e-mail, afin que nous puissions vérifier si l’utilisateur existe et si c’est le cas, comparer le passwordHash au hachage du mot de passe qui a été envoyé avec la demande.

Nous pouvons maintenant importer et utiliser cette fonction dans notre utilisateur lambda.

Détaillons les étapes dont nous avons besoin pour nous connecter à l’utilisateur :

  1. obtenir l’adresse e-mail et le mot de passe de la charge utile de la demande
  2. essayer d’obtenir l’enregistrement de l’utilisateur de la base de données pour l’e-mail
  3. s’il est trouvé, hacher le mot de passe et comparer avec le mot de passeHachage de l’enregistrement de l’utilisateur
  4. si le mot de passe est correct, créer un jeton de session jwt valide et le renvoyer au client

Voici l’implémentation du gestionnaire :

une fois l’inscription et la connexion en place, nous pouvons maintenant procéder à l’implémentation d’un point de terminaison d’API protégé.

Supposons

que nous ayons une ressource protégée dans notre API. Un profil utilisateur peut être un bon exemple. Nous voulons uniquement que les utilisateurs connectés puissent voir et mettre à jour les informations de leur profil. Implémentons un point de terminaison qui renvoie simplement l’enregistrement utilisateur de l’utilisateur actuellement connecté à partir de la base de données.

Voici les étapes que nous devons mettre en œuvre :

  1. valider le jeton jwt (effectué par notre fonction d’autorisation lamda )
  2. obtenir l’utilisateur associé à partir de l’utilisateur de retour de la base de données

Cela semble simple, non ? Jetons un coup d’œil :

la mise en œuvre de est assez courte et simple. Les autorisateurs AWS fonctionnent à l’aide de documents de politique .

le policyDocument doit contenir les informations suivantes :

  • Ressource (nom de la ressource ARN ou Amazon, identifiant unique d’une ressource AWS)
  • Effet (soit )
  • Action (un mot-clé qui décrit l’action souhaitée, dans notre cas

La fonction d’autorisation

Déployez et testez

Maintenant, exécutons et déployons notre service final sur AWS. Le résultat doit ressembler à ce qui suit :

Vous aurez 3 points de terminaison, tels que nous les avons définis, un pour /register, un pour /login et un pour /me.

Tout d’abord, enregistrons un utilisateur à l’aide de cURL :

Nous pouvons utiliser la même commande cURL pour la connexion, il suffit de changer /register en /login à la fin :

Cela devrait renvoyer un jeton :

C’est le jeton que nous allons utiliser pour les requêtes aux points de terminaison d’API protégés.

et Enfin, utilisons le jeton pour tester notre point de terminaison protégé. Nous pouvons passer l’en-tête personnalisé à curl en utilisant l’option :

Lorsque tout s’est bien passé, il devrait renvoyer notre enregistrement utilisateur :




Conclusion

Félicitations. Vous avez appris à concevoir et à déployer un microservice sur AWS Lambda avec l’autorisation JWT. Si vous êtes arrivé jusqu’ici, pensez à me suivre sur Twitter.