diff --git a/keyserver/src/services/blob.js b/keyserver/src/services/blob.js --- a/keyserver/src/services/blob.js +++ b/keyserver/src/services/blob.js @@ -6,17 +6,50 @@ makeBlobServiceEndpointURL, } from 'lib/utils/blob-service.js'; import { getMessageForException } from 'lib/utils/errors.js'; +import { createHTTPAuthorizationHeader } from 'lib/utils/services-utils.js'; + +import { verifyUserLoggedIn } from '../user/login.js'; +import { getContentSigningKey } from '../utils/olm-utils.js'; + +function base64Encode(input: string): string { + return Buffer.from(input, 'utf8').toString('base64'); +} + +async function createRequestHeaders( + includeContentType: boolean = true, +): Promise<{ [string]: string }> { + const [{ userId: userID, accessToken }, deviceID] = await Promise.all([ + verifyUserLoggedIn(), + getContentSigningKey(), + ]); + + const authorization = createHTTPAuthorizationHeader( + { + userID, + deviceID, + accessToken, + }, + base64Encode, + ); + + return { + Authorization: authorization, + ...(includeContentType && { 'Content-Type': 'application/json' }), + }; +} async function uploadBlob(blob: Blob, hash: string): Promise { const formData = new FormData(); formData.append('blob_hash', hash); formData.append('blob_data', blob); + const headers = await createRequestHeaders(false); const uploadBlobResponse = await fetch( makeBlobServiceEndpointURL(blobService.httpEndpoints.UPLOAD_BLOB), { method: blobService.httpEndpoints.UPLOAD_BLOB.method, body: formData, + headers, }, ); @@ -27,6 +60,7 @@ } async function assignHolder(holder: string, hash: string): Promise { + const headers = await createRequestHeaders(); const assignHolderResponse = await fetch( makeBlobServiceEndpointURL(blobService.httpEndpoints.ASSIGN_HOLDER), { @@ -35,9 +69,7 @@ holder, blob_hash: hash, }), - headers: { - 'content-type': 'application/json', - }, + headers, }, ); @@ -71,11 +103,10 @@ }, > { const url = getBlobFetchableURL(hash); + const headers = await createRequestHeaders(); const response = await fetch(url, { method: blobService.httpEndpoints.GET_BLOB.method, - headers: { - 'content-type': 'application/json', - }, + headers, }); if (!response.ok) { diff --git a/lib/utils/services-utils.js b/lib/utils/services-utils.js --- a/lib/utils/services-utils.js +++ b/lib/utils/services-utils.js @@ -1,5 +1,7 @@ // @flow +import type { AuthMetadata } from '../shared/identity-client-context.js'; + const usingCommServicesAccessToken = false; function handleHTTPResponseError(response: Response): void { @@ -9,4 +11,20 @@ } } -export { handleHTTPResponseError, usingCommServicesAccessToken }; +function createHTTPAuthorizationHeader( + authMetadata: AuthMetadata, + // base64 encode function is platform-specific + base64EncodeFunction: string => string = btoa, +): string { + // explicit destructure to make it future-proof + const { userID, deviceID, accessToken } = authMetadata; + const payload = JSON.stringify({ userID, deviceID, accessToken }); + const base64EncodedPayload = base64EncodeFunction(payload); + return `Bearer ${base64EncodedPayload}`; +} + +export { + handleHTTPResponseError, + usingCommServicesAccessToken, + createHTTPAuthorizationHeader, +};