You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS Cognito与Lambda:为用户池添加LinkedIn联合身份

Nice work getting your Cognito user pool, identity pool, and LinkedIn app set up already! Since Cognito doesn't have native support for LinkedIn, using a Lambda function to bridge the gap is exactly the right approach. Here's a detailed, step-by-step guide to make this integration work smoothly:

实现LinkedIn联合身份与AWS Cognito用户池集成的完整流程

1. 提前准备工作(确认已完成)

Before diving in, double-check these boxes to avoid roadblocks:

  • Your LinkedIn app has the correct redirect URIs configured and the r_liteprofile + r_emailaddress scopes enabled
  • Your Cognito user pool has a custom attribute custom:linkedin_user_id created (to store unique LinkedIn user IDs)
  • Your Cognito identity pool is linked to your user pool as an identity provider

2. 创建核心Lambda函数(Python示例)

This function will handle exchanging LinkedIn auth codes for user data, syncing users to your Cognito pool, and returning valid Cognito tokens to your frontend.

First, store sensitive values (LinkedIn client ID/secret, Cognito IDs) in AWS Secrets Manager instead of hardcoding them. Here's the core logic:

import boto3
import requests
import json

# Initialize clients
cognito_client = boto3.client('cognito-idp')
secrets_manager = boto3.client('secretsmanager')

def get_secrets():
    """Fetch sensitive values from Secrets Manager"""
    secret_resp = secrets_manager.get_secret_value(SecretId='linkedin-cognito-integration')
    return json.loads(secret_resp['SecretString'])

def lambda_handler(event, context):
    secrets = get_secrets()
    linkedin_code = event['code']

    # Step 1: Exchange LinkedIn auth code for access token
    token_resp = requests.post(
        'https://www.linkedin.com/oauth/v2/accessToken',
        data={
            'grant_type': 'authorization_code',
            'code': linkedin_code,
            'client_id': secrets['linkedin_client_id'],
            'client_secret': secrets['linkedin_client_secret'],
            'redirect_uri': secrets['linkedin_redirect_uri']
        }
    )
    token_data = token_resp.json()
    access_token = token_data['access_token']

    # Step 2: Fetch LinkedIn user profile and email
    profile_resp = requests.get(
        'https://api.linkedin.com/v2/me',
        headers={'Authorization': f'Bearer {access_token}'}
    )
    profile_data = profile_resp.json()
    linkedin_user_id = profile_data['id']
    first_name = profile_data['localizedFirstName']
    last_name = profile_data['localizedLastName']

    email_resp = requests.get(
        'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))',
        headers={'Authorization': f'Bearer {access_token}'}
    )
    email_data = email_resp.json()
    user_email = email_data['elements'][0]['handle~']['emailAddress']

    # Step 3: Sync user to Cognito user pool
    try:
        # Check if user already exists
        cognito_client.admin_get_user(
            UserPoolId=secrets['cognito_user_pool_id'],
            Username=user_email
        )
        # Update existing user attributes
        cognito_client.admin_update_user_attributes(
            UserPoolId=secrets['cognito_user_pool_id'],
            Username=user_email,
            UserAttributes=[
                {'Name': 'given_name', 'Value': first_name},
                {'Name': 'family_name', 'Value': last_name},
                {'Name': 'custom:linkedin_user_id', 'Value': linkedin_user_id}
            ]
        )
    except cognito_client.exceptions.UserNotFoundException:
        # Create new user in Cognito
        cognito_client.admin_create_user(
            UserPoolId=secrets['cognito_user_pool_id'],
            Username=user_email,
            UserAttributes=[
                {'Name': 'email', 'Value': user_email},
                {'Name': 'email_verified', 'Value': 'true'},
                {'Name': 'given_name', 'Value': first_name},
                {'Name': 'family_name', 'Value': last_name},
                {'Name': 'custom:linkedin_user_id', 'Value': linkedin_user_id}
            ],
            MessageAction='SUPPRESS'  # Skip welcome email
        )
        # Set temporary password (we'll auto-authenticate next)
        cognito_client.admin_set_user_password(
            UserPoolId=secrets['cognito_user_pool_id'],
            Username=user_email,
            Password='TempAuth123!',
            Permanent=False
        )

    # Step 4: Return Cognito auth tokens to frontend
    auth_resp = cognito_client.admin_initiate_auth(
        UserPoolId=secrets['cognito_user_pool_id'],
        ClientId=secrets['cognito_app_client_id'],
        AuthFlow='ADMIN_USER_PASSWORD_AUTH',
        AuthParameters={
            'USERNAME': user_email,
            'PASSWORD': 'TempAuth123!'
        }
    )

    return {
        'statusCode': 200,
        'body': json.dumps({
            'tokens': auth_resp['AuthenticationResult']
        })
    }

3. Configure Lambda Permissions

Attach a policy to your Lambda's execution role that allows these actions:

  • cognito-idp:AdminCreateUser
  • cognito-idp:AdminUpdateUserAttributes
  • cognito-idp:AdminGetUser
  • cognito-idp:AdminInitiateAuth
  • cognito-idp:AdminSetUserPassword
  • secretsmanager:GetSecretValue (for fetching your stored secrets)

If your Lambda runs in a VPC, ensure it has access to the internet (via a NAT Gateway) to call LinkedIn's APIs.

4. Frontend Integration Flow

  1. Redirect users to LinkedIn's authorization URL:
    https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=r_liteprofile%20r_emailaddress
    
  2. After user authorization, LinkedIn will redirect back to your frontend with a code parameter.
  3. Send this code to your Lambda function (expose it via API Gateway for HTTP access).
  4. Use the returned Cognito tokens to authenticate users in your app and interact with your Cognito identity pool for AWS resource access.

5. Optional: Skip Temporary Password Step

For a smoother flow, use Cognito's custom authentication flow instead of ADMIN_USER_PASSWORD_AUTH. Update your Lambda to handle DefineAuthChallenge, CreateAuthChallenge, and VerifyAuthChallengeResponse triggers—this lets you directly authenticate users without a temporary password.

内容的提问来源于stack exchange,提问作者Jez D

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:14:46