aws / aws/aws-cdk

aws-cognito: identity provider attribute mapping mishandles custom attributes

Open
#26,820 6 comments 9 reactions 0 assignees View on GitHub
@aws-cdk/aws-cognito bug documentation effort/small p3
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.