45

In AWS Cognito, you can add a user to a group (after first creating a group). A user may belong to one or more groups.

With using the JavaScript SDK (https://github.com/aws/amazon-cognito-identity-js), is there a way to read the assigned Groups? Would aws-sdk provide access over amazon-cognito-identity-js?

Chris
  • 4,672
  • 13
  • 52
  • 93
user1322092
  • 4,020
  • 7
  • 35
  • 52

8 Answers8

72

If you just need the Cognito UserPools Groups the Authenticated User is a member of, instead of making a separate API call, that data is encoded in the idToken.jwtToken that you received when authenticating.

This is useful for client-side rendering/access decisions in angular/react/etc. apps.

See the "cognito:groups" array claim in this example decoded idToken.jwtToken:

{
  "sub": "a18626f5-a011-454a-b4c2-6969b3155c24",
  "cognito:groups": [
    "uw-app-administrator",
    "uw-app-user"
  ],
  "email_verified": true,
  "iss": "https://cognito-idp.<region>.amazonaws.com/<user-pool-id>",
  "cognito:username": "<my-user-name>",
  "given_name": "<my-first-name>",
  "aud": "<audience-code>",
  "token_use": "id",
  "auth_time": 1493918449,
  "nickname": "Bubbles",
  "exp": 1493922049,
  "iat": 1493918449,
  "email": "<my-email>"
}

Hope this helps.

bfieber
  • 836
  • 7
  • 2
21

I originally expected the Cognito JavaScript API to provide a simple property or method to return the list of groups, but instead I concluded that it was buried within a token, and thus had to learn about jwt. Once the Cognito User is established and the session is retrieved, the array of groups is available within the IdToken.

var jwtDecode = require('jwt-decode');
var AmazonCognitoIdentity = require('amazon-cognito-identity-js');
var CognitoUserPool = AmazonCognitoIdentity.CognitoUserPool;
var CognitoUser = AmazonCognitoIdentity.CognitoUser;

var userPool = new CognitoUserPool({UserPoolId:'', ClientId:''");
...
app.get('/app', function(req, res){
    var cognitoUser = userPool.getCurrentUser();
    if(cognitoUser != null){
        cognitoUser.getSession(function(err, session) {
            if (err) {
                console.error(err);
                return;
            }
            console.log('session validity: ' + session.isValid());

            var sessionIdInfo = jwtDecode(session.getIdToken().jwtToken);
            console.log(sessionIdInfo['cognito:groups']);
        });
    }
});
jspeaks
  • 433
  • 1
  • 4
  • 13
15

If you're using Amplify, if you use the currentAuthenticatedUser method you can get the groups from the response using:

response.signInUserSession.idToken.payload['cognito:groups']

Or using the currentSession method you can use either of:

response.accessToken.payload['cognito:groups']

or

response.idToken.payload['cognito:groups']
10

This API does exist - AdminListGroupsForUser. The reason you're not seeing it is, as the name implies, that the API is currently only available on an admin basis. Cognito doesn't include admin APIs in the mobile SDKs. It would be included in the AWS SDKs/server side SDKs, but it's worth noting that this API does require developer credentials, as do all admin APIs.

Jeff Bailey
  • 5,655
  • 1
  • 22
  • 30
  • Jeff, thanks. I'm writing a public, client-side JS app. I assume I won't be able to use the AWS admin SDK, because of mechanism to store credentials... ? – user1322092 Jan 27 '17 at 03:20
  • 2
    That's fair. As an admin API you have to have developer creds, so as a client side app, that's a risky idea. I can take this as a feature request to add a user level version, though! – Jeff Bailey Jan 27 '17 at 04:04
  • 1
    Thanks Jeff, appreciate it. Many uses cases. With the ability to read group ID, I can easily use it for tenancy (say for a SaaS app). – user1322092 Jan 27 '17 at 05:04
  • 1
    I'll forward that on to the higher ups, thanks for the suggestion! – Jeff Bailey Jan 27 '17 at 05:07
3

You do not need to decode anything, the data is already available from session.getIdToken().payload['cognito:groups']

LiriB
  • 814
  • 8
  • 12
  • 2
    Cannot get this to work, says session.getIdToken().payload is undefined even though session.getIdToken() is defined as { jwtToken:"ejkwjkwjflkwfj..." } – Graham Hesketh Jul 05 '18 at 14:27
2

You can now easily get the user groups from the user session:

session.getIdToken().decodePayload();

This contains an array of groups in the cognito:groups key returned

bwobbones
  • 2,398
  • 3
  • 23
  • 32
0

If you mean to list groups for a specific user in the backend and return them as an API, here's a complete example using golang's aws sdk:

func sessionWithRegion(region *string) *session.Session {
    sess := Session.Copy()
    if v := aws.StringValue(sess.Config.Region); len(v) == 0 {
        sess.Config.Region = region
    }

    return sess
}

func getGroupsForUser(region, userPoolId, userName *string, limit int64, nextToken ...*string) (*cognitoidentityprovider.AdminListGroupsForUserOutput, error) {
    sess := sessionWithRegion(region)
    svc := cognitoidentityprovider.New(sess)

    input := &cognitoidentityprovider.AdminListGroupsForUserInput{
        UserPoolId: userPoolId,
        Username:   userName,
        Limit:      &limit,
    }

    if nextToken != nil && len(nextToken) > 0 {
        input.NextToken = nextToken[0]
    }

    return svc.AdminListGroupsForUser(input)

}

nextToken is used to support pagination to load more groups in case we still have users to return from cognito to return/fetch, in other words, is to fetch next page. here is a simple example of how your calls should look like

func listGroups(pageNo *string) ([]*cognitoidentityprovider.GroupType, *string, error) {

    page, err := getGroupsForUser(aws.String("us-east-1"), aws.String("xxx"), aws.String("myuserName"), 60, map[bool]*string{true: pageNo, false: nil}[pageNo != nil])
    if err != nil {
        return nil, nil, err
    }
    return page.Groups, page.NextToken, nil
}

The above code snippets were just meant to make it easy for you and other colleagues from the community to understand the idea and how to implement it but it may need some tweaks. please feel free to leave a comment in case you need more help.

Muhammad Soliman
  • 21,644
  • 6
  • 109
  • 75
0

If you are using Amplify and the Auth module, you can call the currentAuthenticatedUser method, and pull the payload information. See below:

import {API, Auth} from "aws-amplify";


export const getCurrentUser = async () => {
  try {
    const userInfo = await Auth.currentAuthenticatedUser({bypassCache:true})
    console.log("User info: ",userInfo)

    if(userInfo){
// returns a Array<strings>
      return userInfo.signInUserSession.idToken.payload["cognito:groups"];
    }
  }

  catch (err) {
    console.log('error: ', err)
  }
}