mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-02-09 03:49:19 +00:00
feat: device authorization endpoint (#270)
Co-authored-by: Elias Schneider <login@eliasschneider.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
import Logo from '../logo.svelte';
|
||||
import HeaderAvatar from './header-avatar.svelte';
|
||||
|
||||
const authUrls = [/^\/authorize$/, /^\/login(?:\/.*)?$/, /^\/logout$/];
|
||||
const authUrls = [/^\/authorize$/, /^\/device$/, /^\/login(?:\/.*)?$/, /^\/logout$/];
|
||||
|
||||
let isAuthPage = $derived(
|
||||
!page.error && authUrls.some((pattern) => pattern.test(page.url.pathname))
|
||||
|
||||
13
frontend/src/lib/components/scope-item.svelte
Normal file
13
frontend/src/lib/components/scope-item.svelte
Normal file
@@ -0,0 +1,13 @@
|
||||
<script lang="ts">
|
||||
export let icon: ConstructorOfATypedSvelteComponent;
|
||||
export let name: string;
|
||||
export let description: string;
|
||||
</script>
|
||||
|
||||
<div class="flex items-center">
|
||||
<div class="mr-5 rounded-lg bg-muted p-2"><svelte:component this={icon} /></div>
|
||||
<div class="text-start">
|
||||
<h3 class="font-semibold">{name}</h3>
|
||||
<p class="text-sm text-muted-foreground">{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
27
frontend/src/lib/components/scope-list.svelte
Normal file
27
frontend/src/lib/components/scope-list.svelte
Normal file
@@ -0,0 +1,27 @@
|
||||
<script lang="ts">
|
||||
import { m } from '$lib/paraglide/messages';
|
||||
import { LucideMail, LucideUser, LucideUsers } from 'lucide-svelte';
|
||||
import ScopeItem from './scope-item.svelte';
|
||||
|
||||
let { scope }: { scope: string } = $props();
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-3" data-testid="scopes">
|
||||
{#if scope!.includes('email')}
|
||||
<ScopeItem icon={LucideMail} name={m.email()} description={m.view_your_email_address()} />
|
||||
{/if}
|
||||
{#if scope!.includes('profile')}
|
||||
<ScopeItem
|
||||
icon={LucideUser}
|
||||
name={m.profile()}
|
||||
description={m.view_your_profile_information()}
|
||||
/>
|
||||
{/if}
|
||||
{#if scope!.includes('groups')}
|
||||
<ScopeItem
|
||||
icon={LucideUsers}
|
||||
name={m.groups()}
|
||||
description={m.view_the_groups_you_are_a_member_of()}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1,5 +1,6 @@
|
||||
import type {
|
||||
AuthorizeResponse,
|
||||
OidcDeviceCodeInfo,
|
||||
OidcClient,
|
||||
OidcClientCreate,
|
||||
OidcClientMetaData,
|
||||
@@ -8,6 +9,7 @@ import type {
|
||||
import type { Paginated, SearchPaginationSortRequest } from '$lib/types/pagination.type';
|
||||
import APIService from './api-service';
|
||||
|
||||
|
||||
class OidcService extends APIService {
|
||||
async authorize(
|
||||
clientId: string,
|
||||
@@ -92,6 +94,15 @@ class OidcService extends APIService {
|
||||
const res = await this.api.put(`/oidc/clients/${id}/allowed-user-groups`, { userGroupIds });
|
||||
return res.data as OidcClientWithAllowedUserGroups;
|
||||
}
|
||||
|
||||
async verifyDeviceCode(userCode: string) {
|
||||
return await this.api.post(`/oidc/device/verify?code=${userCode}`);
|
||||
}
|
||||
|
||||
async getDeviceCodeInfo(userCode: string): Promise<OidcDeviceCodeInfo> {
|
||||
const response = await this.api.get(`/oidc/device/info?code=${userCode}`);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
export default OidcService;
|
||||
|
||||
@@ -23,6 +23,12 @@ export type OidcClientCreateWithLogo = OidcClientCreate & {
|
||||
logo: File | null | undefined;
|
||||
};
|
||||
|
||||
export type OidcDeviceCodeInfo = {
|
||||
scope: string;
|
||||
authorizationRequired: boolean;
|
||||
client: OidcClientMetaData;
|
||||
};
|
||||
|
||||
export type AuthorizeResponse = {
|
||||
code: string;
|
||||
callbackURL: string;
|
||||
|
||||
Reference in New Issue
Block a user