-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathauthenticate-celo.ts
51 lines (47 loc) · 1.88 KB
/
authenticate-celo.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import express = require('express')
import { verifySignature } from '@celo/utils/lib/signatureUtils'
import { AuthenticateStrategy } from './authenticate'
/**
* AuthenticateStrategy that authenticates a request using Celo accounts.
*
* @remarks
* Uses the Authorization header in the following form:
* Authorizaton: Celo Account-Address:Signature
* Signature signs a message of the following form: HTTP-Verb Request-Path
**/
export class AuthenticateCelo implements AuthenticateStrategy {
verify(req: express.Request): string {
if (!('authorization' in req.headers)) {
throw new Error('Missing authorization header')
}
const authorization = req.headers.authorization
const [
authorizationType,
authorizationCredentials,
] = authorization.split(' ')
if (authorizationType.toLowerCase() !== 'celo') {
throw new Error(
`Unexpected authorization type ${authorizationType}`,
)
} else if (!authorizationCredentials) {
throw new Error('Missing authorization credentials')
}
const split = authorizationCredentials.split(':')
const address = split[0]
const serializedSignature = split[1]
const message = `${req.method.toLowerCase()} ${req.path.toLowerCase()}`
const verified = verifySignature(message, serializedSignature, address)
if (!verified) {
throw new Error('Invalid authorization')
}
const participantId = address
return participantId
}
verifyMessage(data: object, signature: string, address: string): boolean {
const message = JSON.stringify(data)
return verifySignature(message, signature, address)
}
verifyString(data: string, signature: string, address: string): boolean {
return verifySignature(data, signature, address)
}
}