aws-cognito: identity provider attribute mapping mishandles custom attributes
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
I have added a custom attribute to my Cognito user pool and I wanted for an identity provider to map a claim to this custom attribute.
Following the documentation at https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cognito.AttributeMapping.html I defined the mapping like this
```ts
{
email: cognito.ProviderAttribute.other('email'),
familyName: cognito.ProviderAttribute.other('family_name'),
givenName: cognito.ProviderAttribute.other('given_name'),
fullname: cognito.ProviderAttribute.other('name'),
custom: {
'idp_userid': cognito.ProviderAttribute.other('sub')
}
}
```
And then pass that to the `UserPoolIdentityProviderOidcProps`'s `attributeMapping` property.
However, this generates the wrong CloudFormation template, as the custom attribute is not prefixed with `custom:`. Although it deploys, when editing the mapping from the console, the mapping is not recognized, but if modified manually the console adds the `custom:` prefix.
The generated template looks like this
```
"Type": "AWS::Cognito::UserPoolIdentityProvider",
"Properties": {
"AttributeMapping": {
"email": "email",
"family_name": "family_name",
"given_name": "given_name",
"name": "name",
"custom:idp_userid": "sub"
},
```
When it should look like
### Expected Behavior
The generated template should looks like this
```
"Type": "AWS::Cognito::UserPoolIdentityProvider",
"Properties": {
"AttributeMapping": {
"email": "email",
"family_name": "family_name",
"given_name": "given_name",
"name": "name",
"custom:idp_userid": "sub"
},
```
### Current Behavior
The generated template should looks like this
```
"Type": "AWS::Cognito::UserPoolIdentityProvider",
"Properties": {
"AttributeMapping": {
"email": "email",
"family_name": "family_name",
"given_name": "given_name",
"name": "name",
"idp_userid": "sub"
},
```
### Reproduction Steps
```ts
const userPool = new cognito.UserPool(this, 'CloudUser', {
accountRecovery: cognito.AccountRecovery.EMAIL_ONLY,
customAttributes: {
idp_userid: new cognito.StringAttribute({
minLen: 0,
maxLen: 128,
mutable: true
})
},
standardAttributes: {
email: {
required: true
}
},
selfSignUpEnabled: true,
signInAliases: { email: true },
signInCaseSensitive: false,
userPoolName: `spx-cloud-${props.stage}-mock`,
removalPolicy: RemovalPolicy.DESTROY
});
new cognito.UserPoolIdentityProviderOidc(this, 'SsoIdP',
{
name: 'test',
userPool: userPool,
attributeMapping: {
email: cognito.ProviderAttribute.other('email'),
familyName: cognito.ProviderAttribute.other('family_name'),
givenName: cognito.ProviderAttribute.other('given_name'),
fullname: cognito.ProviderAttribute.other('name'),
custom: {
'idp_userid': cognito.ProviderAttribute.other('sub')
}
},
clientId: 'abcde',
clientSecret: 'password',
issuerUrl: 'http://....',
cognito.OidcAttributeRequestMethod.GET,
scopes: ['openid', 'email', 'profile']
}
);
```
### Possible Solution
A workaround is to define the mapping as follows
```ts
{
email: cognito.ProviderAttribute.other('email'),
familyName: cognito.ProviderAttribute.other('family_name'),
givenName: cognito.ProviderAttribute.other('given_name'),
fullname: cognito.ProviderAttribute.other('name'),
custom: {
'custom:idp_userid': cognito.ProviderAttribute.other('sub')
}
}
```
I think the problem is in https://github.com/aws/aws-cdk/blame/00a7f033f6ad19160a7350784243ecf9c71c388b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/private/user-pool-idp-base.ts#L33C11-L33C11
Instead of
```ts
return { ...agg, [k]: v.attributeName };
```
The code should probably read
```ts
return { ...agg, [k]: `custom:${v.attributeName}` };
```
### Additional Information/Context
_No response_
### CDK CLI Version
2.92.0
### Framework Version
2.92.0
### Node.js Version
v16.18.1
### OS
Linux
### Language
Typescript
### Language Version
_No response_
### Other information
_No response_
Contributor guide
Research direction
Start in packages/aws-cdk-lib/aws-cognito/lib/user-pool-idps/private/user-pool-idp-base.ts, at the attribute-mapping aggregation identified in the issue. Compare the mapping produced for entries under custom with the expected CloudFormation template, then verify that custom attributes are emitted with the custom: prefix and standard attributes remain unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- authentication, cloud
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 38/100