Skip to content

Conversation

@devdattatalele
Copy link
Contributor

This pull request adds support for PocketID as an OAuth provider in Windmill's SSO configuration.

PocketID is a lightweight, self-hosted authentication solution that uses passkeys (WebAuthn/FIDO2) for passwordless authentication with built-in OIDC support.

Changes

Added PocketID OAuth provider configuration component following established patterns from existing providers like Keycloak, Authelia, and Kanidm. The implementation includes a settings component for administrators to configure PocketID base URL, client credentials, and custom display name. The component properly handles OIDC endpoints for authorization, token exchange, and user information retrieval.

Fixed component integration by adding the PocketID icon system and ensuring the component uses the standard IconedResourceType pattern consistent with other OAuth providers.

Testing

Tested locally using Docker environment. The PocketID toggle now appears correctly in SSO settings between existing OAuth providers. Configuration can be saved and persists correctly in workspace settings.

Closes #5678

devdattatalele and others added 3 commits December 8, 2025 15:40
- Implements PocketIdSetting.svelte following Keycloak pattern
- Configures OIDC endpoints for Pocket-ID (/authorize, /api/oidc/*)
- Supports standard OIDC scopes (openid, profile, email)
- Uses passkey-only authentication via Pocket-ID

Refs windmill-labs#5678
- Import PocketIdSetting component
- Add Pocket-ID to provider list in SSO tab
- Update exclusion filter to prevent duplicate custom entries

Refs windmill-labs#5678
- Create PocketIdIcon.svelte component with user profile icon
- Register pocket-id in APP_TO_ICON_COMPONENT mapping
- Fix PocketIdSetting to use IconedResourceType pattern matching other OAuth providers

This resolves the issue where PocketID toggle was not appearing in SSO settings.

Refs windmill-labs#5678
Comment on lines 1 to 68
<script lang="ts">
import IconedResourceType from './IconedResourceType.svelte'
import Toggle from './Toggle.svelte'

export let value: any

$: enabled = value != undefined

let org = ''

$: changeOrg(org)

function changeOrg(org) {
if (value) {
value = {
...value,
connect_config: {
auth_url: `${org}/authorize`,
token_url: `${org}/api/oidc/token`,
scopes: ['openid', 'profile', 'email']
},
login_config: {
auth_url: `${org}/authorize`,
token_url: `${org}/api/oidc/token`,
userinfo_url: `${org}/api/oidc/userinfo`,
scopes: ['openid', 'profile', 'email']
}
}
}
}
</script>

<div class="flex flex-col gap-1">
<label class="text-xs font-semibold text-emphasis flex gap-4 items-center"
><div class="w-[120px]"><IconedResourceType name={'pocket-id'} after={true} /></div><Toggle
checked={enabled}
on:change={(e) => {
if (e.detail) {
value = { id: '', secret: '' }
} else {
value = undefined
}
}}
/></label
>
{#if enabled}
<div class="border rounded p-2">
<label class="block pb-2">
<span class="text-primary font-semibold text-sm"
>Pocket-ID Base URL ({'POCKET_ID_URL/authorize'})</span
>
<input type="text" placeholder="https://id.example.com" bind:value={org} />
</label>
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">Custom Name</span>
<input type="text" placeholder="Pocket ID" bind:value={value['display_name']} />
</label>
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">Client Id</span>
<input type="text" placeholder="Client Id" bind:value={value['id']} />
</label>
<label class="block pb-2">
<span class="text-primary font-semibold text-sm">Client Secret </span>
<input type="text" placeholder="Client Secret" bind:value={value['secret']} />
</label>
</div>
{/if}
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should use svelte 5 here :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rubenfiszel Migrated to Svelte 5 runes syntax. Also implemented base URL pre-population from existing config when editing saved settings.


$: enabled = value != undefined

let org = ''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider initializing the org variable from the existing configuration (e.g. from value.connect_config.auth_url) so that the base URL input is pre-populated when editing saved settings.

- Use $props() with $bindable() for reactive prop binding
- Use $state() for local reactive state
- Use $derived() for computed values
- Use $effect() for reactive side effects
- Replace on:change with onchange event handler
- Pre-populate base URL from existing config when editing
- Clean up bracket notation to dot notation for value properties

Addresses reviewer feedback
@rubenfiszel
Copy link
Contributor

I think you missed oauth_connect.json + pocket-id => pocket_id or pockerid (need to match resource type)

Change identifier from 'pocket-id' to 'pocketid' to match Windmill's naming convention.
No OAuth provider uses hyphens - all custom SSO providers (keycloak, authentik, authelia,
kanidm, zitadel) use no separator.

Changes:
- AuthSettings.svelte: oauths['pocket-id'] → oauths['pocketid'] (2 locations)
- PocketIdSetting.svelte: name={'pocket-id'} → name={'pocketid'}
- icons/index.ts: 'pocket-id': PocketIdIcon → pocketid: PocketIdIcon

Note: PocketID does not need oauth_connect.json entry as it's a custom SSO provider
with user-configured endpoints, similar to Keycloak/Authentik.

Addresses reviewer feedback
@devdattatalele
Copy link
Contributor Author

pocketid works like the other custom sso providers (e.g. Keycloak), also endpoints are supplied by the user, so it doesn’t need an entry in oauth_connect.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feature: Add Pocket-ID support to OAuth

2 participants