Integration architecture
Mechanism A: OIDC federation
Cognito User Pool is configured with 1Kosmos as an external OIDC provider. During the federated sign-in flow, Cognito redirects the user to the 1Kosmos OIDC authorize endpoint with the /assurance/ial/2 scope. On callback, Cognito maps the id_token claims to user pool attributes.
Mechanism B: Lambda triggers
Lambda triggers provide the deepest integration, enabling proofing and step-up as inline steps in the Cognito authentication flow.
import json
import boto3
import requests
def lambda_handler(event, context):
response = requests.post(
f"https://{BLOCKID_TENANT}.1kosmos.net/v1/verify/sessions",
headers={
"Authorization": f"Bearer {BLOCKID_API_KEY}",
"Content-Type": "application/json"
},
json={
"document_types": ["drivers_license", "passport"],
"liveness_mode": "active",
"callback_url": f"{API_GATEWAY_URL}/idv-callback",
"metadata": {
"cognito_user_pool": event['userPoolId'],
"cognito_username": event['userName']
}
}
)
session = response.json()
event['response']['autoConfirmUser'] = False
return event
def define_auth_challenge(event, context):
if event['request']['session'] and \
len(event['request']['session']) > 0 and \
event['request']['session'][-1]['challengeResult']:
event['response']['issueTokens'] = True
else:
event['response']['issueTokens'] = False
event['response']['challengeName'] = 'CUSTOM_CHALLENGE'
return event
def create_auth_challenge(event, context):
stepup = requests.post(
f"https://{BLOCKID_TENANT}.1kosmos.net/v1/auth/stepup",
headers={"Authorization": f"Bearer {BLOCKID_API_KEY}"},
json={
"user_id": event['request']['userAttributes'].get('custom:blockid_sub'),
"reason_code": "high_value_transaction",
"timeout_seconds": 300
}
)
challenge = stepup.json()
event['response']['publicChallengeParameters'] = {
'challenge_id': challenge['challenge_id'],
'challenge_url': challenge['challenge_url']
}
event['response']['privateChallengeParameters'] = {
'challenge_id': challenge['challenge_id']
}
return event
def verify_auth_challenge(event, context):
challenge_id = event['request']['privateChallengeParameters']['challenge_id']
result = requests.get(
f"https://{BLOCKID_TENANT}.1kosmos.net/v1/auth/stepup/{challenge_id}/result",
headers={"Authorization": f"Bearer {BLOCKID_API_KEY}"}
)
stepup_result = result.json()
event['response']['answerCorrect'] = (
stepup_result.get('match_result') == True and
stepup_result.get('liveness_verified') == True
)
return event
import json
import boto3
import requests
def lambda_handler(event, context):
response = requests.post(
f"https://{BLOCKID_TENANT}.1kosmos.net/v1/verify/sessions",
headers={
"Authorization": f"Bearer {BLOCKID_API_KEY}",
"Content-Type": "application/json"
},
json={
"document_types": ["drivers_license", "passport"],
"liveness_mode": "active",
"callback_url": f"{API_GATEWAY_URL}/idv-callback",
"metadata": {
"cognito_user_pool": event['userPoolId'],
"cognito_username": event['userName']
}
}
)
session = response.json()
event['response']['autoConfirmUser'] = False
return event
def define_auth_challenge(event, context):
if event['request']['session'] and \
len(event['request']['session']) > 0 and \
event['request']['session'][-1]['challengeResult']:
event['response']['issueTokens'] = True
else:
event['response']['issueTokens'] = False
event['response']['challengeName'] = 'CUSTOM_CHALLENGE'
return event
def create_auth_challenge(event, context):
stepup = requests.post(
f"https://{BLOCKID_TENANT}.1kosmos.net/v1/auth/stepup",
headers={"Authorization": f"Bearer {BLOCKID_API_KEY}"},
json={
"user_id": event['request']['userAttributes'].get('custom:blockid_sub'),
"reason_code": "high_value_transaction",
"timeout_seconds": 300
}
)
challenge = stepup.json()
event['response']['publicChallengeParameters'] = {
'challenge_id': challenge['challenge_id'],
'challenge_url': challenge['challenge_url']
}
event['response']['privateChallengeParameters'] = {
'challenge_id': challenge['challenge_id']
}
return event
def verify_auth_challenge(event, context):
challenge_id = event['request']['privateChallengeParameters']['challenge_id']
result = requests.get(
f"https://{BLOCKID_TENANT}.1kosmos.net/v1/auth/stepup/{challenge_id}/result",
headers={"Authorization": f"Bearer {BLOCKID_API_KEY}"}
)
stepup_result = result.json()
event['response']['answerCorrect'] = (
stepup_result.get('match_result') == True and
stepup_result.get('liveness_verified') == True
)
return event
import json
import boto3
import requests
def lambda_handler(event, context):
response = requests.post(
f"https://{BLOCKID_TENANT}.1kosmos.net/v1/verify/sessions",
headers={
"Authorization": f"Bearer {BLOCKID_API_KEY}",
"Content-Type": "application/json"
},
json={
"document_types": ["drivers_license", "passport"],
"liveness_mode": "active",
"callback_url": f"{API_GATEWAY_URL}/idv-callback",
"metadata": {
"cognito_user_pool": event['userPoolId'],
"cognito_username": event['userName']
}
}
)
session = response.json()
event['response']['autoConfirmUser'] = False
return event
def define_auth_challenge(event, context):
if event['request']['session'] and \
len(event['request']['session']) > 0 and \
event['request']['session'][-1]['challengeResult']:
event['response']['issueTokens'] = True
else:
event['response']['issueTokens'] = False
event['response']['challengeName'] = 'CUSTOM_CHALLENGE'
return event
def create_auth_challenge(event, context):
stepup = requests.post(
f"https://{BLOCKID_TENANT}.1kosmos.net/v1/auth/stepup",
headers={"Authorization": f"Bearer {BLOCKID_API_KEY}"},
json={
"user_id": event['request']['userAttributes'].get('custom:blockid_sub'),
"reason_code": "high_value_transaction",
"timeout_seconds": 300
}
)
challenge = stepup.json()
event['response']['publicChallengeParameters'] = {
'challenge_id': challenge['challenge_id'],
'challenge_url': challenge['challenge_url']
}
event['response']['privateChallengeParameters'] = {
'challenge_id': challenge['challenge_id']
}
return event
def verify_auth_challenge(event, context):
challenge_id = event['request']['privateChallengeParameters']['challenge_id']
result = requests.get(
f"https://{BLOCKID_TENANT}.1kosmos.net/v1/auth/stepup/{challenge_id}/result",
headers={"Authorization": f"Bearer {BLOCKID_API_KEY}"}
)
stepup_result = result.json()
event['response']['answerCorrect'] = (
stepup_result.get('match_result') == True and
stepup_result.get('liveness_verified') == True
)
return eventMechanism C: Amplify SDK integration
The 1Kosmos JavaScript SDK or mobile SDK is embedded alongside the AWS Amplify Auth library. The client application orchestrates the proofing flow and passes the verification result to Cognito via custom attributes during sign-up.
Step-up verification flow
Cognito's Custom Authentication Flow supports multi-step challenges. A step-up implementation inserts a 1Kosmos LiveID challenge as a CUSTOM_CHALLENGE in the authentication flow. The Define Auth Challenge Lambda evaluates the request context (e.g., API Gateway custom header indicating a high-value transaction) and issues a 1Kosmos biometric challenge. The Verify Auth Challenge Response Lambda validates the signed result from 1Kosmos before issuing tokens. This integrates with AWS API Gateway for transaction-level step-up in serverless architectures.
AWS architecture pattern: