Skip to content

Commit 4c9e7e5

Browse files
committed
support multiple OTP sources
1 parent d3803ef commit 4c9e7e5

2 files changed

Lines changed: 44 additions & 2 deletions

File tree

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "id.helpwave.de",
3-
"version": "0.1.4",
3+
"version": "0.1.5",
44
"repository": {
55
"type": "git",
66
"url": "git://github.com/helpwave/id.helpwave.de.git"

‎src/login/pages/LoginOtp.tsx‎

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useState } from 'react'
2-
import { Button, Input, FormFieldLayout } from '@helpwave/hightide'
2+
import { Button, Input, FormFieldLayout, SelectUncontrolled, SelectOption } from '@helpwave/hightide'
33
import type { KcContext } from '../KcContext'
44
import { useI18n } from '../i18n'
55
import Template from 'keycloakify/login/Template'
@@ -14,13 +14,19 @@ export default function LoginOtp({ kcContext }: LoginOtpProps) {
1414
const { i18n } = useI18n({ kcContext })
1515
const t = useTranslation()
1616
const [otp, setOtp] = useState('')
17+
const [selectedAuthExecId, setSelectedAuthExecId] = useState(
18+
kcContext.auth?.authenticationSelections?.[0]?.authExecId ?? ''
19+
)
1720

1821
const otpError = kcContext.messagesPerField?.existsError('otp')
1922
? kcContext.messagesPerField.get('otp')
2023
: undefined
2124

2225
const message = kcContext.message
2326

27+
const authenticationSelections = kcContext.auth?.authenticationSelections
28+
const hasMultipleSources = authenticationSelections && authenticationSelections.length > 1
29+
2430
return (
2531
<Template
2632
kcContext={kcContext}
@@ -57,6 +63,42 @@ export default function LoginOtp({ kcContext }: LoginOtpProps) {
5763
method="post"
5864
style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}
5965
>
66+
{hasMultipleSources ? (
67+
<>
68+
<input
69+
type="hidden"
70+
name="authExecId"
71+
value={selectedAuthExecId}
72+
/>
73+
<FormFieldLayout
74+
label={t('selectAuthenticatorTitle')}
75+
required
76+
>
77+
{({ id, ariaAttributes }) => (
78+
<SelectUncontrolled
79+
id={id}
80+
value={selectedAuthExecId}
81+
onValueChange={(value) => setSelectedAuthExecId(value)}
82+
onEditComplete={() => {}}
83+
{...ariaAttributes}
84+
>
85+
{authenticationSelections.map((selection) => (
86+
<SelectOption key={selection.authExecId} value={selection.authExecId}>
87+
{selection.displayName}
88+
</SelectOption>
89+
))}
90+
</SelectUncontrolled>
91+
)}
92+
</FormFieldLayout>
93+
</>
94+
) : authenticationSelections && authenticationSelections.length === 1 ? (
95+
<input
96+
type="hidden"
97+
name="authExecId"
98+
value={authenticationSelections[0].authExecId}
99+
/>
100+
) : null}
101+
60102
<FormFieldLayout
61103
label={t('otp')}
62104
invalidDescription={otpError}

0 commit comments

Comments
 (0)