Skip to content

Commit 97bf917

Browse files
hmathavananbraten
andauthored
feat: add config file loading for users and realm settings (#5)
Co-authored-by: Anbraten <anton@ju60.de>
1 parent 1f80b94 commit 97bf917

File tree

4 files changed

+100
-34
lines changed

4 files changed

+100
-34
lines changed

.gitpod.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
tasks:
2+
- init: pnpm install
3+
command: pnpm run start

README.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,35 @@
11
# oauth-mock-server
22

3-
A mocked oauth server for development and e2e testing
3+
> :rotating_light: IMPORTANT: This tool should ONLY be used for development and testing setups!
4+
5+
A mocked oauth server for development and e2e testing.
6+
7+
## Config
8+
9+
You can adjust the default configuration by placing a file `oauth-mock-server.json` in your current working directory:
10+
11+
```json
12+
{
13+
"realm": "my-project",
14+
"users": [
15+
{
16+
"id": "1",
17+
"username": "toni",
18+
"email": "toni@test.com",
19+
"name": "Toni Tester"
20+
},
21+
{
22+
"id": "2",
23+
"username": "alice",
24+
"email": "alice@wonderland.org",
25+
"name": "Alice Wonderland"
26+
},
27+
{
28+
"id": "3",
29+
"username": "herbert",
30+
"email": "her@bert.de",
31+
"name": "Herbert"
32+
}
33+
]
34+
}
35+
```

src/config.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import fs from 'fs';
2+
import { cwd } from 'node:process';
3+
import path from 'path';
4+
5+
export type ConfigUser = {
6+
id: string;
7+
username: string;
8+
email: string;
9+
name: string;
10+
};
11+
12+
export type Config = {
13+
realm: string;
14+
users: ConfigUser[];
15+
};
16+
17+
export function getConfig(): Config {
18+
const defaultConfig = <Config>{
19+
realm: 'my-project',
20+
users: [
21+
{
22+
id: '1',
23+
username: 'toni',
24+
email: 'toni@test.com',
25+
name: 'Toni Tester',
26+
},
27+
{
28+
id: '2',
29+
username: 'alice',
30+
email: 'alice@wonderland.org',
31+
name: 'Alice Wonderland',
32+
},
33+
{
34+
id: '3',
35+
username: 'herbert',
36+
email: 'her@bert.de',
37+
name: 'Herbert',
38+
},
39+
],
40+
};
41+
42+
const configPath = path.join(cwd(), 'oauth-mock-server.json');
43+
if (!fs.existsSync(configPath)) {
44+
return defaultConfig;
45+
}
46+
47+
const rawConfig = fs.readFileSync(configPath);
48+
const config = <Config>{};
49+
Object.assign(config, defaultConfig, JSON.parse(rawConfig.toString()));
50+
return config;
51+
}

src/index.ts

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,20 @@
11
import fastifyFormBody from '@fastify/formbody';
2+
import { getConfig } from 'config';
23
import fastify from 'fastify';
34
import jwt from 'jsonwebtoken';
45

6+
const config = getConfig();
7+
58
const server = fastify();
69
void server.register(fastifyFormBody);
710

8-
const realm = 'bookyp'; // TODO: add way to load realm name from config
9-
10-
// TODO: add way to load users from config
11-
const users = [
12-
{
13-
id: '1',
14-
username: 'toni',
15-
email: 'toni@test.com',
16-
name: 'Toni Tester',
17-
},
18-
{
19-
id: '2',
20-
username: 'alice',
21-
email: 'alice@wonderland.org',
22-
name: 'Alice Wonderland',
23-
},
24-
{
25-
id: '3',
26-
username: 'herbert',
27-
email: 'her@bert.de',
28-
name: 'Herbert',
29-
},
30-
];
31-
3211
const jwtSecret = 'mySuperDuperSecret';
3312

3413
const randomString = () => (Math.random() + 1).toString(36).substring(7);
3514

3615
let sessions: { code: string; user_id: string; access_token?: string }[] = [];
3716

38-
server.get(`/auth/realms/${realm}/protocol/openid-connect/auth`, async (request, reply) => {
17+
server.get(`/auth/realms/${config.realm}/protocol/openid-connect/auth`, async (request, reply) => {
3918
const query = request.query as { redirect_uri: string; error?: string };
4019

4120
const template = `
@@ -84,7 +63,7 @@ server.get(`/auth/realms/${realm}/protocol/openid-connect/auth`, async (request,
8463
<div>
8564
<p>Please login with one of the following usernames:</p>
8665
<ul>
87-
${users
66+
${config.users
8867
.map(
8968
(user) =>
9069
`<li>
@@ -103,12 +82,13 @@ server.get(`/auth/realms/${realm}/protocol/openid-connect/auth`, async (request,
10382

10483
server.all('/do-login', async (request, reply) => {
10584
const query = (request.body || request.query) as { username: string; redirect_uri: string };
106-
const user = users.find((u) => u.username === query.username) || users.find((u) => u.email === query.username);
85+
const user =
86+
config.users.find((u) => u.username === query.username) || config.users.find((u) => u.email === query.username);
10787
const redirect_uri = query.redirect_uri;
10888

10989
if (!user) {
11090
await reply.redirect(
111-
`/auth/realms/${realm}/protocol/openid-connect/auth?error=invalid_credentials&redirect_uri=${redirect_uri}`,
91+
`/auth/realms/${config.realm}/protocol/openid-connect/auth?error=invalid_credentials&redirect_uri=${redirect_uri}`,
11292
);
11393
return;
11494
}
@@ -119,7 +99,7 @@ server.all('/do-login', async (request, reply) => {
11999
await reply.redirect(`${redirect_uri}?session_state=${sessionState}&code=${code}`);
120100
});
121101

122-
server.post(`/auth/realms/${realm}/protocol/openid-connect/token`, async (request, reply) => {
102+
server.post(`/auth/realms/${config.realm}/protocol/openid-connect/token`, async (request, reply) => {
123103
const body = request.body as {
124104
grant_type: string;
125105
code: string;
@@ -139,7 +119,7 @@ server.post(`/auth/realms/${realm}/protocol/openid-connect/token`, async (reques
139119
const payload = {
140120
sub: session.user_id, // TODO check if valid (seems to work somehow)
141121
typ: 'Bearer',
142-
aud: realm,
122+
aud: config.realm,
143123
};
144124

145125
const accessToken = jwt.sign(payload, jwtSecret, { expiresIn: '1h' });
@@ -152,15 +132,15 @@ server.post(`/auth/realms/${realm}/protocol/openid-connect/token`, async (reques
152132
};
153133
});
154134

155-
server.get(`/auth/realms/${realm}/protocol/openid-connect/userinfo`, (request) => {
135+
server.get(`/auth/realms/${config.realm}/protocol/openid-connect/userinfo`, (request) => {
156136
const headers = request.headers as { authorization: string };
157137
const access_token = headers.authorization.replace('Bearer ', '');
158138
const payload = jwt.verify(access_token, jwtSecret) as { sub: string };
159139
const userId = payload.sub;
160-
return users.find((s) => s.id === userId);
140+
return config.users.find((s) => s.id === userId);
161141
});
162142

163-
server.get(`/auth/realms/${realm}/protocol/openid-connect/logout`, async (request, reply) => {
143+
server.get(`/auth/realms/${config.realm}/protocol/openid-connect/logout`, async (request, reply) => {
164144
const query = request.query as { redirect_uri: string };
165145
await reply.redirect(query.redirect_uri);
166146
});

0 commit comments

Comments
 (0)