Skip to content

Commit 60aa568

Browse files
committedMar 15, 2023
fix: re-add examples to readme for convenience
1 parent c76af27 commit 60aa568

8 files changed

+873
-746
lines changed
 

‎.pnp.cjs

+643-643
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.prettierrc ‎.prettierrc.yml

File renamed without changes.

‎README.md

+123-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,129 @@ authentication in your koa or express app. This is why I made this tool, which r
1616

1717
## Usage
1818

19-
Please see the [example test](example/authentication.test.js) of a simple [koa app](example/api.js). Usage for `express`, `hapi` or `graphql` is similar.
19+
Consider a basic `koa` app (works also with `express`, `hapi` or `graphql`):
20+
21+
```js
22+
// api.js
23+
import Koa from 'koa'
24+
import Router from 'koa-router'
25+
import jwt from 'koa-jwt'
26+
import jwksRsa from 'jwks-rsa'
27+
const createApp = ({ jwksUri }) => {
28+
const app = new Koa()
29+
// We set up the jwksRsa client as usual (with production host)
30+
// We switch off caching to show how things work in ours tests.
31+
app.use(
32+
jwt({
33+
secret: jwksRsa.koaJwtSecret({
34+
cache: false,
35+
jwksUri,
36+
}),
37+
audience: 'private',
38+
issuer: 'master',
39+
algorithms: ['RS256'],
40+
})
41+
)
42+
const router = new Router()
43+
// This route is protected by the authentication middleware
44+
router.get('/', (ctx) => {
45+
ctx.body = 'Authenticated!'
46+
})
47+
app.use(router.middleware())
48+
return app
49+
}
50+
export default createApp
51+
```
52+
53+
You can test this app like so:
54+
55+
```js
56+
// authentication.test.js
57+
import createJWKSMock from '../src/index.js'
58+
import createApp from './api.js'
59+
import supertest from 'supertest'
60+
61+
describe('Some tests for authentication for our api', () => {
62+
let jwksMock, server, request
63+
beforeEach(() => {
64+
;({ jwksMock, server, request } = createContext())
65+
})
66+
afterEach(async () => await tearDown({ jwksMock, server }))
67+
test('should not get access without correct token', async () => {
68+
// We start intercepting queries (see below)
69+
jwksMock.start()
70+
const { status } = await request.get('/')
71+
expect(status).toEqual(401)
72+
})
73+
74+
test('should get access with mock token when jwksMock is running', async () => {
75+
// Again we start intercepting queries
76+
jwksMock.start()
77+
const access_token = jwksMock.token({
78+
aud: 'private',
79+
iss: 'master',
80+
})
81+
const { status } = await request
82+
.get('/')
83+
.set('Authorization', `Bearer ${access_token}`)
84+
expect(status).toEqual(200)
85+
})
86+
test('should not get access with mock token when jwksMock is not running', async () => {
87+
// Now we do not intercept queries. The queries of the middleware for the JKWS will
88+
// go to the production server and the local key will be invalid.
89+
const access_token = jwksMock.token({
90+
aud: 'private',
91+
iss: 'master',
92+
})
93+
const { status } = await request
94+
.get('/')
95+
.set('Authorization', `Bearer ${access_token}`)
96+
expect(status).toEqual(401)
97+
})
98+
})
99+
test('Another example with a non-auth0-style jkwsUri', async () => {
100+
const jwksMock = createJWKSMock(
101+
'https://keycloak.somedomain.com/auth/realm/application',
102+
'/protocol/openid-connect/certs'
103+
)
104+
// We start our app.
105+
const server = createApp({
106+
jwksUri:
107+
'https://keycloak.somedomain.com/auth/realm/application/protocol/openid-connect/certs',
108+
}).listen()
109+
const request = supertest(server)
110+
jwksMock.start()
111+
const access_token = jwksMock.token({
112+
aud: 'private',
113+
iss: 'master',
114+
})
115+
const { status } = await request
116+
.get('/')
117+
.set('Authorization', `Bearer ${access_token}`)
118+
await tearDown({ jwksMock, server })
119+
expect(status).toEqual(200)
120+
})
121+
const createContext = () => {
122+
// This creates the local PKI
123+
const jwksMock = createJWKSMock('https://levino.eu.auth0.com/')
124+
// We start our app.
125+
const server = createApp({
126+
jwksUri: 'https://levino.eu.auth0.com/.well-known/jwks.json',
127+
}).listen()
128+
const request = supertest(server)
129+
return {
130+
jwksMock,
131+
request,
132+
server,
133+
}
134+
}
135+
const tearDown = async ({ jwksMock, server }) => {
136+
await server.close()
137+
await jwksMock.stop()
138+
}
139+
```
140+
141+
You can also find [this example in the repo](example/authentication.test.js).
20142

