cognito-express authentifiziert API-Anfragen für eine Node.js-Anwendung (die entweder auf einem Server oder in einer AWS Lambda-Funktion ausgeführt wird), indem die von Amazon Cognito generierte JWT-Signatur des AccessToken
oder IDToken
überprüft wird.
Mit diesem Modul können Sie Node.js-API-Anfragen authentifizieren, indem Sie die JWT-Signatur von AccessToken
oder IDToken
überprüfen – ohne Amazon Cognito für jeden API-Aufruf aufrufen zu müssen.
Das Modul kann einfach und unauffällig in jede Anwendung oder jedes Framework integriert werden, das Middleware im Connect-Stil unterstützt, einschließlich Express.
Dieses Modul bündelt im Wesentlichen die Schritte 1–7, die in der offiziellen AWS-Dokumentation zur Verwendung von ID-Tokens und Zugriffstokens in Ihren Web-APIs aufgeführt sind
iss
-Anspruch. Es sollte zu Ihrem Benutzerpool passen.tokenUse
Anspruch. Es sollte Ihren festgelegten Präferenzen für access
oder id
Token-Typen entsprechenSie können nun den Ansprüchen im Token vertrauen und es entsprechend Ihren Anforderungen verwenden.
Nach erfolgreicher Authentifizierung eines Benutzers stellt Amazon Cognito drei Token an den Client aus:
(Hinweis: Der Anmeldemechanismus wird von diesem Modul nicht abgedeckt und muss separat erstellt werden.)
Speichern Sie diese Token in der Client-App (vorzugsweise als Cookies). Wenn eine API vom Client aufgerufen wird, übergeben Sie das AccessToken
oder IDToken
an den Server.
Es liegt ganz bei Ihnen, wie Sie das AccessToken
oder IDToken
übergeben. Hier gibt es zwei Möglichkeiten:
//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 ( ) ;
}
} ) ;
Unterstützt auch das Async/Warten-Muster
( 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