2017-02-22 14 views
10

OK Jestem teraz w tym dniu i poczyniłem znaczne postępy, ale wciąż jestem całkowicie zaskoczony podstawami.AWS Lambda API gateway z Cognito - jak używać IdentityId do uzyskiwania dostępu i aktualizacji atrybutów UserPool?

Moja aplikacja korzysta z puli użytkowników Cognito do tworzenia i zarządzania użytkownikami - są one identyfikowane na S3 przez ich IdentityId. Każdy z moich użytkowników ma swój własny folder S3, a AWS automatycznie nadaje im nazwę folderu, która jest równa IdentityId użytkownika.

Potrzebuję powiązać IdentityId z innymi informacjami o użytkowniku Cognito, ale nie mogę ustalić, w jaki sposób.

Kluczową rzeczą, której potrzebuję, jest możliwość zidentyfikowania nazwy użytkownika oraz innych atrybutów użytkownika Cognito dla danego IdentityId - i jest to szalenie trudne.

Pierwsza bitwa polegała na ustaleniu, jak uzyskać IdentityId, gdy użytkownik Cognito wykona żądanie przez bramkę AWS API. W końcu udało mi się, a teraz mam użytkownika Cognito, który wysyła żądanie do bramy API, a moja funkcja Lambda za tym ma teraz IdentityId. Ten kawałek działa.

Ale jestem całkowicie zaskoczony, jak uzyskać dostęp do informacji użytkownika Cognito przechowywanych w puli użytkowników. Nie mogę znaleźć żadnych jasnych informacji, a na pewno nie ma kodu, który pokazuje, jak używać IdentityId, aby uzyskać atrybuty, nazwę użytkownika Cognito itp.

Wygląda na to, że jeśli użyję "puli użytkowników Cognito", W interfejsie API Gateway można użyć szablonu mapowania ciała, aby umieścić dane Cognito User, takie jak sub i nazwa użytkownika oraz adres e-mail w kontekście, ALE NIE otrzymam IdentityId.

ALE jeśli używam AWS_IAM do autoryzacji mojej metody w bramce API, to szablon odwzorowania body działa odwrotnie - daje mi IdentityId, ale nie pola Cognito użytkownika, takie jak sub i nazwa użytkownika i e-mail.

To doprowadza mnie do szału - jak mogę połączyć pola IdentityId i wszystkich użytkowników Cognito w jedną strukturę danych? Fakt, że wydaje mi się, że mogę uzyskać tylko jedno, nie ma sensu.

Odpowiedz

11

Okazuje się, że aby uzyskać szczegóły IdentityId AND user w tym samym czasie przy użyciu bramy AWS Lambda/Cognito/API, musisz mieć funkcję Lambda, która jest uwierzytelniana za pomocą AWS_IAM (NOT COGNITO_USER_POOLS), musisz wysłać żądanie AWS API Gateway, ALE MUSI to być podpisane żądanie, musisz następnie zmodyfikować szablony odwzorowania treści żądania integracji tak, aby dostał IdentityId w zdarzeniu (być może kontekst nie może zapamiętać). Teraz masz IdentityId. Uff. Teraz musisz przesłać token Cognito ID klienta od przedniego do tylnego końca. Ważne jest, aby potwierdzić token - nie można ufać, że nie został zmieniony, jeśli go nie sprawdzasz. Aby zdekodować i zweryfikować token, musisz pobrać klucze z puli użytkowników, umieścić je w swoim skrypcie, upewnić się, że masz biblioteki dekodowania jwt oraz biblioteki sprawdzania poprawności podpisu zawarte w pliku zip lambda AWS. Teraz twój skrypt musi zweryfikować token przesłany z przodu, a następnie możesz uzyskać dane użytkownika z tokena. Voila! Teraz masz zarówno IdentityId, jak i dane użytkownika, takie jak sub, nazwa użytkownika i adres e-mail. Tak łatwo.

Powyższe informacje są potrzebne do uzyskania nazwy użytkownika powiązanej z IdentityId za pomocą bramy AWS Cognito/Lambda/API. Zajęło mi to kilka dni, aby pracować.

Czy mogę prosić o wypowiedzenie się do wszystkich pracowników Amazon, którzy wędrują przez to ........ Cóż, to DROGĘ zbyt trudno uzyskać szczegóły użytkownika związane z IdentityId. Musisz to naprawić. Rozzłościło mnie, że to było tak trudne i spalone tak wiele mojego czasu.

Rozwiązanie:

Zrobiłem to przez modyfikację pracowników Amazon zwyczaj Autoryzatora tutaj: https://s3.amazonaws.com/cup-resources/cup_custom_authorizer_lambda_function_blueprint.zip

jak ustalono i opisano tutaj: 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

zgadzam się z tobą na trudności , czy masz szansę spróbować utworzyć zasady IAM S3, które pasują do podanego sub? – Aaron

Powiązane problemy