0

I'm trying to creating a URL that enables federated users to access the AWS Management Console following the [officlal documentation][1]. I'm using Cognito with [enhanced authflow][2] in order to authenticate user with username and password. This is the code:

################## 1. LOGIN ####################

cognito = boto3.client('cognito-idp', aws_access_key_id='', aws_secret_access_key='')
response = cognito.initiate_auth(
        ClientId = app_client_id,
        AuthFlow = 'USER_PASSWORD_AUTH',
        AuthParameters = {
             "USERNAME": username,
             "PASSWORD": password
        },
        ClientMetadata = { 'UserPoolId': user_pool_id }
)

id_token = response['AuthenticationResult']['IdToken'] 

################## 2. GET ID ####################

cognito_identity = boto3.client('cognito-identity', aws_access_key_id='', aws_secret_access_key='', region_name=region)

response = cognito_identity.get_id(
        IdentityPoolId = identity_pool_id,
        Logins = {
                'cognito-idp.{}.amazonaws.com/{}'.format(region, user_pool_id) : id_token 
        }
)

identity_id = response['IdentityId']

################## 3. RETRIEVE CREDENTIALS ####################

response = cognito_identity.get_credentials_for_identity(
        IdentityId = identity_id,
        Logins = {
            'cognito-idp.{}.amazonaws.com/{}'.format(region, user_pool_id) : id_token 
        }
)

access_key_id = response['Credentials']['AccessKeyId']
secret_key = response['Credentials']['SecretKey']
session_token = response['Credentials']['SessionToken']

For the next step (assume role and call federation endpoint) i'm not using the example in the official documentation linked above because it use boto rather than boto3. This is the code:

sts_boto_3 = boto3.client('sts',  aws_access_key_id = access_key_id, 
                                   aws_secret_access_key = secret_key, 
                                   aws_session_token = session_token, 
                                   region_name = region)

    response = sts_boto_3.assume_role(
            RoleArn = role,
            RoleSessionName = role_session_name,
    )
    session_id = response['Credentials']['AccessKeyId']
    session_key = response['Credentials']['SecretAccessKey']
    session_token = response['Credentials']['SessionToken']
    session_string =  '{{"sessioId" : "{}" , "sessionKey": "{}", "sessionToken" : "{}"}}'.format(session_id, session_key, session_token)

    req_url = 'https://signin.aws.amazon.com/federation?Action=getSigninToken&SessionDuration={}&Session={}'.format(3600, urllib.quote_plus(session_string))
    r = requests.get(req_url)
    print r

The result is

<Response [503]>

What i'm wrong?

[EDIT] There wasn't an error in session_string (sessioId instead of sessionId)

session_string =  '{{"sessionId" : "{}" , "sessionKey": "{}", "sessionToken" : "{}"}}'.format(session_id, session_key, session_token)

Now the response is 400 BAD REQUEST

<Response [400]>
user3083618
  • 270
  • 1
  • 4
  • 16

1 Answers1

0

I've added a full example of how to set up credentials and construct a URL that gives federated users direct access to the AWS Management Console on GitHub.

Here's the salient part of the code that constructs the URL:

def construct_federated_url(assume_role_arn, session_name, issuer, sts_client):
    """
    Constructs a URL that gives federated users direct access to the AWS Management
    Console.
    1. Acquires temporary credentials from AWS Security Token Service (AWS STS) that
       can be used to assume a role with limited permissions.
    2. Uses the temporary credentials to request a sign-in token from the
       AWS federation endpoint.
    3. Builds a URL that can be used in a browser to navigate to the AWS federation
       endpoint, includes the sign-in token for authentication, and redirects to
       the AWS Management Console with permissions defined by the role that was
       specified in step 1.
    For more information, see Enabling Custom Identity Broker Access to the AWS Console
    [https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html]
    in the AWS Identity and Access Management User Guide.
    :param assume_role_arn: The role that specifies the permissions that are granted.
                            The current user must have permission to assume the role.
    :param session_name: The name for the STS session.
    :param issuer: The organization that issues the URL.
    :param sts_client: A Boto3 STS instance that can assume the role.
    :return: The federated URL.
    """
    response = sts_client.assume_role(
        RoleArn=assume_role_arn, RoleSessionName=session_name)
    temp_credentials = response['Credentials']
    print(f"Assumed role {assume_role_arn} and got temporary credentials.")

    session_data = {
        'sessionId': temp_credentials['AccessKeyId'],
        'sessionKey': temp_credentials['SecretAccessKey'],
        'sessionToken': temp_credentials['SessionToken']
    }
    aws_federated_signin_endpoint = 'https://signin.aws.amazon.com/federation'

    # Make a request to the AWS federation endpoint to get a sign-in token.
    # The requests.get function URL-encodes the parameters and builds the query string
    # before making the request.
    response = requests.get(
        aws_federated_signin_endpoint,
        params={
            'Action': 'getSigninToken',
            'SessionDuration': str(datetime.timedelta(hours=12).seconds),
            'Session': json.dumps(session_data)
        })
    signin_token = json.loads(response.text)
    print(f"Got a sign-in token from the AWS sign-in federation endpoint.")

    # Make a federated URL that can be used to sign into the AWS Management Console.
    query_string = urllib.parse.urlencode({
        'Action': 'login',
        'Issuer': issuer,
        'Destination': 'https://console.aws.amazon.com/',
        'SigninToken': signin_token['SigninToken']
    })
    federated_url = f'{aws_federated_signin_endpoint}?{query_string}'
    return federated_url
Laren Crawford
  • 561
  • 4
  • 6