From 5a8a54ccb347c0ae3e3db5878b04450f9c03b1fe Mon Sep 17 00:00:00 2001 From: hmathavan Date: Fri, 12 Aug 2022 11:46:15 +0000 Subject: [PATCH 1/9] Added configuration file --- .gitpod.yml | 9 +++++++++ src/config.ts | 5 +++++ src/index.ts | 27 ++++----------------------- src/oauth-mock-server.json | 23 +++++++++++++++++++++++ 4 files changed, 41 insertions(+), 23 deletions(-) create mode 100644 .gitpod.yml create mode 100644 src/config.ts create mode 100644 src/oauth-mock-server.json diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..9b1afe5 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,9 @@ +# This configuration file was automatically generated by Gitpod. +# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file) +# and commit this file to your remote git repository to share the goodness with others. + +tasks: + - init: pnpm install && pnpm run build + command: pnpm run start + + diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..00db947 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,5 @@ +export interface Config +{ + realm: string; + users: string[]; +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 27d99c1..c398629 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,33 +1,14 @@ import fastifyFormBody from '@fastify/formbody'; import fastify from 'fastify'; import jwt from 'jsonwebtoken'; +import Config from './oauth-mock-server.json' const server = fastify(); void server.register(fastifyFormBody); -const realm = 'bookyp'; // TODO: add way to load realm name from config - -// TODO: add way to load users from config -const users = [ - { - id: '1', - username: 'toni', - email: 'toni@test.com', - name: 'Toni Tester', - }, - { - id: '2', - username: 'alice', - email: 'alice@wonderland.org', - name: 'Alice Wonderland', - }, - { - id: '3', - username: 'herbert', - email: 'her@bert.de', - name: 'Herbert', - }, -]; +const realm = Config.realm; + +const users = Config.users; const jwtSecret = 'mySuperDuperSecret'; diff --git a/src/oauth-mock-server.json b/src/oauth-mock-server.json new file mode 100644 index 0000000..a3f407f --- /dev/null +++ b/src/oauth-mock-server.json @@ -0,0 +1,23 @@ +{ + "realm": "Project", + "users": [ + { + "id": "1", + "username": "toni", + "email": "toni@test.com", + "name": "Toni Tester" + }, + { + "id": "2", + "username": "alice", + "email": "alice@wonderland.org", + "name": "Alice Wonderland" + }, + { + "id": "3", + "username": "herbert", + "email": "her@bert.de", + "name": "Herbert" + } + ] +} \ No newline at end of file From 51cd0add4acef6935de7e06014849f5b06bcb0a7 Mon Sep 17 00:00:00 2001 From: hmathavan Date: Tue, 16 Aug 2022 10:30:41 +0000 Subject: [PATCH 2/9] Reolved lint errors --- src/config.ts | 9 ++++----- src/index.ts | 5 +++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/config.ts b/src/config.ts index 00db947..89acfb3 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,4 @@ -export interface Config -{ - realm: string; - users: string[]; -} \ No newline at end of file +export interface Config { + realm: string; + users: string[]; +} diff --git a/src/index.ts b/src/index.ts index c398629..a386164 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,13 @@ import fastifyFormBody from '@fastify/formbody'; import fastify from 'fastify'; import jwt from 'jsonwebtoken'; -import Config from './oauth-mock-server.json' + +import Config from './oauth-mock-server.json'; const server = fastify(); void server.register(fastifyFormBody); -const realm = Config.realm; +const realm = Config.realm; const users = Config.users; From 674d4d74b642399d97dfe9876634e8b474a810ad Mon Sep 17 00:00:00 2001 From: hmathavan Date: Tue, 16 Aug 2022 10:37:53 +0000 Subject: [PATCH 3/9] Resolved lint format issues --- .gitpod.yml | 2 -- src/oauth-mock-server.json | 44 +++++++++++++++++++------------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/.gitpod.yml b/.gitpod.yml index 9b1afe5..f04c5d4 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -5,5 +5,3 @@ tasks: - init: pnpm install && pnpm run build command: pnpm run start - - diff --git a/src/oauth-mock-server.json b/src/oauth-mock-server.json index a3f407f..236512a 100644 --- a/src/oauth-mock-server.json +++ b/src/oauth-mock-server.json @@ -1,23 +1,23 @@ { - "realm": "Project", - "users": [ - { - "id": "1", - "username": "toni", - "email": "toni@test.com", - "name": "Toni Tester" - }, - { - "id": "2", - "username": "alice", - "email": "alice@wonderland.org", - "name": "Alice Wonderland" - }, - { - "id": "3", - "username": "herbert", - "email": "her@bert.de", - "name": "Herbert" - } - ] -} \ No newline at end of file + "realm": "Project", + "users": [ + { + "id": "1", + "username": "toni", + "email": "toni@test.com", + "name": "Toni Tester" + }, + { + "id": "2", + "username": "alice", + "email": "alice@wonderland.org", + "name": "Alice Wonderland" + }, + { + "id": "3", + "username": "herbert", + "email": "her@bert.de", + "name": "Herbert" + } + ] +} From a558a35088f24ea8d181942660a9e4548146f118 Mon Sep 17 00:00:00 2001 From: hmathavan Date: Wed, 17 Aug 2022 21:30:01 +0000 Subject: [PATCH 4/9] code changes in config and index file --- src/config.ts | 44 ++++++++++++++++++++++++++++++++++++++++++-- src/index.ts | 26 ++++++++++++-------------- tsconfig.json | 24 ++++++++++++++++++------ 3 files changed, 72 insertions(+), 22 deletions(-) diff --git a/src/config.ts b/src/config.ts index 89acfb3..16f27ef 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,44 @@ -export interface Config { +import fs from 'fs'; +import { cwd } from 'node:process'; +import path from 'path'; + +interface RealmUsers { realm: string; - users: string[]; + users: [{ id: string; username: string; email: string; name: string }]; +} + +export function getConfig(): RealmUsers { + const defaultConfig = { + realm: 'my-project', + users: [ + { + id: '1', + username: 'toni', + email: 'toni@test.com', + name: 'Toni Tester', + }, + { + id: '2', + username: 'alice', + email: 'alice@wonderland.org', + name: 'Alice Wonderland', + }, + { + id: '3', + username: 'herbert', + email: 'her@bert.de', + name: 'Herbert', + }, + ], + }; + + const configPath = path.join(cwd, 'oauth-mock-server.json'); + if (!fs.existsSync(configPath)) { + return defaultConfig; + } + + const rawConfig = fs.readFileSync('/.oauth-mock-server.json'); + const config = {}; + Object.assign(config, defaultConfig, JSON.parse(rawConfig)); + return config; } diff --git a/src/index.ts b/src/index.ts index a386164..0a47e0a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,23 +1,20 @@ import fastifyFormBody from '@fastify/formbody'; +import { getConfig } from 'config'; import fastify from 'fastify'; import jwt from 'jsonwebtoken'; -import Config from './oauth-mock-server.json'; +const config = getConfig(); const server = fastify(); void server.register(fastifyFormBody); -const realm = Config.realm; - -const users = Config.users; - const jwtSecret = 'mySuperDuperSecret'; const randomString = () => (Math.random() + 1).toString(36).substring(7); let sessions: { code: string; user_id: string; access_token?: string }[] = []; -server.get(`/auth/realms/${realm}/protocol/openid-connect/auth`, async (request, reply) => { +server.get(`/auth/realms/${config.realm}/protocol/openid-connect/auth`, async (request, reply) => { const query = request.query as { redirect_uri: string; error?: string }; const template = ` @@ -66,7 +63,7 @@ server.get(`/auth/realms/${realm}/protocol/openid-connect/auth`, async (request,

