pycognito

repository·master·Indexed 41 days ago

https://github.com/nabucasa/pycognito

A Python library for integrating Boto3's Cognito client to simplify user authentication, registration, and management. It features built-in support for the Secure Remote Password (SRP) protocol, TOTP MFA, token verification, and a requests-compatible auth plugin for automatic HTTP Bearer authentication. Version 2024.5.1.

Tokens
9.3K
Snippets
37
Records
48
Agent score
100%

What's inside pycognito

  1. Access Cognito user claims

    master

    Once authentication or token verification is successful, you can access verified claims from the tokens via the following attributes:

    • id_claims: A dictionary of verified claims from the ID token.
    • access_claims: A dictionary of verified claims from the access token.
  2. Manage remembered devices with AWSSRP

    master

    To use Cognito's device tracking (Remembered Devices) feature, you must use the USER_SRP_AUTH authentication flow.

    1. Retrieve Device Keys

    When calling authenticate_user(), the returned tokens dictionary contains DeviceKey and DeviceGroupKey inside ['AuthenticationResult']['NewDeviceMetadata'].

    2. Confirm a Device

    Use confirm_device(tokens=tokens, DeviceName=...) to confirm the new device. This returns a response and a device_password. The device_password is required for subsequent device-based authentications.

    3. Update Device Status

    Use update_device_status(is_remembered, access_token, device_key) to set the device status.

    • is_remembered=True sets status to "remembered".
    • is_remembered=False sets status to "not_remembered".

    4. Authenticate using a known device

    To authenticate a device that has already been confirmed, pass the device_key, device_group_key, and device_password directly into the AWSSRP constructor.

    5. Forget a device

    Use forget_device(access_token=..., device_key=...) to remove a device.

    import boto3
    from pycognito.aws_srp import AWSSRP
    
    client = boto3.client('cognito-idp')
    aws = AWSSRP(username='username', password='password', pool_id='user_pool_id',
                 client_id='client_id', client=client)
    
    # 1. Get tokens and keys
    tokens = aws.authenticate_user()
    device_key = tokens["AuthenticationResult"]["NewDeviceMetadata"]["DeviceKey"]
    device_group_key = tokens["AuthenticationResult"]["NewDeviceMetadata"]["DeviceGroupKey"]
    
    # 2. Confirm device
    response, device_password = aws.confirm_device(tokens=tokens)
    
    # 3. Update status
    aws.update_device_status(False, tokens["AuthenticationResult"]["AccessToken"], device_key)
    
    # 4. Authenticate with device later
    aws_device = AWSSRP(username='username', password='password', pool_id='user_pool_id',
                        client_id='client_id', client=client, device_key=device_key,
                        device_group_key=device_group_key, device_password=device_password)
    tokens = aws_device.authenticate_user()
    
    # 5. Forget device
    aws.forget_device(access_token=tokens["AuthenticationResult"]["AccessToken"], device_key=device_key)
  3. Configure the COGNITO_JWKS environment variable

    master

    You can optionally provide the JSON Web Key Set (JWKS) via the COGNITO_JWKS environment variable. This is a dictionary representing the well-known JWKs assigned to your user pool by AWS Cognito.

    To find your JWKS URL, substitute your AWS region and pool ID into: https://cognito-idp.{aws-region}.amazonaws.com/{user-pool-id}/.well-known/jwks.json

    COGNITO_JWKS={"keys": [{"alg": "RS256","e": "AQAB","kid": "123456789ABCDEFGHIJKLMNOP","kty": "RSA","n": "123456789ABCDEFGHIJKLMNOP","use": "sig"}]}
  4. Initialize Cognito for user authentication

    master

    To authenticate a user who has not yet logged in (using SRP or admin authentication), initialize the class with the user_pool_id, client_id, and the user's username.

    from pycognito import Cognito
    
    u = Cognito('your-user-pool-id', 'your-client-id', username='bob')
  5. Initialize Cognito with existing tokens

    master

    If a user is already authenticated and you need to reconstruct a Cognito instance (e.g., within a web view), provide the tokens returned during the initial authentication. You can then call verify_tokens() to ensure they are valid.

    from pycognito import Cognito
    
    u = Cognito(
        'your-user-pool-id',
        'your-client-id',
        id_token='your-id-token',
        refresh_token='your-refresh-token',
        access_token='your-access-token'
    )
    
    u.verify_tokens() # May throw an exception if tokens are invalid
  6. Initialize Cognito for User Pool management

    master

    If you only need to perform administrative tasks or retrieve information about the user pool (such as listing users), initialize the class with only the user_pool_id and client_id.

    from pycognito import Cognito
    
    u = Cognito('your-user-pool-id', 'your-client-id')
  7. Manage Cognito Groups

    master

    Methods for interacting with User Pool groups:

    • Get Group: get_group(group_name=...) returns a group instance. Requires developer credentials.
    • Get Groups: get_groups() returns a list of all groups in the pool. Requires developer credentials.
    • Get Group Object: get_group_obj(group_data) returns a group instance from a raw data dictionary.
  8. Manage passwords (Forgot, Confirm, and Change)

    master

    pyCognito provides methods to handle the full password lifecycle:

    1. Initiate Forgot Password: Sends a verification code to the user via initiate_forgot_password().
    2. Confirm Forgot Password: Uses the code and a new password to complete the reset via confirm_forgot_password(confirmation_code, password).
    3. Change Password: Updates a password for an authenticated user via change_password(previous_password, proposed_password). Note that if you aren't using existing tokens, you must first call authenticate to establish the session.
    # Forgot password flow
    u.initiate_forgot_password()
    u.confirm_forgot_password('your-confirmation-code', 'your-new-password')
    
    # Change password flow (requires tokens)
    u = Cognito('pool-id', 'client-id', id_token='...', refresh_token='...', access_token='...')
    u.change_password('old-password', 'new-password')
  9. Register a new user with pyCognito

    master

    You can register a user to a Cognito User Pool using the register method. Before registering, you can define base attributes using set_base_attributes and custom attributes using add_custom_attributes.

    Important:

    • The arguments for set_base_attributes and add_custom_attributes must match your User Pool's configuration.
    • The client_id used must have explicit read/write permissions for the attributes you are attempting to set in the AWS Cognito console.
    from pycognito import Cognito
    
    u = Cognito('your-user-pool-id', 'your-client-id')
    
    # Set standard and custom attributes
    u.set_base_attributes(email='you@you.com', some_random_attr='random value')
    u.add_custom_attributes(state='virginia', city='Centreville')
    
    # Register the user
    u.register('username', 'password')
  10. Retrieve and update user profiles

    master

    You can fetch user data or update existing profiles:

    • Get User: get_user(attr_map=...) returns a user instance using Boto3 data. Use attr_map to map Cognito attribute names to user-friendly names.
    • Get User Object: get_user_obj(...) returns a specific instance of a user class with manual attribute lists and metadata.
    • Update Profile: update_profile(attrs, attr_map=...) updates attributes. attrs is a dictionary of {name: value} and attr_map maps Cognito attributes to your preferred display names.
    # Get user with mapped attributes
    user = u.get_user(attr_map={"given_name":"first_name"})
    
    # Update profile
    u.update_profile({'given_name':'Edward'}, attr_map={})
  11. Perform SRP authentication with AWSSRP

    master

    The AWSSRP class implements the Secure Remote Password (SRP) protocol, which is the preferred authentication method for AWS Cognito. It manages the series of challenges and responses required to obtain ID, access, and refresh tokens.

    To use it, instantiate AWSSRP with the user's credentials and Cognito configuration, then call authenticate_user().

    import boto3
    from pycognito.aws_srp import AWSSRP
    
    client = boto3.client('cognito-idp')
    aws = AWSSRP(username='username', password='password', pool_id='user_pool_id',
                 client_id='client_id', client=client)
    tokens = aws.authenticate_user()