21143
## Under the hood
22144

‎example/api.js

+27-27
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
import Koa from "koa";
2-
import Router from "koa-router";
3-
import jwt from "koa-jwt";
4-
import jwksRsa from "jwks-rsa";
1+
import Koa from 'koa'
2+
import Router from 'koa-router'
3+
import jwt from 'koa-jwt'
4+
import jwksRsa from 'jwks-rsa'
55
const createApp = ({ jwksUri }) => {
6-
const app = new Koa();
7-
// We set up the jwksRsa client as usual (with production host)
8-
// We switch off caching to show how things work in ours tests.
9-
app.use(jwt({
10-
secret: jwksRsa.koaJwtSecret({
11-
cache: false,
12-
jwksUri,
13-
}),
14-
audience: 'private',
15-
issuer: 'master',
16-
algorithms: ['RS256'],
17-
}));
18-
const router = new Router();
19-
// This route is protected by the authentication middleware
20-
router.get('/', (ctx) => {
21-
ctx.body = 'Authenticated!';
22-
});
23-
app.use(router.middleware());
24-
return app;
25-
};
26-
export default createApp;
27-
28-
6+
const app = new Koa()
7+
// We set up the jwksRsa client as usual (with production host)
8+
// We switch off caching to show how things work in ours tests.
9+
app.use(
10+
jwt({
11+
secret: jwksRsa.koaJwtSecret({
12+
cache: false,
13+
jwksUri,
14+
}),
15+
audience: 'private',
16+
issuer: 'master',
17+
algorithms: ['RS256'],
18+
})
19+
)
20+
const router = new Router()
21+
// This route is protected by the authentication middleware
22+
router.get('/', (ctx) => {
23+
ctx.body = 'Authenticated!'
24+
})
25+
app.use(router.middleware())
26+
return app
27+
}
28+
export default createApp

‎example/authentication.test.js

+76-72
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,82 @@
1-
import createJWKSMock from "../src/index.js";
2-
import createApp from "./api.js";
3-
import supertest from "supertest";
1+
import createJWKSMock from '../src/index.js'
2+
import createApp from './api.js'
3+
import supertest from 'supertest'
44

