From 71f62b9d895d5d146aba1fe5d86baefd9cf4bd2a Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Sun, 2 Apr 2023 21:59:38 +0200 Subject: [PATCH] tmp --- packages/backend/package.json | 5 +- .../src/server/oauth/OAuth2ProviderService.ts | 2 +- packages/backend/test/e2e/oauth.ts | 94 +++++++++++++++++++ pnpm-lock.yaml | 60 ++++++++++++ 4 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 packages/backend/test/e2e/oauth.ts diff --git a/packages/backend/package.json b/packages/backend/package.json index 2e4f2b532..584e57c23 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -127,6 +127,7 @@ "otpauth": "9.1.2", "parse5": "7.1.2", "pg": "8.11.0", + "pkce-challenge": "^3.1.0", "probe-image-size": "7.2.3", "promise-limit": "2.7.0", "pug": "3.0.2", @@ -202,6 +203,7 @@ "@types/sanitize-html": "2.9.0", "@types/semver": "7.5.0", "@types/sharp": "0.32.0", + "@types/simple-oauth2": "^5.0.4", "@types/sinonjs__fake-timers": "8.1.2", "@types/tinycolor2": "1.4.3", "@types/tmp": "0.2.3", @@ -219,6 +221,7 @@ "eslint-plugin-import": "2.27.5", "execa": "6.1.0", "jest": "29.5.0", - "jest-mock": "29.5.0" + "jest-mock": "29.5.0", + "simple-oauth2": "^5.0.0" } } diff --git a/packages/backend/src/server/oauth/OAuth2ProviderService.ts b/packages/backend/src/server/oauth/OAuth2ProviderService.ts index 4a4080295..ffe2137cf 100644 --- a/packages/backend/src/server/oauth/OAuth2ProviderService.ts +++ b/packages/backend/src/server/oauth/OAuth2ProviderService.ts @@ -433,7 +433,7 @@ export class OAuth2ProviderService { fastify.get<{ Querystring: OAuthRequestQuery }>('/oauth/authorize', async (request, reply) => { console.log('HIT /oauth/authorize', request.query); const oauth2 = (request.raw as any).oauth2 as (OAuth2 | undefined); - console.log(oauth2); + console.log(oauth2, request.raw.session); if (request.query.response_type !== 'code') { throw new Error('`response_type` parameter must be set as "code"'); diff --git a/packages/backend/test/e2e/oauth.ts b/packages/backend/test/e2e/oauth.ts new file mode 100644 index 000000000..9d7050c2c --- /dev/null +++ b/packages/backend/test/e2e/oauth.ts @@ -0,0 +1,94 @@ +process.env.NODE_ENV = 'test'; + +import * as assert from 'assert'; +import { port, signup, startServer } from '../utils.js'; +import type { INestApplicationContext } from '@nestjs/common'; +import { AuthorizationCode } from 'simple-oauth2'; +import pkceChallenge from 'pkce-challenge'; +import { JSDOM } from 'jsdom'; + +describe('OAuth', () => { + let app: INestApplicationContext; + + let alice: any; + const clientPort = port + 1; + + beforeAll(async () => { + app = await startServer(); + alice = await signup({ username: 'alice' }); + // fastify = Fastify(); + }, 1000 * 60 * 2); + + afterAll(async () => { + await app.close(); + }); + + test('Full flow', async () => { + const { code_challenge, code_verifier } = pkceChallenge.default(128); + + const client = new AuthorizationCode({ + client: { + id: `http://127.0.0.1:${clientPort}/`, + }, + auth: { + tokenHost: `http://127.0.0.1:${port}`, + tokenPath: '/oauth/token', + authorizePath: '/oauth/authorize', + }, + options: { + authorizationMethod: 'body', + }, + }); + + const redirect_uri = `http://127.0.0.1:${clientPort}/redirect`; + + const authEndpoint = client.authorizeURL({ + redirect_uri, + scope: 'write:notes', + state: 'state', + code_challenge, + code_challenge_method: 'S256', + }); + const response = await fetch(authEndpoint); + assert.strictEqual(response.status, 200); + const cookie = response.headers.get('set-cookie'); + assert.ok(cookie?.startsWith('connect.sid=')); + + const fragment = JSDOM.fragment(await response.text()); + const transactionId = fragment.querySelector('meta[name="misskey:oauth:transaction-id"]')?.content; + assert.strictEqual(typeof transactionId, 'string'); + + const formData = new FormData(); + formData.append('transaction_id', transactionId!); + formData.append('login_token', alice.token); + const decisionResponse = await fetch(`http://127.0.0.1:${port}/oauth/decision`, { + method: 'post', + body: new URLSearchParams({ + transaction_id: transactionId!, + login_token: alice.token, + }), + redirect: 'manual', + headers: { + 'content-type': 'application/x-www-form-urlencoded', + cookie: cookie!, + }, + }); + assert.strictEqual(decisionResponse.status, 302); + assert.ok(decisionResponse.headers.has('location')); + + const location = new URL(decisionResponse.headers.get('location')!); + assert.strictEqual(location.origin + location.pathname, redirect_uri); + + assert.ok(location.searchParams.has('code')); + assert.strictEqual(location.searchParams.get('state'), 'state'); + + const token = await client.getToken({ + code: location.searchParams.get('code')!, + redirect_uri, + code_verifier, + }); + assert.strictEqual(typeof token.token.access_token, 'string'); + assert.strictEqual(typeof token.token.refresh_token, 'string'); + assert.strictEqual(token.token.token_type, 'Bearer'); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2c21152d5..3ab71a327 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -296,6 +296,9 @@ importers: pg: specifier: 8.11.0 version: 8.11.0 + pkce-challenge: + specifier: ^3.1.0 + version: 3.1.0 probe-image-size: specifier: 7.2.3 version: 7.2.3 @@ -598,6 +601,9 @@ importers: '@types/sharp': specifier: 0.32.0 version: 0.32.0 + '@types/simple-oauth2': + specifier: ^5.0.4 + version: 5.0.4 '@types/sinonjs__fake-timers': specifier: 8.1.2 version: 8.1.2 @@ -652,6 +658,9 @@ importers: jest-mock: specifier: 29.5.0 version: 29.5.0 + simple-oauth2: + specifier: ^5.0.0 + version: 5.0.0 packages/frontend: dependencies: @@ -4934,6 +4943,24 @@ packages: hashlru: 2.3.0 dev: false + /@hapi/boom@10.0.1: + resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==} + dependencies: + '@hapi/hoek': 11.0.2 + dev: true + + /@hapi/bourne@3.0.0: + resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} + dev: true + + /@hapi/hoek@10.0.1: + resolution: {integrity: sha512-CvlW7jmOhWzuqOqiJQ3rQVLMcREh0eel4IBnxDx2FAcK8g7qoJRQK4L1CPBASoCY6y8e6zuCy3f2g+HWdkzcMw==} + dev: true + + /@hapi/hoek@11.0.2: + resolution: {integrity: sha512-aKmlCO57XFZ26wso4rJsW4oTUnrgTFw2jh3io7CAtO9w4UltBNwRXvXIVzzyfkaaLRo3nluP/19msA8vDUUuKw==} + dev: true + /@hapi/hoek@9.3.0: resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} dev: true @@ -4944,6 +4971,14 @@ packages: '@hapi/hoek': 9.3.0 dev: true + /@hapi/wreck@18.0.1: + resolution: {integrity: sha512-OLHER70+rZxvDl75xq3xXOfd3e8XIvz8fWY0dqg92UvhZ29zo24vQgfqgHSYhB5ZiuFpSLeriOisAlxAo/1jWg==} + dependencies: + '@hapi/boom': 10.0.1 + '@hapi/bourne': 3.0.0 + '@hapi/hoek': 11.0.2 + dev: true + /@humanwhocodes/config-array@0.11.10: resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==} engines: {node: '>=10.10.0'} @@ -7964,6 +7999,10 @@ packages: sharp: 0.32.1 dev: true + /@types/simple-oauth2@5.0.4: + resolution: {integrity: sha512-4SvTfmAa1fGUa1d07j9vIiC4o92bGh0ihPXmtS05udMMmNwVIaU2nZ706cC4wI8cJxOlHD4P/d5tzqvWYd+KxA==} + dev: true + /@types/sinon@10.0.13: resolution: {integrity: sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ==} dependencies: @@ -10609,6 +10648,10 @@ packages: shebang-command: 2.0.0 which: 2.0.2 + /crypto-js@4.1.1: + resolution: {integrity: sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==} + dev: false + /crypto-random-string@2.0.0: resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} engines: {node: '>=8'} @@ -17096,6 +17139,12 @@ packages: engines: {node: '>= 6'} dev: true + /pkce-challenge@3.1.0: + resolution: {integrity: sha512-bQ/0XPZZ7eX+cdAkd61uYWpfMhakH3NeteUF1R8GNa+LMqX8QFAkbCLqq+AYAns1/ueACBu/BMWhrlKGrdvGZg==} + dependencies: + crypto-js: 4.1.1 + dev: false + /pkg-dir@3.0.0: resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==} engines: {node: '>=6'} @@ -18890,6 +18939,17 @@ packages: once: 1.4.0 simple-concat: 1.0.1 + /simple-oauth2@5.0.0: + resolution: {integrity: sha512-8291lo/z5ZdpmiOFzOs1kF3cxn22bMj5FFH+DNUppLJrpoIlM1QnFiE7KpshHu3J3i21TVcx4yW+gXYjdCKDLQ==} + dependencies: + '@hapi/hoek': 10.0.1 + '@hapi/wreck': 18.0.1 + debug: 4.3.4(supports-color@8.1.1) + joi: 17.7.0 + transitivePeerDependencies: + - supports-color + dev: true + /simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} dependencies: