cognito-express authentifie les requêtes API sur une application Node.js (exécutée sur un serveur ou dans une fonction AWS Lambda) en vérifiant la signature JWT d' AccessToken
ou IDToken
générée par Amazon Cognito.
Ce module vous permet d'authentifier les requêtes API Node.js en vérifiant la signature JWT d' AccessToken
ou IDToken
- sans avoir besoin d'appeler Amazon Cognito pour chaque appel d'API.
Le module peut être intégré facilement et discrètement à n'importe quelle application ou framework prenant en charge le middleware de style Connect, y compris Express.
Ce module regroupe essentiellement les étapes 1 à 7 répertoriées dans la documentation officielle d'AWS sur l'utilisation des jetons d'identification et des jetons d'accès dans vos API Web.
iss
. Il doit correspondre à votre pool d'utilisateurs.tokenUse
. Il doit correspondre à vos préférences définies pour les types de jetons access
ou id
Vous pouvez désormais faire confiance aux revendications contenues dans le jeton et l'utiliser selon vos besoins.
Après l'authentification réussie d'un utilisateur, Amazon Cognito émet trois jetons au client :
(Remarque : le mécanisme de connexion n'est pas couvert par ce module et vous devrez le construire séparément)
Enregistrez ces jetons dans l'application client (de préférence sous forme de cookies). Lorsqu'une API est appelée à partir du client, transmettez l' AccessToken
ou IDToken
au serveur.
C'est à vous de décider comment vous transmettez le AccessToken
ou IDToken
. Voici deux options :
//Initializing CognitoExpress constructor
const cognitoExpress = new CognitoExpress ( {
region : "us-east-1" ,
cognitoUserPoolId : "us-east-1_dXlFef73t" ,
tokenUse : "access" , //Possible Values: access | id
tokenExpiration : 3600000 //Up to default expiration of 1 hour (3600000 ms)
} ) ;
cognitoExpress . validate ( accessTokenFromClient , function ( err , response ) {
if ( err ) {
/*
//API is not authenticated, do something with the error.
//Perhaps redirect user back to the login page
//ERROR TYPES:
//If accessTokenFromClient is null or undefined
err = {
"name": "TokenNotFound",
"message": "access token not found"
}
//If tokenuse doesn't match accessTokenFromClient
{
"name": "InvalidTokenUse",
"message": "Not an id token"
}
//If token expired
err = {
"name": "TokenExpiredError",
"message": "jwt expired",
"expiredAt": "2017-07-05T16:41:59.000Z"
}
//If token's user pool doesn't match the one defined in constructor
{
"name": "InvalidUserPool",
"message": "access token is not from the defined user pool"
}
*/
} else {
//Else API has been authenticated. Proceed.
res . locals . user = response ; //Optional - if you want to capture user information
next ( ) ;
}
} ) ;
Prend également en charge le modèle asynchrone/attente
( async function main ( ) {
try {
const response = await cognitoExpress . validate ( accessTokenFromClient ) ;
console . log ( response ) ;
//User is authenticated, proceed with rest of your business logic.
} catch ( e ) {
console . error ( e ) ;
//User is not authenticated, do something with the error.
//Perhaps redirect user back to the login page
}
} ) ( ) ;
//app.js
"use strict" ;
const express = require ( "express" ) ,
CognitoExpress = require ( "cognito-express" ) ,
port = process . env . PORT || 8000 ;
const app = express ( ) ,
authenticatedRoute = express . Router ( ) ; //I prefer creating a separate Router for authenticated requests
app . use ( "/api" , authenticatedRoute ) ;
//Initializing CognitoExpress constructor
const cognitoExpress = new CognitoExpress ( {
region : "us-east-1" ,
cognitoUserPoolId : "us-east-1_dXlFef73t" ,
tokenUse : "access" , //Possible Values: access | id
tokenExpiration : 3600000 //Up to default expiration of 1 hour (3600000 ms)
} ) ;
//Our middleware that authenticates all APIs under our 'authenticatedRoute' Router
authenticatedRoute . use ( function ( req , res , next ) {
//I'm passing in the access token in header under key accessToken
let accessTokenFromClient = req . headers . accesstoken ;
//Fail if token not present in header.
if ( ! accessTokenFromClient ) return res . status ( 401 ) . send ( "Access Token missing from header" ) ;
cognitoExpress . validate ( accessTokenFromClient , function ( err , response ) {
//If API is not authenticated, Return 401 with error message.
if ( err ) return res . status ( 401 ) . send ( err ) ;
//Else API has been authenticated. Proceed.
res . locals . user = response ;
next ( ) ;
} ) ;
} ) ;
//Define your routes that need authentication check
authenticatedRoute . get ( "/myfirstapi" , function ( req , res , next ) {
res . send ( `Hi ${ res . locals . user . username } , your API call is authenticated!` ) ;
} ) ;
app . listen ( port , function ( ) {
console . log ( `Live on port: ${ port } !` ) ;
} ) ;
//client.js - angular example
"use strict" ;
//I stored my access token value returned from Cognito in a cookie called ClientAccessToken
app . controller ( "MyFirstAPI" , function ( $scope , $http , $cookies ) {
$http ( {
method : "GET" ,
url : "/api/myfirstapi" ,
headers : {
accesstoken : $cookies . get ( "ClientAccessToken" )
}
}
} ) . then (
function success ( response ) {
//Authenticated. Do something with the response.
} ,
function error ( err ) {
console . error ( err ) ;
}
) ;
} ) ;
Gary Arora
MIT