55
describe('Some tests for authentication for our api', () => {
6-
let jwksMock, server, request;
7-
beforeEach(() => {
8-
;
9-
({ jwksMock, server, request } = createContext());
10-
});
11-
afterEach(async () => await tearDown({ jwksMock, server }));
12-
test('should not get access without correct token', async () => {
13-
// We start intercepting queries (see below)
14-
jwksMock.start();
15-
const { status } = await request.get('/');
16-
expect(status).toEqual(401);
17-
});
18-
test('should get access with mock token when jwksMock is running', async () => {
19-
// Again we start intercepting queries
20-
jwksMock.start();
21-
const access_token = jwksMock.token({
22-
aud: 'private',
23-
iss: 'master',
24-
});
25-
const { status } = await request
26-
.get('/')
27-
.set('Authorization', `Bearer ${access_token}`);
28-
expect(status).toEqual(200);
29-
});
30-
test('should not get access with mock token when jwksMock is not running', async () => {
31-
// Now we do not intercept queries. The queries of the middleware for the JKWS will
32-
// go to the production server and the local key will be invalid.
33-
const access_token = jwksMock.token({
34-
aud: 'private',
35-
iss: 'master',
36-
});
37-
const { status } = await request
38-
.get('/')
39-
.set('Authorization', `Bearer ${access_token}`);
40-
expect(status).toEqual(401);
41-
});
42-
});
43-
test('Another example with a non-auth0-style jkwsUri', async () => {
44-
const jwksMock = createJWKSMock('https://keycloak.somedomain.com/auth/realm/application', '/protocol/openid-connect/certs');
45-
// We start our app.
46-
const server = createApp({
47-
jwksUri: 'https://keycloak.somedomain.com/auth/realm/application/protocol/openid-connect/certs',
48-
}).listen();
49-
const request = supertest(server);
50-
jwksMock.start();
6+
let jwksMock, server, request
7+
beforeEach(() => {
8+
;({ jwksMock, server, request } = createContext())
9+
})
10+
afterEach(async () => await tearDown({ jwksMock, server }))
11+
test('should not get access without correct token', async () => {
12+
// We start intercepting queries (see below)
13+
jwksMock.start()
14+
const { status } = await request.get('/')
15+
expect(status).toEqual(401)
16+
})
17+
18+
test('should get access with mock token when jwksMock is running', async () => {
19+
// Again we start intercepting queries
20+
jwksMock.start()
5121
const access_token = jwksMock.token({
52-
aud: 'private',
53-
iss: 'master',
54-
});
22+
aud: 'private',
23+
iss: 'master',
24+
})
5525
const { status } = await request
56-
.get('/')
57-
.set('Authorization', `Bearer ${access_token}`);
58-
await tearDown({ jwksMock, server });
59-
expect(status).toEqual(200);
60-
});
26+
.get('/')
27+
.set('Authorization', `Bearer ${access_token}`)
28+
expect(status).toEqual(200)
29+
})
30+
test('should not get access with mock token when jwksMock is not running', async () => {
31+
// Now we do not intercept queries. The queries of the middleware for the JKWS will
32+
// go to the production server and the local key will be invalid.
33+
const access_token = jwksMock.token({
34+
aud: 'private',
35+
iss: 'master',
36+
})
37+
const { status } = await request
38+
.get('/')
39+
.set('Authorization', `Bearer ${access_token}`)
40+
expect(status).toEqual(401)
41+
})
42+
})
43+
test('Another example with a non-auth0-style jkwsUri', async () => {
44+
const jwksMock = createJWKSMock(
45+
'https://keycloak.somedomain.com/auth/realm/application',
46+
'/protocol/openid-connect/certs'
47+
)
48+
// We start our app.
49+
const server = createApp({
50+
jwksUri:
51+
'https://keycloak.somedomain.com/auth/realm/application/protocol/openid-connect/certs',
52+
}).listen()
53+
const request = supertest(server)
54+
jwksMock.start()
55+
const access_token = jwksMock.token({
56+
aud: 'private',
57+
iss: 'master',
58+
})
59+
const { status } = await request
60+
.get('/')
61+
.set('Authorization', `Bearer ${access_token}`)
62+
await tearDown({ jwksMock, server })
63+
expect(status).toEqual(200)
64+
})
6165
const createContext = () => {
62-
// This creates the local PKI
63-
const jwksMock = createJWKSMock('https://hardfork.eu.auth0.com/');
64-
// We start our app.
65-
const server = createApp({
66-
jwksUri: 'https://hardfork.eu.auth0.com/.well-known/jwks.json',
67-
}).listen();
68-
const request = supertest(server);
69-
return {
70-
jwksMock,
71-
request,
72-
server,
73-
};
74-
};
66+
// This creates the local PKI
67+
const jwksMock = createJWKSMock('https://levino.eu.auth0.com/')
68+
// We start our app.
69+
const server = createApp({
70+
jwksUri: 'https://levino.eu.auth0.com/.well-known/jwks.json',
71+
}).listen()
72+
const request = supertest(server)
73+
return {
74+
jwksMock,
75+
request,
76+
server,
77+
}
78+
}
7579
const tearDown = async ({ jwksMock, server }) => {
76-
await server.close();
77-
await jwksMock.stop();
78-
};
80+
await server.close()
81+
await jwksMock.stop()
82+
}

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"@types/base64-url": "^2.2.0",
6060
"@types/chai": "^4.3.3",
6161
"@types/chai-as-promised": "^7.1.5",
62-
"@types/jest": "^29.1.2",
62+
"@types/jest": "^29.4.2",
6363
"@types/jsonwebtoken": "^9.0.1",
6464
"@types/nock": "^11.1.0",
6565
"@types/node": "^18.15.3",

‎src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const createJWKSMock = (
1111
...keypair,
1212
jwksOrigin,
1313
})
14+
1415
let jwksUrlInterceptor: nock.Interceptor
1516

1617
const kid = () => JWKS.keys[0].kid

‎yarn.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -1231,7 +1231,7 @@ __metadata:
12311231
languageName: node
12321232
linkType: hard
12331233

1234-
"@types/jest@npm:^29.1.2":
1234+
"@types/jest@npm:^29.4.2":
12351235
version: 29.4.2
12361236
resolution: "@types/jest@npm:29.4.2"
12371237
dependencies:
@@ -4436,7 +4436,7 @@ __metadata:
44364436
"@types/base64-url": "npm:^2.2.0"
44374437
"@types/chai": "npm:^4.3.3"
44384438
"@types/chai-as-promised": "npm:^7.1.5"
4439-
"@types/jest": "npm:^29.1.2"
4439+
"@types/jest": "npm:^29.4.2"
44404440
"@types/jsonwebtoken": "npm:^9.0.1"
44414441
"@types/nock": "npm:^11.1.0"
44424442
"@types/node": "npm:^18.15.3"

0 commit comments

Comments
 (0)
Please sign in to comment.