List of usage examples for com.amazonaws.services.cognitoidp.model PasswordPolicyType setRequireSymbols
public void setRequireSymbols(Boolean requireSymbols)
In the password policy that you have set, refers to whether you have required users to use at least one symbol in their password.
From source file:squash.deployment.lambdas.CognitoCustomResourceLambda.java
License:Apache License
/** * Implementation for the AWS Lambda function backing the Cognito resource. * //from ww w . ja v a 2s . c o m * <p>This lambda requires the following environment variables: * <ul> * <li>StackName - name of Cloudformation stack - used as the name of the identity pool.</li> * <li>AuthenticatedRole - arn of role specifying permissions for authenticated users.</li> * <li>AuthenticatedRoleName - name of the authenticated role.</li> * <li>UnauthenticatedRole - arn of role specifying permissions for guest users.</li> * <li>UnauthenticatedRoleName - name of the unauthenticated role.</li> * <li>AdminEmail - initial email address for the admin user</li> * <li>LoginUrl - url of login page for admin user</li> * <li>Region - the AWS region in which the Cloudformation stack is created.</li> * <li>Revision - integer incremented to force stack updates to update this resource.</li> * </ul> * * <p>On success, it returns the following outputs to Cloudformation: * <ul> * <li>CognitoIdentityPoolId - id of the created Cognito identity pool.</li> * <li>CognitoUserPoolId - id of the created Cognito user pool.</li> * <li>CognitoUserPoolIdentityProviderName - name of the Cognito user pool identity provider to use from javascript.</li> * <li>JavascriptClientAppId - id of user pool client app to use from javascript</li> * </ul> * * <p>Updates will re-set the pool unauthenticated and authenticated roles * * @param request request parameters as provided by the CloudFormation service * @param context context as provided by the CloudFormation service */ @Override public Object handleRequest(Map<String, Object> request, Context context) { LambdaLogger logger = context.getLogger(); logger.log("Starting Cognito custom resource handleRequest"); // Handle standard request parameters Map<String, String> standardRequestParameters = LambdaInputLogger.logStandardRequestParameters(request, logger); String requestType = standardRequestParameters.get("RequestType"); // Handle required environment variables logger.log("Logging required environment variables for custom resource request"); String stackName = System.getenv("StackName"); String authenticatedRole = System.getenv("AuthenticatedRole"); String authenticatedRoleName = System.getenv("AuthenticatedRoleName"); String unauthenticatedRole = System.getenv("UnauthenticatedRole"); String unauthenticatedRoleName = System.getenv("UnauthenticatedRoleName"); String adminEmail = System.getenv("AdminEmail"); String loginUrl = System.getenv("LoginUrl"); String region = System.getenv("AWS_REGION"); String revision = System.getenv("Revision"); // Log out our required environment variables logger.log("StackName: " + stackName); logger.log("Authenticated role: " + authenticatedRole); logger.log("Authenticated role name: " + authenticatedRoleName); logger.log("Unauthenticated role: " + unauthenticatedRole); logger.log("Unauthenticated role name: " + unauthenticatedRoleName); logger.log("Initial email address of admin user: " + adminEmail); logger.log("Login url for the admin user: " + loginUrl); logger.log("Region: " + region); logger.log("Revision: " + revision); // API calls below can sometimes give access denied errors during stack // creation which I think is bc required new roles have not yet propagated // across AWS. We sleep here to allow time for this propagation. try { Thread.sleep(10000); } catch (InterruptedException e) { logger.log("Sleep to allow new roles to propagate has been interrupted."); } // Prepare our response to be sent in the finally block CloudFormationResponder cloudFormationResponder = new CloudFormationResponder(standardRequestParameters, "DummyPhysicalResourceId"); // Initialise failure response, which will be changed on success String responseStatus = "FAILED"; String identityPoolName = stackName; logger.log("Setting Cognito Identity Pool name to: " + identityPoolName); String userPoolId = null; String identityPoolId = null; String providerName = null; String javascriptClientAppId = null; try { cloudFormationResponder.initialise(); AmazonCognitoIdentity identityClient = getAmazonCognitoIdentityClient(region); ListIdentityPoolsRequest listIdentityPoolsRequest = new ListIdentityPoolsRequest(); // Set some reasonable maximum (must be >=1 and <= 60) listIdentityPoolsRequest.setMaxResults(50); Optional<IdentityPoolShortDescription> identityPool = identityClient .listIdentityPools(listIdentityPoolsRequest).getIdentityPools().stream() .filter(pool -> pool.getIdentityPoolName().equals(identityPoolName)).findFirst(); AWSCognitoIdentityProvider providerClient = getAmazonCognitoIdentityProviderClient(region); ListUserPoolsRequest listUserPoolsRequest = new ListUserPoolsRequest(); listUserPoolsRequest.setMaxResults(50); Optional<UserPoolDescriptionType> userPool = providerClient.listUserPools(listUserPoolsRequest) .getUserPools().stream().filter(pool -> pool.getName().equals(identityPoolName)).findFirst(); if (requestType.equals("Create")) { // Check the Cognito Identity or User Pools do not exist already Boolean identityPoolAlreadyExists = identityPool.isPresent(); Boolean userPoolAlreadyExists = userPool.isPresent(); if (identityPoolAlreadyExists.booleanValue() || userPoolAlreadyExists.booleanValue()) { if (identityPoolAlreadyExists.booleanValue()) { logger.log("identityPoolAlreadyExists: " + identityPoolAlreadyExists.toString() + " : " + identityPool.get().getIdentityPoolName()); logger.log( "Error: Cognito identity pool with name: " + identityPoolName + " already exists"); } else { logger.log("userPoolAlreadyExists: " + userPoolAlreadyExists.toString() + " : " + userPool.get().getName()); logger.log("Error: Cognito user pool with name: " + identityPoolName + " already exists"); } // Change physical id in responder - this is bc CloudFormation will // follow up this failed creation with a Delete request to clean up // - and we want to ignore that delete call - but not delete calls // for our original resource - and we use the PhysicalId to tell these // two cases apart. cloudFormationResponder.setPhysicalResourceId("DuplicatePhysicalResourceId"); return null; } // Create the Cognito user pool with the specified name logger.log("Cognito user pool with name: " + identityPoolName + " does not exist, so creating it"); CreateUserPoolRequest createUserPoolRequest = new CreateUserPoolRequest(); createUserPoolRequest.setPoolName(identityPoolName); // Prevent users signing themselves up AdminCreateUserConfigType adminCreateUserConfigType = new AdminCreateUserConfigType(); adminCreateUserConfigType.setAllowAdminCreateUserOnly(true); adminCreateUserConfigType.setUnusedAccountValidityDays(1); MessageTemplateType inviteMessageTemplateType = new MessageTemplateType(); inviteMessageTemplateType.setEmailSubject("Your squash account details"); inviteMessageTemplateType.setEmailMessage( "Welcome! Your username is: {username} and your temporary password is: {####} (valid for 24 hours). Please login at: " + loginUrl); adminCreateUserConfigType.setInviteMessageTemplate(inviteMessageTemplateType); createUserPoolRequest.setAdminCreateUserConfig(adminCreateUserConfigType); // Allow user to sign in using their email List<String> aliasAttributes = new ArrayList<>(); aliasAttributes.add("email"); createUserPoolRequest.setAliasAttributes(aliasAttributes); // Don't force password to include symbols PasswordPolicyType passwordPolicy = new PasswordPolicyType(); passwordPolicy.setMinimumLength(6); passwordPolicy.setRequireSymbols(false); UserPoolPolicyType userPoolPolicy = new UserPoolPolicyType(); userPoolPolicy.setPasswordPolicy(passwordPolicy); createUserPoolRequest.setPolicies(userPoolPolicy); // Require email to be verified by entering a code. // N.B. Think this attribute is called "auto" verified bc, after a user // signs up, Cognito sends out an email to the user without us doing // anything more i.e. automatically. (And not bc the verification itself // is automatic). Note self-signUp is currently disabled. List<String> autoVerifiedAttributes = new ArrayList<>(); autoVerifiedAttributes.add("email"); createUserPoolRequest.setAutoVerifiedAttributes(autoVerifiedAttributes); // Customise the email verification message. This is used to send a code // during the forgot-password flow. It would also be sent to users // signing themselves up - though self-signup is currently disabled. createUserPoolRequest.setEmailVerificationSubject("Your squash verification code"); createUserPoolRequest .setEmailVerificationMessage("Please use the following code: {####} (valid for 24 hours)."); CreateUserPoolResult result = providerClient.createUserPool(createUserPoolRequest); userPoolId = result.getUserPool().getId(); logger.log("Created user pool with id: " + userPoolId); // Create admin app for use without SRP in this custom resource logger.log("Adding admin client app to user pool"); CreateUserPoolClientRequest createUserPoolClientRequestAdmin = new CreateUserPoolClientRequest(); createUserPoolClientRequestAdmin.setClientName("CutomResourceAdminClient"); createUserPoolClientRequestAdmin.setGenerateSecret(false); // Do not require SRP use when called from this custom resource List<String> explicitAuthFlows = new ArrayList<>(); explicitAuthFlows.add("ADMIN_NO_SRP_AUTH"); createUserPoolClientRequestAdmin.setExplicitAuthFlows(explicitAuthFlows); createUserPoolClientRequestAdmin.setUserPoolId(userPoolId); CreateUserPoolClientResult resultAdmin = providerClient .createUserPoolClient(createUserPoolClientRequestAdmin); String adminClientAppId = resultAdmin.getUserPoolClient().getClientId(); logger.log("Added admin client app to user pool. Client app id: " + adminClientAppId); // Create web app for use with SRP from Angular app logger.log("Adding javascript client app to user pool"); CreateUserPoolClientRequest createUserPoolClientRequestJavascript = new CreateUserPoolClientRequest(); createUserPoolClientRequestJavascript.setClientName("JavascriptClient"); // Javascript sdk does not use a client secret: createUserPoolClientRequestJavascript.setGenerateSecret(false); createUserPoolClientRequestJavascript.setUserPoolId(userPoolId); CreateUserPoolClientResult resultJavascript = providerClient .createUserPoolClient(createUserPoolClientRequestJavascript); javascriptClientAppId = resultJavascript.getUserPoolClient().getClientId(); logger.log("Added javascript client app to user pool. Client app id: " + javascriptClientAppId); // Create the Cognito identity pool with the specified name logger.log( "Cognito identity pool with name: " + identityPoolName + " does not exist, so creating it"); CreateIdentityPoolRequest createIdentityPoolRequest = new CreateIdentityPoolRequest(); createIdentityPoolRequest.setIdentityPoolName(identityPoolName); createIdentityPoolRequest.setAllowUnauthenticatedIdentities(true); CreateIdentityPoolResult pool = identityClient.createIdentityPool(createIdentityPoolRequest); identityPoolId = pool.getIdentityPoolId(); // Add roles to the pool addRolesToIdentityPool(unauthenticatedRoleName, unauthenticatedRole, authenticatedRoleName, authenticatedRole, identityPoolId, identityClient, logger); logger.log("Created identity pool with id: " + identityPoolId); // Create our Admin user with this user pool. This user will have to // change their password when they first sign in in order to // authenticate. logger.log("Creating admin user with user pool"); AdminCreateUserRequest adminCreateUserRequest = new AdminCreateUserRequest(); adminCreateUserRequest.setDesiredDeliveryMediums(Arrays.asList("EMAIL")); adminCreateUserRequest.setUsername("admin"); adminCreateUserRequest.setUserPoolId(userPoolId); // Set some attributes for the admin user List<AttributeType> userAttributes = new ArrayList<>(); AttributeType nameAttribute = new AttributeType(); nameAttribute.setName("given_name"); nameAttribute.setValue("Squash bookings service administrator"); userAttributes.add(nameAttribute); AttributeType emailAttribute = new AttributeType(); emailAttribute.setName("email"); emailAttribute.setValue(adminEmail); userAttributes.add(emailAttribute); // Must set email as verified to enable forgot-password flow (the user's // use of their initial random password does not set their email to // verified for some reason) AttributeType emailVerifiedAttribute = new AttributeType(); emailVerifiedAttribute.setName("email_verified"); emailVerifiedAttribute.setValue("True"); userAttributes.add(emailVerifiedAttribute); adminCreateUserRequest.setUserAttributes(userAttributes); providerClient.adminCreateUser(adminCreateUserRequest); logger.log("Created admin user with user pool"); // Set user pool identity providers in the identity pool. This allows // Cognito to dish out temporary credentials for users who are // authenticated with our user pool (although currently only the admin // user will exist). logger.log("Setting user pool identity providers with the identity pool"); List<CognitoIdentityProvider> cognitoIdentityProviders = new ArrayList<>(); providerName = "cognito-idp." + region + ".amazonaws.com/" + userPoolId; logger.log("Using identity provider name: " + providerName); CognitoIdentityProvider cognitoIdentityProviderAdmin = new CognitoIdentityProvider(); cognitoIdentityProviderAdmin.setClientId(adminClientAppId); cognitoIdentityProviderAdmin.setProviderName(providerName); cognitoIdentityProviders.add(cognitoIdentityProviderAdmin); CognitoIdentityProvider cognitoIdentityProviderJavascript = new CognitoIdentityProvider(); cognitoIdentityProviderJavascript.setClientId(javascriptClientAppId); cognitoIdentityProviderJavascript.setProviderName(providerName); cognitoIdentityProviders.add(cognitoIdentityProviderJavascript); // Add these providers to the identity pool UpdateIdentityPoolRequest updateIdentityPoolRequest = new UpdateIdentityPoolRequest(); updateIdentityPoolRequest.setCognitoIdentityProviders(cognitoIdentityProviders); updateIdentityPoolRequest.setAllowUnauthenticatedIdentities(true); updateIdentityPoolRequest.setIdentityPoolId(identityPoolId); updateIdentityPoolRequest.setIdentityPoolName(identityPoolName); identityClient.updateIdentityPool(updateIdentityPoolRequest); logger.log("Set user pool identity providers with the identity pool"); // Encode identities of both our pools in the physical resource id String physicalResourceId = "Identity pool id: " + identityPoolId + ", User pool id: " + userPoolId; logger.log("Setting physical resource id to: " + physicalResourceId); cloudFormationResponder.setPhysicalResourceId(physicalResourceId); } else if (requestType.equals("Update")) { // Updates will only ever be to the 2 pool roles - so just replace them logger.log("Updating the Cognito identity pool roles"); String physicalResourceId = standardRequestParameters.get("PhysicalResourceId"); cloudFormationResponder.setPhysicalResourceId(physicalResourceId); Map<String, String> poolIds = getPoolIdsFromPhysicalResourceId(physicalResourceId, logger); identityPoolId = poolIds.get("IdentityPoolId"); userPoolId = poolIds.get("UserPoolId"); providerName = "cognito-idp." + region + ".amazonaws.com/" + userPoolId; addRolesToIdentityPool(unauthenticatedRoleName, unauthenticatedRole, authenticatedRoleName, authenticatedRole, identityPoolId, identityClient, logger); } else if (requestType.equals("Delete")) { // Early-out if this is a Delete corresponding to a failed attempt to // create a duplicate pool, otherwise we will end up wrongly deleting // our (valid) original pool instead. String physicalResourceId = standardRequestParameters.get("PhysicalResourceId"); if (physicalResourceId.equals("DuplicatePhysicalResourceId")) { logger.log("Ignoring delete request as it's for a non-existent duplicate pool"); } else { Map<String, String> poolIds = getPoolIdsFromPhysicalResourceId(physicalResourceId, logger); identityPoolId = poolIds.get("IdentityPoolId"); userPoolId = poolIds.get("UserPoolId"); // Check the Cognito Identity Pool does exist if (!identityPool.isPresent()) { logger.log( "Error: Cognito identity pool with name: " + identityPoolName + " does not exist"); return null; } // Delete the Cognito identity pool with the specified name logger.log("Deleting Cognito identity pool with name: " + identityPoolName); DeleteIdentityPoolRequest deleteIdentityPoolRequest = new DeleteIdentityPoolRequest(); deleteIdentityPoolRequest.setIdentityPoolId(identityPoolId); identityClient.deleteIdentityPool(deleteIdentityPoolRequest); logger.log("Deleted Cognito identity pool"); // Check the Cognito User Pool does exist if (!userPool.isPresent()) { logger.log("Error: Cognito user pool with name: " + identityPoolName + " does not exist"); return null; } // Delete the Cognito user pool with the specified name logger.log("Deleting Cognito user pool with name: " + identityPoolName); DeleteUserPoolRequest deleteUserPoolRequest = new DeleteUserPoolRequest(); deleteUserPoolRequest.setUserPoolId(userPoolId); providerClient.deleteUserPool(deleteUserPoolRequest); logger.log("Deleted Cognito user pool"); } } responseStatus = "SUCCESS"; return null; } catch (AmazonServiceException ase) { ExceptionUtils.logAmazonServiceException(ase, logger); return null; } catch (AmazonClientException ace) { ExceptionUtils.logAmazonClientException(ace, logger); return null; } catch (Exception e) { logger.log("Exception caught in Cognito Lambda: " + e.getMessage()); return null; } finally { // Send response to CloudFormation cloudFormationResponder.addKeyValueOutputsPair("CognitoIdentityPoolId", identityPoolId); cloudFormationResponder.addKeyValueOutputsPair("CognitoUserPoolId", userPoolId); cloudFormationResponder.addKeyValueOutputsPair("CognitoUserPoolIdentityProviderName", providerName); cloudFormationResponder.addKeyValueOutputsPair("JavascriptClientAppId", javascriptClientAppId); cloudFormationResponder.sendResponse(responseStatus, logger); } }