cognito-express mengautentikasi permintaan API pada aplikasi Node.js (baik berjalan di server atau dalam fungsi AWS Lambda) dengan memverifikasi tanda tangan JWT dari AccessToken
atau IDToken
yang dihasilkan oleh Amazon Cognito.
Modul ini memungkinkan Anda mengautentikasi permintaan API Node.js dengan memverifikasi tanda tangan JWT AccessToken
atau IDToken
- tanpa perlu memanggil Amazon Cognito untuk setiap pemanggilan API.
Modul ini dapat dengan mudah dan diam-diam diintegrasikan ke dalam aplikasi atau kerangka kerja apa pun yang mendukung middleware bergaya Connect, termasuk Express.
Modul ini pada dasarnya menggabungkan langkah 1-7 yang tercantum di dokumentasi resmi AWS tentang Menggunakan Token ID dan Token Akses di API Web Anda
iss
. Itu harus cocok dengan kumpulan pengguna Anda.tokenUse
. Ini harus sesuai dengan preferensi yang Anda tetapkan untuk jenis access
atau token id
Anda sekarang dapat mempercayai klaim di dalam token dan menggunakannya sesuai kebutuhan Anda.
Setelah autentikasi pengguna berhasil, Amazon Cognito mengeluarkan tiga token ke klien:
(Catatan: Mekanisme login tidak tercakup dalam modul ini dan Anda harus membuatnya secara terpisah)
Simpan token ini dalam aplikasi klien (sebaiknya sebagai cookie). Ketika API apa pun dipanggil dari klien, teruskan AccessToken
atau IDToken
ke server.
Terserah Anda bagaimana Anda meneruskan AccessToken
atau IDToken
. Berikut dua opsi:
//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 ( ) ;
}
} ) ;
Juga mendukung pola async/menunggu
( 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