Skip to content

Commit

Permalink
Add OTP (Software MFA Token) Support. (#220)
Browse files Browse the repository at this point in the history
  • Loading branch information
Xtendera authored Jan 7, 2025
1 parent 02fc963 commit 85cdf58
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 1 deletion.
8 changes: 7 additions & 1 deletion client/cognito-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ type ChallengeName =
| "CUSTOM_CHALLENGE"
| "PASSWORD_VERIFIER"
| "SMS_MFA"
| "NEW_PASSWORD_REQUIRED";
| "NEW_PASSWORD_REQUIRED"
| "SOFTWARE_TOKEN_MFA";

interface ChallengeResponse {
ChallengeName: ChallengeName;
Expand Down Expand Up @@ -648,6 +649,7 @@ export async function handleAuthResponse({
authResponse,
username,
smsMfaCode,
otpMfaCode,
newPassword,
customChallengeAnswer,
clientMetadata,
Expand All @@ -659,6 +661,7 @@ export async function handleAuthResponse({
*/
username: string;
smsMfaCode?: () => Promise<string>;
otpMfaCode?: () => Promise<string>;
newPassword?: () => Promise<string>;
customChallengeAnswer?: () => Promise<string>;
clientMetadata?: Record<string, string>;
Expand Down Expand Up @@ -688,6 +691,9 @@ export async function handleAuthResponse({
if (!customChallengeAnswer)
throw new Error("Missing custom challenge answer");
responseParameters.ANSWER = await customChallengeAnswer();
} else if (authResponse.ChallengeName === "SOFTWARE_TOKEN_MFA") {
if (!otpMfaCode) throw new Error("Missing Software MFA Code");
responseParameters.SOFTWARE_TOKEN_MFA_CODE = await otpMfaCode();
} else {
throw new Error(`Unsupported challenge: ${authResponse.ChallengeName}`);
}
Expand Down
3 changes: 3 additions & 0 deletions client/plaintext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function authenticateWithPlaintextPassword({
username,
password,
smsMfaCode,
otpMfaCode,
newPassword,
tokensCb,
statusCb,
Expand All @@ -32,6 +33,7 @@ export function authenticateWithPlaintextPassword({
username: string;
password: string;
smsMfaCode?: () => Promise<string>;
otpMfaCode?: () => Promise<string>;
newPassword?: () => Promise<string>;
tokensCb?: (tokens: TokensFromSignIn) => void | Promise<void>;
statusCb?: (status: BusyState | IdleState) => void;
Expand All @@ -57,6 +59,7 @@ export function authenticateWithPlaintextPassword({
authResponse,
username,
smsMfaCode,
otpMfaCode,
newPassword,
clientMetadata,
abort: abort.signal,
Expand Down
6 changes: 6 additions & 0 deletions client/react/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ function _usePasswordless() {
username,
password,
smsMfaCode,
otpMfaCode,
clientMetadata,
}: {
/**
Expand All @@ -509,13 +510,15 @@ function _usePasswordless() {
username: string;
password: string;
smsMfaCode?: () => Promise<string>;
otpMfaCode?: () => Promise<string>;
clientMetadata?: Record<string, string>;
}) => {
setLastError(undefined);
const signinIn = authenticateWithSRP({
username,
password,
smsMfaCode,
otpMfaCode,
clientMetadata,
statusCb: setSigninInStatus,
tokensCb: (tokens) => storeTokens(tokens).then(() => setTokens(tokens)),
Expand All @@ -528,6 +531,7 @@ function _usePasswordless() {
username,
password,
smsMfaCode,
otpMfaCode,
clientMetadata,
}: {
/**
Expand All @@ -536,13 +540,15 @@ function _usePasswordless() {
username: string;
password: string;
smsMfaCode?: () => Promise<string>;
otpMfaCode?: () => Promise<string>;
clientMetadata?: Record<string, string>;
}) => {
setLastError(undefined);
const signinIn = authenticateWithPlaintextPassword({
username,
password,
smsMfaCode,
otpMfaCode,
clientMetadata,
statusCb: setSigninInStatus,
tokensCb: (tokens) => storeTokens(tokens).then(() => setTokens(tokens)),
Expand Down
3 changes: 3 additions & 0 deletions client/srp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ export function authenticateWithSRP({
username,
password,
smsMfaCode,
otpMfaCode,
newPassword,
customChallengeAnswer,
authflow = "USER_SRP_AUTH",
Expand All @@ -268,6 +269,7 @@ export function authenticateWithSRP({
username: string;
password: string;
smsMfaCode?: () => Promise<string>;
otpMfaCode?: () => Promise<string>;
newPassword?: () => Promise<string>;
customChallengeAnswer?: () => Promise<string>;
authflow?: "USER_SRP_AUTH" | "CUSTOM_AUTH";
Expand Down Expand Up @@ -335,6 +337,7 @@ export function authenticateWithSRP({
authResponse: authResult,
username,
smsMfaCode,
otpMfaCode,
newPassword,
customChallengeAnswer,
clientMetadata,
Expand Down

0 comments on commit 85cdf58

Please sign in to comment.