Skip to content

Commit 2e26ff5

Browse files
committed
feat(HTTP & WebSocket): Add JSON Web Token authentication
1 parent 0d40a89 commit 2e26ff5

8 files changed

Lines changed: 293 additions & 52 deletions

package-lock.json

Lines changed: 174 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"ajv": "^6.10.2",
3333
"cross-fetch": "^3.0.4",
3434
"fastify": "^2.10.0",
35+
"fastify-jwt": "^1.1.0",
3536
"fastify-websocket": "^0.6.0",
3637
"isomorphic-ws": "^4.0.1",
3738
"length-prefixed-stream": "^2.0.0",

src/http/HttpClient.ts

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,22 @@ import fetch from 'cross-fetch'
22
import Client from '../base/Client'
33
import Request from '../base/Request'
44
import { HttpAddress, TcpAddressInitializer } from '../base/Transports'
5+
import Response from '../base/Response'
6+
import JsonRpcError from '../base/Error'
57

68
/**
79
* A `Client` using HTTP/S for communication.
810
*/
911
export default class HttpClient extends Client {
10-
private readonly address: HttpAddress
12+
public readonly url: string
1113

12-
public constructor(address?: TcpAddressInitializer) {
14+
private readonly jwt?: string
15+
16+
public constructor(address: HttpAddress = new HttpAddress()) {
1317
super()
14-
this.address = new HttpAddress(address)
15-
}
1618

17-
public get url() {
18-
return this.address.toString()
19+
this.url = address.toString()
20+
this.jwt = address.jwt
1921
}
2022

2123
protected send(request: Request): Promise<void> {
@@ -26,12 +28,25 @@ export default class HttpClient extends Client {
2628
credentials: 'same-origin', // include, *same-origin, omit
2729
headers: {
2830
'Content-Type': 'application/json; charset=utf-8',
29-
Accept: 'application/json; charset=utf-8'
31+
Accept: 'application/json; charset=utf-8',
32+
...(this.jwt !== undefined
33+
? { Authorization: `Bearer ${this.jwt}` }
34+
: {})
3035
},
3136
body: JSON.stringify(request)
3237
})
33-
.then(response => response.json())
34-
.then(response => this.receive(response))
38+
.then(async reply => {
39+
if (reply.status >= 400) {
40+
// Translate the HTTP error into JSON-RPC error
41+
const message = await reply.text()
42+
const error = new JsonRpcError(-32600, message)
43+
return new Response(request.id, undefined, error)
44+
}
45+
return reply.json()
46+
})
47+
.then((response: Response) => {
48+
this.receive(response)
49+
})
3550
}
3651

3752
// Additional methods for getting and posting to server

src/http/HttpClientServer.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { testClient } from '../test/testClient'
22
import HttpClient from './HttpClient'
33
import HttpServer from './HttpServer'
4+
import { HttpAddress } from '../base/Transports'
5+
6+
beforeAll(() => {
7+
process.env.JWT_SECRET = 'not-a-secret-at-all'
8+
})
49

510
test('HttpClient and HttpServer', async () => {
611
const server = new HttpServer()

0 commit comments

Comments
 (0)