Skip to Main Content

NoSQL Database

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Creating the authorization header for querying a table in oracle nosql cloud using web crypto

drsganeshNov 14 2024

I want to query a table in oracle nosql cloud. I don't want to use any packages and want to use web crypto for creating the authorization header. I am trying to use the code below. But it is not working. What is the error here?

const oracleAuth = {}

oracleAuth.createHeaders = async function (httpMethod, host, requestPath, headers, body, privateKeyPem, tenancyOCID, userOCID, keyFingerprint) {

// Helper function to encode data in Base64





const base64Encode = (arrayBuffer) => {

    let binary = '';

    const bytes = new Uint8Array(arrayBuffer);

    for (let i = 0; i \< bytes.byteLength; i++) {

        binary += String.fromCharCode(bytes\[i\]);

    }

    return btoa(binary);

};




// Helper function to generate the signing string

const generateSigningString = (headersToSign, headers, requestTarget) => {

    return headersToSign.map(header => {

        if (header.toLowerCase() === '(request-target)') {

            return \`(request-target): ${requestTarget}\`;

        } else {

            return \`${header.toLowerCase()}: ${headers\[header.toLowerCase()\]}\`;

        }

    }).join('\\n');

};




// Import the private key

const importPrivateKey = async (pem) => {

    const pemHeader = '-----BEGIN PRIVATE KEY-----';

    const pemFooter = '-----END PRIVATE KEY-----';




    const pemHeaderStart = pem.indexOf(pemHeader);

    const pemFooterStart = pem.indexOf(pemFooter);




    const pemContents = pem.substring(pemHeaderStart + pemHeader.length, pemFooterStart).replace(/\\s+/g, '');





    const binaryDerString = atob(pemContents);

    const binaryDer = new Uint8Array(binaryDerString.length);

    for (let i = 0; i \< binaryDerString.length; i++) {

        binaryDer\[i\] = binaryDerString.charCodeAt(i);

    }





    return await crypto.subtle.importKey(

        'pkcs8',

        binaryDer.buffer,

        {

            name: 'RSASSA-PKCS1-v1\_5',

            hash: 'SHA-256',

        },

        false,

        \['sign'\]

    );

};




// Compute the SHA-256 hash of the request body

const computeSHA256 = async (data) => {

    const encoder = new TextEncoder();

    const dataBuffer = encoder.encode(data);

    const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);

    return base64Encode(hashBuffer);

};




// Ensure headers keys are in lowercase

headers = Object.keys(headers).reduce((acc, key) => {

    acc\[key.toLowerCase()\] = headers\[key\];

    return acc;

}, {});




// Prepare headers

headers\['host'\] = host;

headers\['date'\] = new Date().toUTCString();







if (body) {

    headers\['x-content-sha256'\] = await computeSHA256(body);

    headers\['content-length'\] = body.length.toString();

    headers\['content-type'\] = 'application/json';

} else {

    headers\['x-content-sha256'\] = await computeSHA256('');

    headers\['content-length'\] = '0';

    headers\['content-type'\] = 'application/json';

}




// Define the headers to sign

const headersToSign = \['date', '(request-target)', 'host', 'content-length', 'content-type', 'x-content-sha256'\];




// Generate the signing string

const requestTarget = \`${httpMethod.toLowerCase()} ${requestPath}\`;

const signingString = generateSigningString(headersToSign, headers, requestTarget);





debugger

// Import the private key

const privateKey = await importPrivateKey(privateKeyPem);




// Sign the signing string

const encoder = new TextEncoder();

const signingStringBuffer = encoder.encode(signingString);

const signatureBuffer = await crypto.subtle.sign(

    {

        name: 'RSASSA-PKCS1-v1\_5',

        hash: 'SHA-256',

    },

    privateKey,

    signingStringBuffer

);

const signature = base64Encode(signatureBuffer);




// Construct the Authorization header

const keyId = \`${tenancyOCID}/${userOCID}/${keyFingerprint}\`;

const authorizationHeader = \`Signature version="1",headers="${headersToSign.join(' ')}",keyId="${keyId}",algorithm="rsa-sha256",signature="${signature}"\`;




const headersRet = {

    'date': headers\['date'\],

    'authorization': authorizationHeader,

    'content-type': 'application/json',

    'x-content-sha256': headers\['x-content-sha256'\],

    'content-length': headers\['content-length'\],




}




return headersRet;

}

oracleAuth.test = async function () {

const httpMethod = 'POST';

const requestPath = 'https://nosql.ap-hyderabad-1.oci.oraclecloud.com/20190828/query';

const headers = {};

const body = JSON.stringify(

    {

        statement: "SELECT \* FROM otb1",

        compartmentId: 'comp1'

    }

)//




const hR\_priK = await fetch('./keys/pri.pem')

const privateKeyPem = await hR\_priK.text()





const tenancyOCID = \`ocid1.tenancy.oc1..XXX\`;

const userOCID = 'ocid1.user.oc1..xxx';

const keyFingerprint = '50:87:b5:93:6f:fb:05:e4:dc:a9:ec:a3:5f:3a:1c:ff';





const host = 'nosql.ap-hyderabad-1.oci.oraclecloud.com';




const er = await oracleAuth.createAuthorizationHeader(httpMethod, host, requestPath, headers, body, privateKeyPem, tenancyOCID, userOCID, keyFingerprint)

const hR = await fetch(requestPath, {

    method: httpMethod,

    headers: er,

    body: body,

});




const txtR = await hR.text()




//error : "{"code":"InvalidAuthorization","message":"NotAuthenticated. The request signature is invalid, credentials information might be incorrect or public key is not ready to use"}"

}

Comments
Post Details
Added on Nov 14 2024
0 comments
222 views