Please login with one of the following usernames:

    - ${users + ${config.users .map( (user) => `
  • @@ -85,12 +82,13 @@ server.get(`/auth/realms/${realm}/protocol/openid-connect/auth`, async (request, server.all('/do-login', async (request, reply) => { const query = (request.body || request.query) as { username: string; redirect_uri: string }; - const user = users.find((u) => u.username === query.username) || users.find((u) => u.email === query.username); + const user = + config.users.find((u) => u.username === query.username) || config.users.find((u) => u.email === query.username); const redirect_uri = query.redirect_uri; if (!user) { await reply.redirect( - `/auth/realms/${realm}/protocol/openid-connect/auth?error=invalid_credentials&redirect_uri=${redirect_uri}`, + `/auth/realms/${config.realm}/protocol/openid-connect/auth?error=invalid_credentials&redirect_uri=${redirect_uri}`, ); return; } @@ -101,7 +99,7 @@ server.all('/do-login', async (request, reply) => { await reply.redirect(`${redirect_uri}?session_state=${sessionState}&code=${code}`); }); -server.post(`/auth/realms/${realm}/protocol/openid-connect/token`, async (request, reply) => { +server.post(`/auth/realms/${config.realm}/protocol/openid-connect/token`, async (request, reply) => { const body = request.body as { grant_type: string; code: string; @@ -121,7 +119,7 @@ server.post(`/auth/realms/${realm}/protocol/openid-connect/token`, async (reques const payload = { sub: session.user_id, // TODO check if valid (seems to work somehow) typ: 'Bearer', - aud: realm, + aud: config.realm, }; const accessToken = jwt.sign(payload, jwtSecret, { expiresIn: '1h' }); @@ -134,15 +132,15 @@ server.post(`/auth/realms/${realm}/protocol/openid-connect/token`, async (reques }; }); -server.get(`/auth/realms/${realm}/protocol/openid-connect/userinfo`, (request) => { +server.get(`/auth/realms/${config.realm}/protocol/openid-connect/userinfo`, (request) => { const headers = request.headers as { authorization: string }; const access_token = headers.authorization.replace('Bearer ', ''); const payload = jwt.verify(access_token, jwtSecret) as { sub: string }; const userId = payload.sub; - return users.find((s) => s.id === userId); + return config.users.find((s) => s.id === userId); }); -server.get(`/auth/realms/${realm}/protocol/openid-connect/logout`, async (request, reply) => { +server.get(`/auth/realms/${config.realm}/protocol/openid-connect/logout`, async (request, reply) => { const query = request.query as { redirect_uri: string }; await reply.redirect(query.redirect_uri); }); diff --git a/tsconfig.json b/tsconfig.json index 3c926c9..1da5202 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,9 @@ "compilerOptions": { "target": "es2017", "module": "esnext", - "lib": ["ESNext"], + "lib": [ + "ESNext" + ], "moduleResolution": "node", "esModuleInterop": true, "strict": true, @@ -14,10 +16,20 @@ "skipLibCheck": true, "noUnusedLocals": true, "paths": { - "~/*": ["./*"], - "$/*": ["../test/*"] + "~/*": [ + "./*" + ], + "$/*": [ + "../test/*" + ] } }, - "include": ["src", "test"], - "exclude": ["node_modules", "**/dist"] -} + "include": [ + "src", + "test" + ], + "exclude": [ + "node_modules", + "**/dist" + ] +} \ No newline at end of file From ddfac7bafa6e3818fc87c3034b1ad3e026a400e1 Mon Sep 17 00:00:00 2001 From: hmathavan Date: Wed, 17 Aug 2022 22:52:28 +0000 Subject: [PATCH 5/9] Resolved Typecheck issues --- src/config.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/config.ts b/src/config.ts index 16f27ef..9968f6c 100644 --- a/src/config.ts +++ b/src/config.ts @@ -4,7 +4,7 @@ import path from 'path'; interface RealmUsers { realm: string; - users: [{ id: string; username: string; email: string; name: string }]; + users: { id: string; username: string; email: string; name: string }[]; } export function getConfig(): RealmUsers { @@ -32,13 +32,23 @@ export function getConfig(): RealmUsers { ], }; - const configPath = path.join(cwd, 'oauth-mock-server.json'); + const configPath = path.join(cwd(), 'oauth-mock-server.json'); if (!fs.existsSync(configPath)) { return defaultConfig; } const rawConfig = fs.readFileSync('/.oauth-mock-server.json'); - const config = {}; - Object.assign(config, defaultConfig, JSON.parse(rawConfig)); + const config = { + realm: '', + users: [ + { + id: '', + username: '', + email: '', + name: '', + }, + ], + }; + Object.assign(config, defaultConfig, JSON.parse(rawConfig.toString())); return config; } From f7353551f421ca6599e13a13b023a55f298b6510 Mon Sep 17 00:00:00 2001 From: Anbraten Date: Thu, 18 Aug 2022 07:58:15 +0000 Subject: [PATCH 6/9] adjust some types and add some notes --- README.md | 34 +++++++++++++++++++++++++++++++++- src/config.ts | 31 ++++++++++++++----------------- src/oauth-mock-server.json | 23 ----------------------- 3 files changed, 47 insertions(+), 41 deletions(-) delete mode 100644 src/oauth-mock-server.json diff --git a/README.md b/README.md index 485fe00..5b22fd9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,35 @@ # oauth-mock-server -A mocked oauth server for development and e2e testing +> :rotating_light: IMPORTANT: This tool should ONLY be used for development and testing setups! + +A mocked oauth server for development and e2e testing. + +## Config + +You can adjust the default configuration by placing a file `oauth-mock-server.json` in your current working directory: + +```json +{ + "realm": "my-project", + "users": [ + { + "id": "1", + "username": "toni", + "email": "toni@test.com", + "name": "Toni Tester", + }, + { + "id": "2", + "username": "alice", + "email": "alice@wonderland.org", + "name": "Alice Wonderland", + }, + { + "id": "3", + "username": "herbert", + "email": "her@bert.de", + "name": "Herbert", + } + ] +} +``` diff --git a/src/config.ts b/src/config.ts index 9968f6c..d82b910 100644 --- a/src/config.ts +++ b/src/config.ts @@ -2,13 +2,20 @@ import fs from 'fs'; import { cwd } from 'node:process'; import path from 'path'; -interface RealmUsers { +export type ConfigUser = { + id: string; + username: string; + email: string; + name: string; +}; + +export type Config = { realm: string; - users: { id: string; username: string; email: string; name: string }[]; -} + users: ConfigUser[]; +}; -export function getConfig(): RealmUsers { - const defaultConfig = { +export function getConfig(): Config { + const defaultConfig = { realm: 'my-project', users: [ { @@ -37,18 +44,8 @@ export function getConfig(): RealmUsers { return defaultConfig; } - const rawConfig = fs.readFileSync('/.oauth-mock-server.json'); - const config = { - realm: '', - users: [ - { - id: '', - username: '', - email: '', - name: '', - }, - ], - }; + const rawConfig = fs.readFileSync(configPath); + const config = {}; Object.assign(config, defaultConfig, JSON.parse(rawConfig.toString())); return config; } diff --git a/src/oauth-mock-server.json b/src/oauth-mock-server.json deleted file mode 100644 index 236512a..0000000 --- a/src/oauth-mock-server.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "realm": "Project", - "users": [ - { - "id": "1", - "username": "toni", - "email": "toni@test.com", - "name": "Toni Tester" - }, - { - "id": "2", - "username": "alice", - "email": "alice@wonderland.org", - "name": "Alice Wonderland" - }, - { - "id": "3", - "username": "herbert", - "email": "her@bert.de", - "name": "Herbert" - } - ] -} From df710f45c3ecac465b0f4ecf7678c55ffd71e086 Mon Sep 17 00:00:00 2001 From: Anbraten Date: Thu, 18 Aug 2022 08:01:49 +0000 Subject: [PATCH 7/9] apply prettier --- README.md | 42 +++++++++++++++++++++--------------------- tsconfig.json | 24 ++++++------------------ 2 files changed, 27 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 5b22fd9..aa43cf8 100644 --- a/README.md +++ b/README.md @@ -10,26 +10,26 @@ You can adjust the default configuration by placing a file `oauth-mock-server.js ```json { - "realm": "my-project", - "users": [ - { - "id": "1", - "username": "toni", - "email": "toni@test.com", - "name": "Toni Tester", - }, - { - "id": "2", - "username": "alice", - "email": "alice@wonderland.org", - "name": "Alice Wonderland", - }, - { - "id": "3", - "username": "herbert", - "email": "her@bert.de", - "name": "Herbert", - } - ] + "realm": "my-project", + "users": [ + { + "id": "1", + "username": "toni", + "email": "toni@test.com", + "name": "Toni Tester" + }, + { + "id": "2", + "username": "alice", + "email": "alice@wonderland.org", + "name": "Alice Wonderland" + }, + { + "id": "3", + "username": "herbert", + "email": "her@bert.de", + "name": "Herbert" + } + ] } ``` diff --git a/tsconfig.json b/tsconfig.json index 1da5202..3c926c9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,9 +2,7 @@ "compilerOptions": { "target": "es2017", "module": "esnext", - "lib": [ - "ESNext" - ], + "lib": ["ESNext"], "moduleResolution": "node", "esModuleInterop": true, "strict": true, @@ -16,20 +14,10 @@ "skipLibCheck": true, "noUnusedLocals": true, "paths": { - "~/*": [ - "./*" - ], - "$/*": [ - "../test/*" - ] + "~/*": ["./*"], + "$/*": ["../test/*"] } }, - "include": [ - "src", - "test" - ], - "exclude": [ - "node_modules", - "**/dist" - ] -} \ No newline at end of file + "include": ["src", "test"], + "exclude": ["node_modules", "**/dist"] +} From f53c7e9979ce0808b29c9d9015259b4362cecba1 Mon Sep 17 00:00:00 2001 From: Anbraten Date: Mon, 22 Aug 2022 09:31:48 +0200 Subject: [PATCH 8/9] Update .gitpod.yml --- .gitpod.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitpod.yml b/.gitpod.yml index f04c5d4..10a3812 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -3,5 +3,5 @@ # and commit this file to your remote git repository to share the goodness with others. tasks: - - init: pnpm install && pnpm run build + - init: pnpm install command: pnpm run start From 5946aa8194121ef8999c370bfe154fa9a2fb7673 Mon Sep 17 00:00:00 2001 From: Anbraten Date: Mon, 22 Aug 2022 09:32:09 +0200 Subject: [PATCH 9/9] Update .gitpod.yml --- .gitpod.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.gitpod.yml b/.gitpod.yml index 10a3812..e605228 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,7 +1,3 @@ -# This configuration file was automatically generated by Gitpod. -# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file) -# and commit this file to your remote git repository to share the goodness with others. - tasks: - init: pnpm install command: pnpm run start