2017-02-22 18 views
10

好的,我現在已經進入了這一天,取得了重大進展,但仍然完全陷入了基本面的困境。帶有Cognito的AWS Lambda API網關 - 如何使用IdentityId訪問和更新UserPool屬性?

我的應用程序使用Cognito用戶池來創建和管理用戶 - 它們在S3上看起來是由他們的IdentityId標識的。我的每個用戶都有自己的S3文件夾,AWS會自動爲他們提供一個與用戶的IdentityId相同的文件夾名稱。

我需要將IdentityId與其他Cognito用戶信息關聯,但無法解決問題。

我需要的關鍵是能夠識別給定IdentityId的用戶名和其他cognito用戶屬性 - 而且這非常困難。

因此,第一場戰鬥是如何在Cognito用戶通過AWS API網關發出請求時獲取IdentityId。最後我得到了解決方案,現在我有一個Cognito用戶,他向API網關發出請求,而我後面的Lambda函數現在擁有IdentityId。這個位有用。

但是我完全難以理解如何訪問存儲在用戶池中的Cognito用戶的信息。我找不到任何明確的信息,並且肯定沒有代碼,顯示如何使用IdentityId來獲取Cognito用戶的屬性,用戶名等。

看來,如果我使用「Cognito用戶池」來授權我方法在API網關,然後身體映射模板可用於將Cognito用戶信息,如子和用戶名和電子郵件地址放入上下文,但我沒有得到IdentityId。

但是,如果我使用AWS_IAM在API網關中授權我的方法,那麼身體映射模板會做相反的事情 - 它給我IdentityId,但不是Cognit用戶字段,例如子和用戶名和電子郵件。

這讓我很瘋狂 - 我如何才能將IdentityId和所有Cognito用戶字段和屬性合併到一個數據結構中?事實上,我似乎只能得到一個或另一個是沒有意義的。

回答

11

事實證明,要使用AWS Lambda/Cognito/API網關同時獲取IdentityId和用戶詳細信息,您需要具有使用AWS_IAM(NOT COGNITO_USER_POOLS)進行身份驗證的Lambda函數,則必須發送請求AWS API網關,但它必須是一個已簽名的請求,那麼您必須修改集成請求體映射模板,以便在事件中爲您提供IdentityId(也許上下文無法記住)。現在你有了IdentityId。唷。現在您必須將客戶端的Cognito ID令牌從前端提交到後端。驗證令牌非常重要 - 如果您不驗證它,則不能相信它未被篡改。要解碼和驗證令牌,您必須從用戶池中獲取密鑰,將它們放入您的腳本中,確保您擁有包含在AWS lambda zipfile中的jwt解碼庫和簽名驗證庫。現在,您的腳本必須驗證從前端提交的令牌,然後才能從令牌中獲取用戶詳細信息。瞧!現在你有兩個IdentityId加用戶的詳細信息,如他們的子,用戶名和電子郵件地址。太簡單。

以上是使用AWS Cognito/Lambda/API網關獲取與IdentityId關聯的用戶名所需的內容。這花了我幾天才能工作。

我可以向任何漫步於此的亞馬遜員工說說........很難獲得與IdentityId相關的用戶詳細信息。你需要解決這個問題。這讓我很生氣,因爲這太辛苦,而且被我燒得太多了。

解決辦法:

我這樣做是通過修改亞馬遜員工的自定義授權位置: https://s3.amazonaws.com/cup-resources/cup_custom_authorizer_lambda_function_blueprint.zip

如發現這裏描述: https://aws.amazon.com/blogs/mobile/integrating-amazon-cognito-user-pools-with-api-gateway/

use strict'; 
let util = require('util'); 

var jwt = require('jsonwebtoken'); 
var jwkToPem = require('jwk-to-pem'); 

var userPoolId = 'YOUR USERPOOL ID'; 
var region = 'YOUR REGION'; //e.g. us-east-1 
var iss = 'https://cognito-idp.' + region + '.amazonaws.com/' + userPoolId; 

//https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html 
// DOWNLOAD FROM https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json 
let userPoolKeys = {PUT YOUR DOWNLOADED USER POOL KEYS JSON HERE}; 
var pems = {}; 

let convertKeysToPems =() => { 
    var keys = userPoolKeys['keys']; 
    for(var i = 0; i < keys.length; i++) { 
     //Convert each key to PEM 
     var key_id = keys[i].kid; 
     var modulus = keys[i].n; 
     var exponent = keys[i].e; 
     var key_type = keys[i].kty; 
     var jwk = { kty: key_type, n: modulus, e: exponent}; 
     var pem = jwkToPem(jwk); 
     pems[key_id] = pem; 
    } 
} 

exports.handler = function(event, context) { 

    convertKeysToPems() 
    console.log(event); 
    let token = event['body-json'].cognitoUserToken; 
    console.log(event['body-json'].cognitoUserToken); 
    ValidateToken(pems, event, context, token); 

}; 


let ValidateToken = (pems, event, context, token) => { 

    //Fail if the token is not jwt 
    var decodedJwt = jwt.decode(token, {complete: true}); 
     console.log(decodedJwt) 
    if (!decodedJwt) { 
     console.log("Not a valid JWT token"); 
     context.fail("Unauthorized"); 
     return; 
    } 

    //Fail if token is not from your UserPool 
    if (decodedJwt.payload.iss != iss) { 
     console.log("invalid issuer"); 
     context.fail("Unauthorized"); 
     return; 
    } 

    //Reject the jwt if it's not an 'Access Token' 
    if (decodedJwt.payload.token_use != 'id') { 
     console.log("Not an id token"); 
     context.fail("Unauthorized"); 
     return; 
    } 

    //Get the kid from the token and retrieve corresponding PEM 
    var kid = decodedJwt.header.kid; 
    var pem = pems[kid]; 
    if (!pem) { 
     console.log(pems, 'pems'); 
     console.log(kid, 'kid'); 
     console.log('Invalid token'); 
     context.fail("Unauthorized"); 
     return; 
    } 

    //Verify the signature of the JWT token to ensure it's really coming from your User Pool 

    jwt.verify(token, pem, { issuer: iss }, function(err, payload) { 
     if(err) { 
     context.fail("Unauthorized"); 
     } else { 
     let x = decodedJwt.payload 
     x.identityId = context.identity.cognitoIdentityId 
     //let x = {'identityId': context['cognito-identity-id'], 'decodedJwt': decodedJwt} 
     console.log(x); 
     context.succeed(x); 
     } 
    }); 
} 
+0

我與你的難度同意,您是否有機會嘗試創建與提供的子級匹配的IAM S3策略? – Aaron

相關問題