mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-07-16 04:03:47 +03:00
feat: prompt admin with PKCE client support hint (#1499)
Co-authored-by: james <james@goldfish.net> Co-authored-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com> Co-authored-by: Elias Schneider <login@eliasschneider.com> Co-authored-by: Kyle Mendell <kmendell@ofkm.us>
This commit is contained in:
@@ -530,5 +530,7 @@
|
||||
"emails_verified_by_default_description": "When enabled, users' email addresses will be marked as verified by default upon signup or when their email address is changed.",
|
||||
"user_has_no_passkeys_yet": "This user has no passkeys yet.",
|
||||
"replay_protection": "Replay Protection",
|
||||
"replay_protection_description": "If enabled the provided token can only be used once. If your provider uses the same token multiple times, you may need to disable this option."
|
||||
"replay_protection_description": "If enabled the provided token can only be used once. If your provider uses the same token multiple times, you may need to disable this option.",
|
||||
"pkce_supported_client_title": "This client supports PKCE",
|
||||
"pkce_supported_client_description": "This client supports Proof Key for Code Exchange (PKCE). PKCE is a security feature that helps protect against certain attacks during the OAuth 2.0 authorization process. It's recommended to enable it."
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ export type OidcClient = OidcClientMetaData & {
|
||||
credentials?: OidcClientCredentials;
|
||||
launchURL?: string;
|
||||
isGroupRestricted: boolean;
|
||||
pkceSupported: boolean;
|
||||
};
|
||||
|
||||
export type OidcClientWithAllowedUserGroups = OidcClient & {
|
||||
@@ -42,7 +43,7 @@ export type OidcClientWithAllowedUserGroupsCount = OidcClient & {
|
||||
allowedUserGroupsCount: number;
|
||||
};
|
||||
|
||||
export type OidcClientUpdate = Omit<OidcClient, 'id' | 'logoURL' | 'hasLogo' | 'hasDarkLogo'>;
|
||||
export type OidcClientUpdate = Omit<OidcClient, 'id' | 'logoURL' | 'hasLogo' | 'hasDarkLogo' | 'pkceSupported'>;
|
||||
export type OidcClientCreate = OidcClientUpdate & {
|
||||
id?: string;
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import CollapsibleCard from '$lib/components/collapsible-card.svelte';
|
||||
import { openConfirmDialog } from '$lib/components/confirm-dialog';
|
||||
import CopyToClipboard from '$lib/components/copy-to-clipboard.svelte';
|
||||
import * as Alert from '$lib/components/ui/alert';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import * as Card from '$lib/components/ui/card';
|
||||
import * as Field from '$lib/components/ui/field';
|
||||
@@ -16,7 +17,7 @@
|
||||
import type { ScimServiceProviderCreate } from '$lib/types/scim.type';
|
||||
import { cachedOidcClientLogo } from '$lib/utils/cached-image-util';
|
||||
import { axiosErrorToast } from '$lib/utils/error-util';
|
||||
import { LucideChevronLeft, LucideRefreshCcw } from '@lucide/svelte';
|
||||
import { LucideChevronLeft, LucideInfo, LucideRefreshCcw } from '@lucide/svelte';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { slide } from 'svelte/transition';
|
||||
import { backNavigate } from '../../users/navigate-back-util';
|
||||
@@ -90,6 +91,9 @@
|
||||
if (updatedClient.darkLogo !== undefined || updatedClient.darkLogoUrl !== undefined) {
|
||||
client.hasDarkLogo = updatedClient.darkLogo !== null || !!updatedClient.darkLogoUrl;
|
||||
}
|
||||
if (updatedClient.pkceEnabled) {
|
||||
client.pkceEnabled = updatedClient.pkceEnabled;
|
||||
}
|
||||
toast.success(m.oidc_client_updated_successfully());
|
||||
})
|
||||
.catch((e) => {
|
||||
@@ -209,11 +213,22 @@
|
||||
>
|
||||
{/snippet}
|
||||
|
||||
{#if client.pkceSupported && !client.pkceEnabled}
|
||||
<Alert.Root variant="info">
|
||||
<LucideInfo class="size-4" />
|
||||
<Alert.Title>{m.pkce_supported_client_title()}</Alert.Title>
|
||||
<Alert.Description>
|
||||
{m.pkce_supported_client_description()}
|
||||
</Alert.Description>
|
||||
</Alert.Root>
|
||||
{/if}
|
||||
|
||||
<div>
|
||||
<button type="button" class="text-muted-foreground flex text-sm" onclick={backNavigation.go}
|
||||
><LucideChevronLeft class="size-5" /> {m.back()}</button
|
||||
>
|
||||
</div>
|
||||
|
||||
<Card.Root>
|
||||
<Card.Header>
|
||||
<Card.Title>{client.name}</Card.Title>
|
||||
|
||||
@@ -57,7 +57,8 @@
|
||||
federatedIdentities: existingClient?.credentials?.federatedIdentities || []
|
||||
},
|
||||
logoUrl: '',
|
||||
darkLogoUrl: ''
|
||||
darkLogoUrl: '',
|
||||
pkceSupported: existingClient?.pkceSupported || false
|
||||
};
|
||||
|
||||
const formSchema = z.object({
|
||||
@@ -98,6 +99,8 @@
|
||||
type FormSchema = typeof formSchema;
|
||||
const { inputs, errors, ...form } = createForm<FormSchema>(formSchema, client);
|
||||
|
||||
const pkcePromptNeeded = $derived(!$inputs.pkceEnabled.value && client.pkceSupported);
|
||||
|
||||
async function onSubmit() {
|
||||
const data = form.validate();
|
||||
if (!data) return;
|
||||
@@ -215,13 +218,19 @@
|
||||
}}
|
||||
bind:checked={$inputs.isPublic.value}
|
||||
/>
|
||||
<SwitchWithLabel
|
||||
id="pkce"
|
||||
label={m.pkce()}
|
||||
description={m.proof_key_code_exchange_is_a_security_feature_to_prevent_csrf_and_authorization_code_interception_attacks()}
|
||||
disabled={$inputs.isPublic.value}
|
||||
bind:checked={$inputs.pkceEnabled.value}
|
||||
/>
|
||||
<div
|
||||
class="rounded-lg transition-all duration-200"
|
||||
class:[&_[data-switch-root]]:ring-2={pkcePromptNeeded}
|
||||
class:[&_[data-switch-root]]:ring-blue-500={pkcePromptNeeded}
|
||||
>
|
||||
<SwitchWithLabel
|
||||
id="pkce"
|
||||
label={m.pkce()}
|
||||
description={m.proof_key_code_exchange_is_a_security_feature_to_prevent_csrf_and_authorization_code_interception_attacks()}
|
||||
disabled={$inputs.isPublic.value}
|
||||
bind:checked={$inputs.pkceEnabled.value}
|
||||
/>
|
||||
</div>
|
||||
<SwitchWithLabel
|
||||
id="requires-reauthentication"
|
||||
label={m.requires_reauthentication()}
|
||||
|
||||
Reference in New Issue
Block a user