dnb-api
Version:
Client for DNB Open Banking platform
121 lines (98 loc) • 4.01 kB
JavaScript
const {HeaderBuilder} = require('aika')
const crypto = require('crypto')
module.exports = (options) => {
return new HeaderBuilder({
constants: {
apiKey: options.apiKey,
clientId: options.clientId,
clientSecret: options.clientSecret,
hostName: options.hostName,
// Reference to client JWT
token: options.token,
// Amz
algorithm: 'AWS4-HMAC-SHA256',
signedHeaders: 'host;x-amz-date',
awsRegion: options.awsRegion,
awsService: options.awsService
},
helpers: {
// Basics
hashHex: string => crypto.createHash('sha256').update(string, 'utf8').digest('hex'),
createAmzDate: () => new Date().toISOString().replace(/[:-]|\.\d{3}/g, ''),
signData: (key, data, encoding) => crypto.createHmac('sha256', key).update(data, 'utf8').digest(encoding ? encoding : 'hex'),
// Canonical
canonicalUri: path => {
const queryStringMatch = path.match(/(.*)\?/)
let canonicalUri = path
if (queryStringMatch !== null) {
const firstMatchIndex = 1
canonicalUri = queryStringMatch[firstMatchIndex]
}
return canonicalUri
},
canonicalHeaders: (hostName, amzDate) => `host:${hostName}\nx-amz-date:${amzDate}\n`,
canonicalRequest: (method, canonicalUri, canonicalQuerystring, canonicalHeaders, signedHeaders, payloadHash) => {
return `${method}\n${canonicalUri}\n${canonicalQuerystring}\n${canonicalHeaders}\n${signedHeaders}\n${payloadHash}`
},
// Credential
credentialScope: (dateStamp, region, service) => `${dateStamp}/${region}/${service}/aws4_request`,
credentialHeader: (clientId, credentialScope) => `Credential=${clientId}/${credentialScope}`,
signedHeaders: () => 'host;x-amz-date',
getSignatureKey: (context, clientSecret, dateStamp, serviceName, regionName) => {
const date = context.helpers.signData((`AWS4${clientSecret}`), dateStamp)
const region = context.helpers.signData(date, regionName)
const service = context.helpers.signData(region, serviceName)
return context.helpers.signData(service, 'aws4_request')
},
stringToSign: (context, algorithm, amzDate, credentialScope, canonicalRequest) => `${algorithm}\n${amzDate}\n${credentialScope}\n${context.helpers.hashHex(canonicalRequest)}`,
},
headerFunctions: {
Host: c => c.constants.hostName,
Accept: () => 'application/json',
'Content-type': () => 'application/json',
'x-api-key': c => c.constants.apiKey,
'x-amz-date': c => c.helpers.createAmzDate(),
//'x-dnbapi-jwt': c => c.constants.token.jwt,
Authorization: (c, r) => {
const amzDate = c.helpers.createAmzDate()
const dateStamp = amzDate.substr(0, 8)
const signedHeaders = c.constants.signedHeaders
const payloadHash = c.helpers.hashHex(r.body ? JSON.stringify(r.body) : '')
// Canonical
const canonicalUri = c.helpers.canonicalUri(r.path)
const canonicalQuerystring = r.params
const canonicalHeaders = c.helpers.canonicalHeaders(c.constants.hostName, amzDate)
const canonicalRequest = c.helpers.canonicalRequest(
r.method,
canonicalUri,
canonicalQuerystring,
canonicalHeaders,
signedHeaders,
payloadHash
)
//
const credentialScope = c.helpers.credentialScope(dateStamp, c.constants.awsRegion, c.constants.awsService)
const signingKey = c.helpers.getSignatureKey(
c,
c.constants.clientSecret,
dateStamp,
c.constants.awsService,
c.constants.awsRegion
)
const stringToSign = c.helpers.stringToSign(
c,
c.constants.algorithm,
amzDate,
credentialScope,
canonicalRequest
)
// Final
const credentialHeader = c.helpers.credentialHeader(c.constants.clientId, credentialScope)
const signature = c.helpers.signData(signingKey, stringToSign, 'hex')
console.log('Canonical string:\n', canonicalRequest)
console.log('String to sign:\n', stringToSign)
return `${c.constants.algorithm} ${credentialHeader}, SignedHeaders=${signedHeaders}, Signature=${signature}`
},
}
})
}