1
0
mirror of https://github.com/pocket-id/pocket-id.git synced 2026-02-12 05:09:00 +00:00

feat: device authorization endpoint (#270)

Co-authored-by: Elias Schneider <login@eliasschneider.com>
This commit is contained in:
Kyle Mendell
2025-04-25 12:14:51 -05:00
committed by GitHub
parent 630327c979
commit 22f7d64bf0
26 changed files with 778 additions and 80 deletions

View File

@@ -1,6 +1,7 @@
import test, { expect } from '@playwright/test';
import { accessTokens, idTokens, oidcClients, refreshTokens, users } from './data';
import { cleanupBackend } from './utils/cleanup.util';
import oidcUtil from './utils/oidc.util';
import passkeyUtil from './utils/passkey.util';
test.beforeEach(cleanupBackend);
@@ -277,3 +278,99 @@ test.describe('Introspection endpoint', () => {
expect(introspectionResponse.status()).toBe(400);
});
});
test('Authorize new client with device authorization flow', async ({ page }) => {
const client = oidcClients.immich;
const userCode = await oidcUtil.getUserCode(page, client.id, client.secret);
await page.goto(`/device?code=${userCode}`);
await expect(page.getByTestId('scopes').getByRole('heading', { name: 'Email' })).toBeVisible();
await expect(page.getByTestId('scopes').getByRole('heading', { name: 'Profile' })).toBeVisible();
await page.getByRole('button', { name: 'Authorize' }).click();
await expect(
page.getByRole('paragraph').filter({ hasText: 'The device has been authorized.' })
).toBeVisible();
});
test('Authorize new client with device authorization flow while not signed in', async ({
page
}) => {
await page.context().clearCookies();
const client = oidcClients.immich;
const userCode = await oidcUtil.getUserCode(page, client.id, client.secret);
await page.goto(`/device?code=${userCode}`);
await (await passkeyUtil.init(page)).addPasskey();
await page.getByRole('button', { name: 'Authorize' }).click();
await expect(page.getByTestId('scopes').getByRole('heading', { name: 'Email' })).toBeVisible();
await expect(page.getByTestId('scopes').getByRole('heading', { name: 'Profile' })).toBeVisible();
await page.getByRole('button', { name: 'Authorize' }).click();
await expect(
page.getByRole('paragraph').filter({ hasText: 'The device has been authorized.' })
).toBeVisible();
});
test('Authorize existing client with device authorization flow', async ({ page }) => {
const client = oidcClients.nextcloud;
const userCode = await oidcUtil.getUserCode(page, client.id, client.secret);
await page.goto(`/device?code=${userCode}`);
await expect(
page.getByRole('paragraph').filter({ hasText: 'The device has been authorized.' })
).toBeVisible();
});
test('Authorize existing client with device authorization flow while not signed in', async ({
page
}) => {
await page.context().clearCookies();
const client = oidcClients.nextcloud;
const userCode = await oidcUtil.getUserCode(page, client.id, client.secret);
await page.goto(`/device?code=${userCode}`);
await (await passkeyUtil.init(page)).addPasskey();
await page.getByRole('button', { name: 'Authorize' }).click();
await expect(
page.getByRole('paragraph').filter({ hasText: 'The device has been authorized.' })
).toBeVisible();
});
test('Authorize client with device authorization flow with invalid code', async ({ page }) => {
await page.goto('/device?code=invalid-code');
await expect(
page.getByRole('paragraph').filter({ hasText: 'Invalid device code.' })
).toBeVisible();
});
test('Authorize new client with device authorization with user group not allowed', async ({
page
}) => {
await page.context().clearCookies();
const client = oidcClients.immich;
const userCode = await oidcUtil.getUserCode(page, client.id, client.secret);
await page.goto(`/device?code=${userCode}`);
await (await passkeyUtil.init(page)).addPasskey('craig');
await page.getByRole('button', { name: 'Authorize' }).click();
await expect(page.getByTestId('scopes').getByRole('heading', { name: 'Email' })).toBeVisible();
await expect(page.getByTestId('scopes').getByRole('heading', { name: 'Profile' })).toBeVisible();
await page.getByRole('button', { name: 'Authorize' }).click();
await expect(
page.getByRole('paragraph').filter({ hasText: "You're not allowed to access this service." })
).toBeVisible();
});