sst / guide

Repo for guide.sst.dev
https://guide.sst.dev
MIT License
3.68k stars 446 forks source link

is there a way to retrieve cog users attributes etc using the cognitoIdentityId ? #213

Open walshe opened 6 years ago

walshe commented 6 years ago

or any thing else in the request..

I know I could pass in the email address from the frontend and use adminGetUser() but wondered if theres a way using the default stuff passed to the lambda event:

{
    "resource": "/appToken",
    "path": "/appToken",
    "httpMethod": "GET",
    "headers": {
        "Accept": "application/json",
        "accept-encoding": "gzip, deflate, br",
        "Accept-Language": "en-US,en;q=0.9,la;q=0.8",
        "CloudFront-Forwarded-Proto": "https",
        "CloudFront-Is-Desktop-Viewer": "true",
        "CloudFront-Is-Mobile-Viewer": "false",
        "CloudFront-Is-SmartTV-Viewer": "false",
        "CloudFront-Is-Tablet-Viewer": "false",
        "CloudFront-Viewer-Country": "US",
        "content-type": "application/json",
        "Host": "sh0sqilix3.execute-api.us-east-1.amazonaws.com",
        "origin": "http://localhost:3000",
        "Referer": "http://localhost:3000/login",
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
        "Via": "2.0 e81b6793c2b9879878a5c7ea08e930ec3d.cloudfront.net (CloudFront)",
        "X-Amz-Cf-Id": "ddddddd-6JeD94veDuL19m7xg==",
        "x-amz-date": "20180329T012958Z",
        "x-amz-security-token": "Ago.....adadasdfasdfasdfxxxx",
        "X-Amzn-Trace-Id": "Root=1-5abadasdd22c25e9c3dd709b",
        "X-Forwarded-For": "67.254asdasd.173, 204.246.168.112",
        "X-Forwarded-Port": "443",
        "X-Forwarded-Proto": "https"
    },
    "queryStringParameters": null,
    "pathParameters": null,
    "stageVariables": null,
    "requestContext": {
        "resourceId": "nzgdtl",
        "resourcePath": "/appToken",
        "httpMethod": "GET",
        "extendedRequestId": "Ee8vkHsToAMFa0A=",
        "requestTime": "29/Mar/2018:01:29:58 +0000",
        "path": "/dev/appToken",
        "accountId": "45345",
        "protocol": "HTTP/1.1",
        "stage": "dev",
        "requestTimeEpoch": 1522286998876,
        "requestId": "b1a59a78-32werwer9c7e-7750ea569b7f",
        "identity": {
            "cognitoIdentityPoolId": "us-east-1werwerae-4f12-9af7-dfa7af96fac2",
            "accountId": "werwer",
            "cognitoIdentityId": "us-east-234234880d-40c48951cf7b",
            "caller": "AROAJKAEMPFSM234234BLC2:CognitoIdentityCredentials",
            "sourceIp": "67.254.215.173",
            "accessKey": "343434",
            "cognitoAuthenticationType": "authenticated",
            "cognitoAuthenticationProvider": "cognito-idp.us-east-1.amazxxxxx3f1",
            "userArn": "arn:awdfsdfsdfIdentityCredentials",
            "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
            "user": "AROAJKAsdfsdfsMBKDBLC2:CognitoIdentityCredentials"
        },
        "apiId": "gjhgjgjg"
    },
    "body": null,
    "isBase64Encoded": false
}
jayair commented 6 years ago

@walshe I don't think there is a direct way. But there is a hack that we use internally. The cognitoAuthenticationProvider is basically the User Pool Id of the user that you can use to get the attributes. It is formatted a bit weirdly but you can parse it out and use it.

walshe commented 6 years ago

actually I just see its all contained in payload session.getIdToken() on the client, so I could pass it it from there

walshe commented 6 years ago

this cognito api is so confusing

by the way, in the notes api how come you associate a note with a cognitoIdentityId rather than the 'sub' which is at the end of the cognitoAuthenticationProvider field

"cognitoAuthenticationProvider": "cognito-idp.us-east-1.amazonaws.com/us-east-1_Wg0Dp2n5r,cognito-idp.us-east-1.amazonaws.com/us-east-1_Wg0Dp2n5r:CognitoSignIn:c45b94b4-57e5-41gc-86c3-6ed5e41212359",

The reason i say this is because when it comes to lokoing up users in the cognito console, then they all get listed there by sub, with no sign of a cognitoIdentityId at all . @jayair

jayair commented 6 years ago

@walshe It can be done either way. But say you had multiple auth providers (Facebook and Google); the Identity Id gives you a unified id for the user.

walshe commented 6 years ago

I see. Btw @jayair whats your opinion on this as a way to get info on a user groups and attributes.. here is what I am doing:

I pass the email addr from frontend (used in the login form) to a protected lambda. In there i use email param to:

  1. call var user = await cognitoIdentityServiceProvider.adminGetUser({ UserPoolId: process.env.USER_POOL_ID, Username: email }).promise()
  2. check event.requestContext.identity.cognitoAuthenticationProvider.includes(user.Username)) (just in case a logged in user maliciously tried to pass in someone else's email address to try to obtain admin access of some sort)
  3. then use the attributes from the user obj in (1) as i know they are belonging to the caller
  4. call var groupsResult = await cognitoIdentityServiceProvider.adminListGroupsForUser({UserPoolId:process.env.USER_POOL_ID, Username: user.Username}).promise() to get the groups for the user. Here the Username param is actually the sub of the cognito user
  5. I process groupsResult to check that user is in 'admin' group i have configued
jayair commented 6 years ago

@walshe Yeah that makes sense. I haven't tried it but it looks okay.