Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/every-knives-warn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@aws-amplify/backend-output-schemas': minor
'@aws-amplify/auth-construct': minor
'@aws-amplify/client-config': minor
---

Add passwordless authentication options to client config
104 changes: 52 additions & 52 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions packages/auth-construct/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ export type AuthProps = {
multifactor?: MFA;
accountRecovery?: keyof typeof aws_cognito.AccountRecovery;
groups?: string[];
passwordlessOptions?: {
preferredChallenge?: 'EMAIL_OTP' | 'SMS_OTP' | 'PASSWORD' | 'WEB_AUTHN';
};
outputStorageStrategy?: BackendOutputStorageStrategy<AuthOutput>;
};

Expand Down
1 change: 1 addition & 0 deletions packages/auth-construct/src/construct.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1461,6 +1461,7 @@ void describe('Auth construct', () => {
'passwordPolicyRequirements',
'mfaConfiguration',
'mfaTypes',
'passwordlessOptions',
'socialProviders',
'oauthCognitoDomain',
'oauthScope',
Expand Down
51 changes: 51 additions & 0 deletions packages/auth-construct/src/construct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ export class AmplifyAuth
*/
private customSenderKMSkey: IKey | undefined;

/**
* The preferred authentication challenge
*/
private readonly preferredChallenge: string | undefined;

/**
* Create a new Auth construct with AuthProps.
* If no props are provided, email login and defaults will be used.
Expand All @@ -154,6 +159,7 @@ export class AmplifyAuth
super(scope, id);
this.name = props.name ?? '';
this.domainPrefix = props.loginWith.externalProviders?.domainPrefix;
this.preferredChallenge = props.passwordlessOptions?.preferredChallenge;
// UserPool
this.computedUserPoolProps = this.getUserPoolProps(props);

Expand Down Expand Up @@ -1369,6 +1375,51 @@ export class AmplifyAuth
},
});

// extract passwordless configuration
output.passwordlessOptions = Lazy.string({
produce: () => {
const passwordlessConfig: {
emailOtpEnabled?: boolean;
smsOtpEnabled?: boolean;
webAuthn?: {
relyingPartyId: string;
userVerification: 'required' | 'preferred';
};
preferredChallenge?: string;
} = {};

const signInPolicy = (
cfnUserPool.policies as CfnUserPool.PoliciesProperty
)?.signInPolicy;
if (signInPolicy) {
const allowedFactors =
(signInPolicy as CfnUserPool.SignInPolicyProperty)
.allowedFirstAuthFactors || [];
passwordlessConfig.emailOtpEnabled =
allowedFactors.includes('EMAIL_OTP');
passwordlessConfig.smsOtpEnabled = allowedFactors.includes('SMS_OTP');

if (allowedFactors.includes('WEB_AUTHN')) {
passwordlessConfig.webAuthn = {
relyingPartyId: cfnUserPool.webAuthnRelyingPartyId || '',
userVerification:
(cfnUserPool.webAuthnUserVerification as
| 'required'
| 'preferred') || 'preferred',
};
}
}

if (this.preferredChallenge) {
passwordlessConfig.preferredChallenge = this.preferredChallenge;
}

return Object.keys(passwordlessConfig).length > 0
? JSON.stringify(passwordlessConfig)
: '';
},
});

// extract social providers from UserPool resource
output.socialProviders = Lazy.string({
produce: () => {
Expand Down
14 changes: 14 additions & 0 deletions packages/auth-construct/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,20 @@ export type AuthProps = {
*/
groups?: string[];

/**
* Passwordless authentication options.
*/
passwordlessOptions?: {
/**
* Specify the preferred authentication challenge for users.
* This setting is propagated to the frontend but does not affect backend behavior.
* @default undefined
* @example
* preferredChallenge: 'PASSWORD'
*/
preferredChallenge?: 'EMAIL_OTP' | 'SMS_OTP' | 'PASSWORD' | 'WEB_AUTHN';
};

/**
* @internal
*/
Expand Down
Loading
Loading