From 7f3195774fce9fafdc8235462063e879f04ac396 Mon Sep 17 00:00:00 2001 From: SamTV12345 <40429738+samtv12345@users.noreply.github.com> Date: Sat, 23 Mar 2024 07:38:23 +0100 Subject: [PATCH] Added oauth provider. --- src/ep.json | 6 +++ src/node/security/OAuth2Provider.ts | 60 +++++++++++++++++++++++++++++ src/node/security/OAuth2User.ts | 5 +++ src/node/security/OIDCAdapter.ts | 41 ++++++++++++++++++++ src/package.json | 6 ++- 5 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 src/node/security/OAuth2Provider.ts create mode 100644 src/node/security/OAuth2User.ts create mode 100644 src/node/security/OIDCAdapter.ts diff --git a/src/ep.json b/src/ep.json index f6d41e203..95cb4135e 100644 --- a/src/ep.json +++ b/src/ep.json @@ -45,6 +45,12 @@ "expressPreSession": "ep_etherpad-lite/node/hooks/express/specialpages" } }, + { + "name": "oauth2", + "hooks": { + "expressCreateServer": "ep_etherpad-lite/node/security/OAuth2Provider" + } + }, { "name": "padurlsanitize", "hooks": { diff --git a/src/node/security/OAuth2Provider.ts b/src/node/security/OAuth2Provider.ts new file mode 100644 index 000000000..266a1a9cf --- /dev/null +++ b/src/node/security/OAuth2Provider.ts @@ -0,0 +1,60 @@ +import {ArgsExpressType} from "../types/ArgsExpressType"; +import Provider, {Configuration} from 'oidc-provider'; +import {OIDCAdapter} from "./OIDCAdapter"; + +const configuration: Configuration = { + // refer to the documentation for other available configuration + clients: [{ + grant_types: ["refresh_token", "authorization_code"], + client_id: 'foo', + client_secret: 'bar', + application_type: 'web', + redirect_uris: ['http://localhost:9001/test'], + }], + cookies: { + keys: ['some secret key', 'and also the old rotated away some time ago', 'and one more'], + }, + claims: { + address: ['address'], + email: ['email', 'email_verified'], + phone: ['phone_number', 'phone_number_verified'], + profile: ['birthdate', 'family_name', 'gender', 'given_name', 'locale', 'middle_name', 'name', + 'nickname', 'picture', 'preferred_username', 'profile', 'updated_at', 'website', 'zoneinfo'], + }, + features: { + devInteractions: { enabled: false }, // defaults to true + + deviceFlow: { enabled: true }, // defaults to false + revocation: { enabled: true }, // defaults to false + }, + adapter: OIDCAdapter, + jwks: { + keys: [ + { + d: 'VEZOsY07JTFzGTqv6cC2Y32vsfChind2I_TTuvV225_-0zrSej3XLRg8iE_u0-3GSgiGi4WImmTwmEgLo4Qp3uEcxCYbt4NMJC7fwT2i3dfRZjtZ4yJwFl0SIj8TgfQ8ptwZbFZUlcHGXZIr4nL8GXyQT0CK8wy4COfmymHrrUoyfZA154ql_OsoiupSUCRcKVvZj2JHL2KILsq_sh_l7g2dqAN8D7jYfJ58MkqlknBMa2-zi5I0-1JUOwztVNml_zGrp27UbEU60RqV3GHjoqwI6m01U7K0a8Q_SQAKYGqgepbAYOA-P4_TLl5KC4-WWBZu_rVfwgSENwWNEhw8oQ', + dp: 'E1Y-SN4bQqX7kP-bNgZ_gEv-pixJ5F_EGocHKfS56jtzRqQdTurrk4jIVpI-ZITA88lWAHxjD-OaoJUh9Jupd_lwD5Si80PyVxOMI2xaGQiF0lbKJfD38Sh8frRpgelZVaK_gm834B6SLfxKdNsP04DsJqGKktODF_fZeaGFPH0', + dq: 'F90JPxevQYOlAgEH0TUt1-3_hyxY6cfPRU2HQBaahyWrtCWpaOzenKZnvGFZdg-BuLVKjCchq3G_70OLE-XDP_ol0UTJmDTT-WyuJQdEMpt_WFF9yJGoeIu8yohfeLatU-67ukjghJ0s9CBzNE_LrGEV6Cup3FXywpSYZAV3iqc', + e: 'AQAB', + kty: 'RSA', + n: 'xwQ72P9z9OYshiQ-ntDYaPnnfwG6u9JAdLMZ5o0dmjlcyrvwQRdoFIKPnO65Q8mh6F_LDSxjxa2Yzo_wdjhbPZLjfUJXgCzm54cClXzT5twzo7lzoAfaJlkTsoZc2HFWqmcri0BuzmTFLZx2Q7wYBm0pXHmQKF0V-C1O6NWfd4mfBhbM-I1tHYSpAMgarSm22WDMDx-WWI7TEzy2QhaBVaENW9BKaKkJklocAZCxk18WhR0fckIGiWiSM5FcU1PY2jfGsTmX505Ub7P5Dz75Ygqrutd5tFrcqyPAtPTFDk8X1InxkkUwpP3nFU5o50DGhwQolGYKPGtQ-ZtmbOfcWQ', + p: '5wC6nY6Ev5FqcLPCqn9fC6R9KUuBej6NaAVOKW7GXiOJAq2WrileGKfMc9kIny20zW3uWkRLm-O-3Yzze1zFpxmqvsvCxZ5ERVZ6leiNXSu3tez71ZZwp0O9gys4knjrI-9w46l_vFuRtjL6XEeFfHEZFaNJpz-lcnb3w0okrbM', + q: '3I1qeEDslZFB8iNfpKAdWtz_Wzm6-jayT_V6aIvhvMj5mnU-Xpj75zLPQSGa9wunMlOoZW9w1wDO1FVuDhwzeOJaTm-Ds0MezeC4U6nVGyyDHb4CUA3ml2tzt4yLrqGYMT7XbADSvuWYADHw79OFjEi4T3s3tJymhaBvy1ulv8M', + qi: 'wSbXte9PcPtr788e713KHQ4waE26CzoXx-JNOgN0iqJMN6C4_XJEX-cSvCZDf4rh7xpXN6SGLVd5ibIyDJi7bbi5EQ5AXjazPbLBjRthcGXsIuZ3AtQyR0CEWNSdM7EyM5TRdyZQ9kftfz9nI03guW3iKKASETqX2vh0Z8XRjyU', + use: 'sig', + }, { + crv: 'P-256', + d: 'K9xfPv773dZR22TVUB80xouzdF7qCg5cWjPjkHyv7Ws', + kty: 'EC', + use: 'sig', + x: 'FWZ9rSkLt6Dx9E3pxLybhdM6xgR5obGsj5_pqmnz5J4', + y: '_n8G69C-A2Xl4xUW2lF0i8ZGZnk_KPYrhv4GbTGu5G4', + }, + ], + }, +}; + +export const expressCreateServer = (hookName:string, args:ArgsExpressType, cb:Function) => { + const oidc = new Provider('http://localhost:9001', configuration); + args.app.use("/oidc",oidc.callback()); + cb(); +} diff --git a/src/node/security/OAuth2User.ts b/src/node/security/OAuth2User.ts new file mode 100644 index 000000000..b4305c401 --- /dev/null +++ b/src/node/security/OAuth2User.ts @@ -0,0 +1,5 @@ +export type OAuth2User = { + username: string; + password: string; + admin: boolean; +} diff --git a/src/node/security/OIDCAdapter.ts b/src/node/security/OIDCAdapter.ts new file mode 100644 index 000000000..8eac719cc --- /dev/null +++ b/src/node/security/OIDCAdapter.ts @@ -0,0 +1,41 @@ +import {Account, Adapter, AdapterPayload} from "oidc-provider"; + +export class OIDCAdapter implements Adapter { + private store: Map = new Map(); + private logins: Map = new Map(); + consume(id: string): Promise { + console.log('consume', id) + return Promise.resolve(undefined); + } + + destroy(id: string): Promise { + console.log('destroy', id) + return Promise.resolve(undefined); + } + + find(id: string): Promise { + console.log('find', id) + return Promise.resolve(undefined); + } + + findByUid(uid: string): Promise { + console.log('findByUid', uid) + return Promise.resolve(undefined); + } + + findByUserCode(userCode: string): Promise { + console.log('findByUserCode', userCode) + return Promise.resolve(undefined); + } + + revokeByGrantId(grantId: string): Promise { + console.log('revokeByGrantId', grantId) + return Promise.resolve(undefined); + } + + upsert(id: string, payload: AdapterPayload, expiresIn: number): Promise { + console.log('upsert', id, payload, expiresIn) + return Promise.resolve(undefined); + } + +} diff --git a/src/package.json b/src/package.json index 9652b1ff9..2e061347a 100644 --- a/src/package.json +++ b/src/package.json @@ -54,6 +54,7 @@ "log4js": "^6.9.1", "measured-core": "^2.0.0", "mime-types": "^2.1.35", + "oidc-provider": "^8.4.5", "openapi-backend": "^5.10.6", "proxy-addr": "^2.0.7", "rate-limiter-flexible": "^5.0.0", @@ -79,15 +80,17 @@ "etherpad-lite": "node/server.ts" }, "devDependencies": { + "@playwright/test": "^1.42.1", "@types/async": "^3.2.24", "@types/express": "^4.17.21", "@types/http-errors": "^2.0.4", "@types/jsdom": "^21.1.6", "@types/mocha": "^10.0.6", "@types/node": "^20.11.30", + "@types/oidc-provider": "^8.4.4", + "@types/semver": "^7.5.8", "@types/sinon": "^17.0.3", "@types/supertest": "^6.0.2", - "@types/semver": "^7.5.8", "@types/underscore": "^1.11.15", "eslint": "^8.57.0", "eslint-config-etherpad": "^4.0.4", @@ -96,7 +99,6 @@ "mocha-froth": "^0.2.10", "nodeify": "^1.0.1", "openapi-schema-validation": "^0.4.2", - "@playwright/test": "^1.42.1", "set-cookie-parser": "^2.6.0", "sinon": "^17.0.1", "split-grid": "^1.0.11",