Skip to content

Commit a157e0b

Browse files
committed
Merge remote-tracking branch 'origin/main' into hypeship/render-field-input-mode
2 parents ff624e4 + 150ff2e commit a157e0b

4 files changed

Lines changed: 87 additions & 2 deletions

File tree

‎packages/managed-auth-react/CHANGELOG.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# @onkernel/managed-auth-react
22

3+
## 0.5.2
4+
5+
### Patch Changes
6+
7+
- [#27](https://github.com/kernel/managed-auth-react/pull/27) [`63cac3e`](https://github.com/kernel/managed-auth-react/commit/63cac3efcba043f8762be5b0f54e3dc1680d2cb3) Thanks [@masnwilliams](https://github.com/masnwilliams)! - Render typed reauthentication blockers and rejected authenticator codes with specific recovery guidance.
8+
39
## 0.5.1
410

511
### Patch Changes

‎packages/managed-auth-react/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@onkernel/managed-auth-react",
3-
"version": "0.5.1",
3+
"version": "0.5.2",
44
"description": "React component library for Kernel managed auth — one-component drop-in with a Clerk-style appearance API",
55
"license": "MIT",
66
"author": "Kernel Technologies, Inc.",
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { describe, expect, test } from "bun:test";
2+
import { errorDisplayForCode } from "./StepError";
3+
4+
describe("errorDisplayForCode", () => {
5+
test("renders typed challenge outcomes with context-neutral copy", () => {
6+
const cases = [
7+
["totp_required", "Authenticator code required"],
8+
["sms_code_required", "SMS code required"],
9+
["email_code_required", "Email code required"],
10+
["account_choice_required", "Account selection required"],
11+
["customer_input_required", "Additional input required"],
12+
["external_action_required", "External action required"],
13+
];
14+
15+
for (const [code, title] of cases) {
16+
const display = errorDisplayForCode(code);
17+
expect(display?.title).toBe(title);
18+
expect(display?.description.toLowerCase()).not.toContain("reauth");
19+
}
20+
});
21+
22+
test("does not infer TOTP secret availability", () => {
23+
expect(errorDisplayForCode("totp_required")?.description).toBe(
24+
"An authenticator code is required.",
25+
);
26+
});
27+
28+
test("uses customer-facing copy for additional input", () => {
29+
expect(errorDisplayForCode("customer_input_required")?.description).toBe(
30+
"Additional information is required before login can continue.",
31+
);
32+
});
33+
34+
test("distinguishes a rejected authenticator code from invalid credentials", () => {
35+
const display = errorDisplayForCode("totp_code_rejected");
36+
const invalidCredentials = errorDisplayForCode("credentials_invalid");
37+
38+
expect(display?.title).toBe("Authenticator code rejected");
39+
expect(display?.description).toContain("Try a fresh code");
40+
expect(invalidCredentials).toBeTruthy();
41+
expect(display).not.toEqual(invalidCredentials);
42+
});
43+
});

‎packages/managed-auth-react/src/components/StepError.tsx‎

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,38 @@ const ERROR_DISPLAY: Record<string, { title: string; description: string }> = {
2626
title: "Invalid credentials",
2727
description: "The username or password was not accepted by the website.",
2828
},
29+
totp_required: {
30+
title: "Authenticator code required",
31+
description: "An authenticator code is required.",
32+
},
33+
sms_code_required: {
34+
title: "SMS code required",
35+
description: "A code sent by SMS is required.",
36+
},
37+
email_code_required: {
38+
title: "Email code required",
39+
description: "A code sent by email is required.",
40+
},
41+
account_choice_required: {
42+
title: "Account selection required",
43+
description:
44+
"An account or identity must be selected before login can continue.",
45+
},
46+
customer_input_required: {
47+
title: "Additional input required",
48+
description:
49+
"Additional information is required before login can continue.",
50+
},
51+
external_action_required: {
52+
title: "External action required",
53+
description:
54+
"An external action is required to continue. Check your authenticator app, email, or phone for a verification request.",
55+
},
56+
totp_code_rejected: {
57+
title: "Authenticator code rejected",
58+
description:
59+
"The website rejected the authenticator code. Try a fresh code, or reconnect the account if generated codes keep failing across new code windows.",
60+
},
2961
bot_detected: {
3062
title: "Verification required",
3163
description:
@@ -66,6 +98,10 @@ const ERROR_DISPLAY: Record<string, { title: string; description: string }> = {
6698
},
6799
};
68100

101+
export function errorDisplayForCode(errorCode?: string) {
102+
return errorCode ? ERROR_DISPLAY[errorCode] : undefined;
103+
}
104+
69105
function extractErrorText(raw: string): string {
70106
try {
71107
const parsed = JSON.parse(raw);
@@ -92,7 +128,7 @@ export function StepError({
92128
const siteName = extractDomainName(targetDomain);
93129
const [showDetails, setShowDetails] = useState(false);
94130

95-
const display = errorCode ? ERROR_DISPLAY[errorCode] : undefined;
131+
const display = errorDisplayForCode(errorCode);
96132
const title = display?.title ?? l.errorTitle;
97133
const description = display?.description ?? l.errorGenericMessage;
98134

0 commit comments

Comments
 (0)