Ability to configure a Cognito User Pool Clients including callback URLs, signout URLs, and allowed scopes.
I'm submitting a ...
What is the current behavior?
Can create UserPools and UserPool clients, however the configuration of the client is very limited. Can only specify clientName, enabledAuthFlows, and whether to create a secret or not.
What is the expected behavior (or behavior of feature suggested)?
Would also like to be able to configure callback URLs, signout URLs, and allowed scopes so a complete functional UserPool can be created from scratch.
What is the motivation / use case for changing the behavior or adding this feature?
Ability to create an ApiGateway secured by a cognito userpool with specific callback URLs and available scopes.
Please tell us about your environment:
Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. associated pull-request, stackoverflow, gitter, etc)
Currently I am creating the userpool like below, I believe this to be correct but please tell me if this is the wrong way to go about this?
const userPool = new cognito.UserPool(this, "userPool", {
autoVerifiedAttributes: [],
poolName: "userPool",
signInType: cognito.SignInType.Username,
usernameAliasAttributes: [
cognito.UserPoolAttribute.Email,
cognito.UserPoolAttribute.PhoneNumber
]
});
const userPoolClient = new cognito.UserPoolClient(
this,
"userPoolClient",
{
clientName: "Client",
enabledAuthFlows: [
cognito.AuthFlow.AdminNoSrp,
cognito.AuthFlow.CustomFlowOnly
],
userPool: userPool
}
);
Hi Callum, thanks for reaching out!
Unfortunately, it appears that CloudFormation doesn't currently support setting callback or signout URLs.
I recommend commenting here to try to bring some attention to the issue. Meanwhile I have put in an internal ticket to the Cloudformation team regarding this gap.
Once they have resolved the issue, I will reopen this issue as a feature-request.
Thanks will close for now and keep an eye on cloud formation updates.
In an effort to have better visibility of Cfn support gaps, we are going to keep these open, so I am going to reopen this issue.
From the CloudFormation documentation on UserPoolClient I would expect CloudFormation to support callback and logout URLS. Not sure if this was added recently by the CloudFormation team, but I thought it would be useful to post it here.
So this means that for now you could use the Cfn
escape hatch as long as not all features in the CDK classes are implemented. Something like this gives you an idea:
const userPool = new UserPool(...);
...
const userPoolClient = new UserPoolClient(
scope,
'user-pool-client',
{
userPoolClientName: 'user-pool-client-name',
userPool: userPool,
enabledAuthFlows: [AuthFlow.USER_PASSWORD],
generateSecret: true
}
);
const cfnUserPoolClient = userPoolClient.node.defaultChild as CfnUserPoolClient;
cfnUserPoolClient.supportedIdentityProviders = ['COGNITO'];
cfnUserPoolClient.callbackUrLs = ['https://your_service_domain/oauth2/idpresponse'];
cfnUserPoolClient.allowedOAuthFlowsUserPoolClient = true;
cfnUserPoolClient.allowedOAuthFlows = ['code'];
cfnUserPoolClient.allowedOAuthScopes = ['openid'];
Be aware of the 'strange' capitalizing of the callbackUrLs
and logoutUrLs
methods.
I did give it a run with CDK 1.9.0 and it seemed to create the UserPoolClient with the callback URL just fine for me.
I'm not sure if this is the right place, but in my use case, I'd like to authenticate with cognito from an application load balancer action using a secret generated via a UserPoolClient or CfnUserPoolClient.
It doesn't seem clear how the oidc client secret can be gotten from the UserPoolClient and given to the application load balancer rule actions, as I seem to get a nonsense value from from the UserPoolClient.userPoolClientClientSecret
property.
Apparently there was a ClientSecret attribute documented on UserPoolClient resources at one point. I'm not sure what happened.
https://github.com/awsdocs/aws-cloudformation-user-guide/issues/72
Hi @misterjoshua,
I believe there is no convenient way to automate this at the moment. The client secret is not available through CloudFormation and thus there is no way to use it from CDK simply by referencing the attribute.
That said, what you might be able to do is the following*:
*Not sure if this plays well if all resources are defined within the same stack, because secrets needs to be available at the moment the CloudFormation template is being rolled out. But if you use different stacks for your Cognito UserPoolClient and ALB resources I don't see why it wouldn't work.
I haven't tried this myself, so that's how far my warranty goes ;-), but it might be worth a try.
By the way have you considered posting your question on Stackoverflow? Maybe other people might have a potential solution for this as well.
May be worth checking out and subscribing to https://github.com/aws/aws-cdk-rfcs/issues/95 as well.
I'm having an issue with something similar. I'm unable to use the suggested SSM parameter if the string is secured.
See https://github.com/aws/aws-cdk/issues/6819
As a followup to @dveijck's post above replying to @misterjoshua; CDK has a really short/convenient syntax for custom resources that just need to call AWS SDK functions:
A basic example (untested for this use case exactly) derived from some similar code I wrote recently:
const describeCognitoUserPoolClient = new cr.AwsCustomResource(
this,
'DescribeCognitoUserPoolClient',
{
resourceType: 'Custom::DescribeCognitoUserPoolClient',
onCreate: {
region: 'us-east-1',
service: 'CognitoIdentityServiceProvider',
action: 'describeUserPoolClient',
parameters: {
UserPoolId: userPool.userPoolId,
ClientId: userPoolClient.userPoolClientId,
},
physicalResourceId: cr.PhysicalResourceId.of(userPoolClient.userPoolClientId),
},
// TODO: can we restrict this policy more?
policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE,
}),
}
)
const userPoolClientSecret = describeCognitoUserPoolClient.getResponseField(
'UserPoolClient.ClientSecret'
)
new cdk.CfnOutput(this, 'UserPoolClientSecret', {
value: userPoolClientSecret,
})
The original issue opened here has been resolved - https://github.com/aws/aws-cdk/commit/09852d05242fff9ba9080df9121537f81af9d131
I've opened a separate issue to track retrieval of the client secret - https://github.com/aws/aws-cdk/issues/7225. Please +1 and comment over there.
Thanks!
Hello,
I am wondering if the Sign out URL has been implemented yet? I can only find the Callback Url
Thanks
I'm wondering the same, I cannot find the sign out URL as params. I'm using cdk in typescript.
@huankimtran @leantorres73 the parameter is called logoutUrLs
.
@katiewoolston maybe it exists for other languages, for typescript is not implemented.
export interface OAuthSettings {
/**
* OAuth flows that are allowed with this client.
* @see - the 'Allowed OAuth Flows' section at https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-idp-settings.html
* @default {authorizationCodeGrant:true,implicitCodeGrant:true}
*/
readonly flows?: OAuthFlows;
/**
* List of allowed redirect URLs for the identity providers.
* @default - ['https://example.com'] if either authorizationCodeGrant or implicitCodeGrant flows are enabled, no callback URLs otherwise.
*/
readonly callbackUrls?: string[];
/**
* OAuth scopes that are allowed with this client.
* @see https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-idp-settings.html
* @default [OAuthScope.PHONE,OAuthScope.EMAIL,OAuthScope.OPENID,OAuthScope.PROFILE,OAuthScope.COGNITO_ADMIN]
*/
readonly scopes?: OAuthScope[];
}
@leantorres73 I'm using TypeScript, but the logoutUrLs
attribute is in the user pool App Client constructor props. This is how I set it:
import { CfnUserPoolClient } from '@aws-cdk/aws-cognito';
const userPoolClient = new CfnUserPoolClient(this, 'MyAppClient', {
clientName: 'MyAppClient',
userPoolId: 'some-userpool-id',
...someOtherParams,
callbackUrLs: [myAppUrl],
logoutUrLs: [myAppUrl],
});
@katiewoolston got it, I'm using the pool.addClient()
method, which has the callbackUrls but it doesn't have the logoutUrls
. This was my example:
const client = pool.addClient('app-client', {
oAuth: {
flows: {
authorizationCodeGrant: true,
},
scopes: [ OAuthScope.OPENID, OAuthScope.EMAIL, OAuthScope.PROFILE ],
callbackUrls: [ '', '' ]
}
});
Ah, I see - yeah, it doesn't look like you can do it that way.
Most helpful comment
From the CloudFormation documentation on UserPoolClient I would expect CloudFormation to support callback and logout URLS. Not sure if this was added recently by the CloudFormation team, but I thought it would be useful to post it here.
So this means that for now you could use the
Cfn
escape hatch as long as not all features in the CDK classes are implemented. Something like this gives you an idea:Be aware of the 'strange' capitalizing of the
callbackUrLs
andlogoutUrLs
methods.I did give it a run with CDK 1.9.0 and it seemed to create the UserPoolClient with the callback URL just fine for me.