aws-samples / amazon-cognito-passwordless-auth

Passwordless authentication with Amazon Cognito: FIDO2 (WebAuthn, support for Passkeys), Magic Link, SMS OTP Step Up
Apache License 2.0
378 stars 69 forks source link

Amplify defineAuth how to pass to UserPool in Passwordless lib #209

Open VadzimBelski-ScienceSoft opened 15 hours ago

VadzimBelski-ScienceSoft commented 15 hours ago

Hi,

I am trying to make a sinergy for Amplify Auth definitions with Passwordless.

My Backend.ts looks like this but unfortunetely it does not deploy

import * as cdk from "aws-cdk-lib";
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { data } from './data/resource';
import { PaswordlessStack } from './passwordless/resource';
import * as cognito from "aws-cdk-lib/aws-cognito";

/**
 * @see https://docs.amplify.aws/react/build-a-backend/ to add storage, functions, and more
 */
const backend = defineBackend({
  auth,
  data
});

// extract L1 CfnUserPool resources
const { cfnUserPool } = backend.auth.resources.cfnResources;

const passwordlessStack = new PaswordlessStack(  
  backend.createStack('PaswordlessStack'),
  'PaswordlessStack',
  cfnUserPool
);

backend.addOutput({
  custom: {
    region: "us-east-1",
    cognitoIdpEndpoint: passwordlessStack.passwordless.userPoolClients!.at(0)!.userPoolClientId,
    userPoolId: passwordlessStack.passwordless.userPool.userPoolId,
    ClientId: passwordlessStack.passwordless.userPoolClients!.at(0)!.userPoolClientId,
    Fido2Url: passwordlessStack.passwordless.fido2Api!.url!,
  },
});

My Paswordless looks like this


import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import { Passwordless } from "amazon-cognito-passwordless-auth/cdk";
import * as cognito from "aws-cdk-lib/aws-cognito";

export class PaswordlessStack extends cdk.Stack {
  public readonly passwordless: Passwordless;
  constructor(scope: Construct, id: string, userPool: cognito.IUserPool, props?: cdk.StackProps) {
    super(scope, id, props);

    this.passwordless = new Passwordless(this, "Passwordless", {
      userPool: userPool,
      allowedOrigins: [
        "http://localhost",
        "http://localhost:3000",
      ],
      magicLink: {
        sesFromAddress: "vadim.belsky@gmail.com", // must be a verified domain or identity in Amazon SES
        secretsTableProps: {
          removalPolicy: cdk.RemovalPolicy.DESTROY,
          billingMode: cdk.aws_dynamodb.BillingMode.PAY_PER_REQUEST,
        },
      },
      userPoolProps: {
        removalPolicy: cdk.RemovalPolicy.DESTROY,
      },
      fido2: {
        authenticatorsTableProps: {
          removalPolicy: cdk.RemovalPolicy.DESTROY,
          billingMode: cdk.aws_dynamodb.BillingMode.PAY_PER_REQUEST,
        },
        relyingPartyName: "Passwordless Fido2 Example",
        allowedRelyingPartyIds: [
          "localhost", // Domain names that you wish to use as Relying Party ID
        ],
        attestation: "none",
        userVerification: "required",
        updatedCredentialsNotification: {
          sesFromAddress: "vadim.belsky@gmail.com", // must be a verified domain or identity in Amazon SES
        },
      },
      smsOtpStepUp: {},
      userPoolClientProps: {
        // perrty short so you see token refreshes in action often:
        idTokenValidity: cdk.Duration.minutes(5),
        accessTokenValidity: cdk.Duration.minutes(5),
        refreshTokenValidity: cdk.Duration.hours(1),
        // while testing/experimenting it's best to set this to false,
        // so that when you try to sign in with a user that doesn't exist,
        // Cognito will tell you that––and you don't wait for a magic link
        // that will never arrive in your inbox:
        preventUserExistenceErrors: false,
      },
      // while testing/experimenting it's heplful to see e.g. full request details in logs:
      logLevel: "DEBUG",
    });
    new cdk.CfnOutput(this, "ClientId", {
      value: this.passwordless.userPoolClients!.at(0)!.userPoolClientId,
    });
    new cdk.CfnOutput(this, "cognitoIdpEndpoint", {
        value: this.passwordless.userPool.userPoolProviderUrl
    });
    new cdk.CfnOutput(this, "userPoolId", {
        value: this.passwordless.userPool.userPoolId
    });
    new cdk.CfnOutput(this, "Fido2Url", {
      value: this.passwordless.fido2Api!.url!,
    });
  }
}

from what i understand is that i can not modify Amplify cdk provisioned resources so i can not merge this 2 libs to work.

Please give me directions.

ottokruse commented 2 hours ago

The Passwordless CDK construct needs to create its own User Pool, or at least have the User Pool in the same CDK stack. That's why it can take in a UserPool as prop but not an IUserPool. If you can somehow make that happen it should work together. I don't know enough about Amplify to suggest to you if and how that can be down with Amplify.

ottokruse commented 18 minutes ago

Also see pointers here: https://github.com/aws-samples/amazon-cognito-passwordless-auth/issues/118