diff --git a/app/forms/idp/create.tsx b/app/forms/idp/create.tsx
index 95f9d13d7..c7c1e1578 100644
--- a/app/forms/idp/create.tsx
+++ b/app/forms/idp/create.tsx
@@ -21,8 +21,10 @@ import { useSiloSelector } from '~/hooks/use-params'
import { addToast } from '~/stores/toast'
import { Checkbox } from '~/ui/lib/Checkbox'
import { FormDivider } from '~/ui/lib/Divider'
+import { Message } from '~/ui/lib/Message'
import { SideModal } from '~/ui/lib/SideModal'
import { readBlobAsBase64 } from '~/util/file'
+import { links } from '~/util/links'
import { pb } from '~/util/path-builder'
import { MetadataSourceField, type IdpCreateFormValues } from './shared'
@@ -128,7 +130,35 @@ export function CreateIdpSideModalForm() {
submitError={createIdp.error}
submitLabel="Create provider"
>
-
+
+ Read the{' '}
+
+ Rack Configuration
+ {' '}
+ guide to learn more about setting up an identity provider.
+ >
+ }
+ />
+
+ A short name for the provider in our system. Users will see it in the path to
+ the login page:{' '}
+
+ /login/{silo}/saml/{name.trim() || 'idp-name'}
+
+ >
+ }
+ />
+
+
+ Request signing
{/* We don't bother validating that you have both of these or neither even
though the API requires that because we are going to change the API to
always require both, at which point these become simple `required` fields */}
@@ -186,7 +219,7 @@ export function CreateIdpSideModalForm() {
id="public-cert-file-input"
name="signingKeypair.publicCert"
description="DER-encoded X.509 certificate"
- label="Public cert"
+ label="Public certificate"
control={form.control}
/>
{
diff --git a/test/e2e/silos.e2e.ts b/test/e2e/silos.e2e.ts
index 7f0e3ba0f..4dccf3656 100644
--- a/test/e2e/silos.e2e.ts
+++ b/test/e2e/silos.e2e.ts
@@ -171,6 +171,7 @@ test('Default silo', async ({ page }) => {
page.getByText('Silo viewerFleet viewer'),
])
})
+
test('Identity providers', async ({ page }) => {
await page.goto('/system/silos/maze-war')
@@ -199,21 +200,32 @@ test('Identity providers', async ({ page }) => {
await expect(dialog).toBeVisible()
- const nameField = dialog.getByLabel('Name', { exact: true })
- const acsUrlField = dialog.getByLabel('ACS URL', { exact: true })
+ // test login URL preview in name field description
+ await expect(page.getByText('login page: /login/maze-war/saml/idp-name')).toBeVisible()
+ const nameField = dialog.getByLabel('Name', { exact: true })
await nameField.fill('test-provider')
+
+ // preview updates as you type
+ await expect(
+ page.getByText('login page: /login/maze-war/saml/test-provider')
+ ).toBeVisible()
+
// ACS URL should be populated with generated value
+ const acsUrlField = dialog.getByLabel('ACS URL', { exact: true })
const acsUrl = 'https://maze-war.sys.placeholder/login/maze-war/saml/test-provider'
await expect(acsUrlField).toHaveValue(acsUrl)
+ const acsUrlCheckbox = dialog.getByRole('checkbox', { name: 'Use standard ACS URL' })
+ await expect(acsUrlCheckbox).toBeChecked()
+
// uncheck the box and change the value
- await dialog.getByRole('checkbox', { name: 'Use standard ACS URL' }).click()
+ await acsUrlCheckbox.click()
await acsUrlField.fill('https://example.com')
await expect(acsUrlField).toHaveValue('https://example.com')
// re-check the box and verify that the value is regenerated
- await dialog.getByRole('checkbox', { name: 'Use standard ACS URL' }).click()
+ await acsUrlCheckbox.click()
await expect(acsUrlField).toHaveValue(acsUrl)
await page.getByRole('button', { name: 'Create provider' }).click()