# Authentication
# Introduction
SalesCloud Apps can authenticate and perform queries and mutations with the SalesCloud Graph on behalf of organizations.
Users must install your App from the Appstore to their organization to give your app access to their data in the graphql.
# Api Keys
SalesCloud Apps must use a public key and a secret key to authorize requests with the SalesCloud Graph.
These keys are found in the security section of your app in the SalesCloud Developer portal.
The secret key cannot be retrieved again after it is generated, so make sure to save it in a secure place. A new secret key can be generated at any given time and is effective immediately.
# Headers
Authenticated requests on behalf of your app have the following headers.
# SalesCloud-Application
This header is the uuid of your app so that the SalesCloud Graph knows which app is making the authenticated request.
# SalesCloud-Application-Public-Key
This header is the public key of your app as seen on the security section in the developer portal.
# SalesCloud-Organization
This header is the uuid of the organization on behalf which you want to make a request.
The uuid of the organization must exist and must have your application installed for your request to make an authenticated request on behalf of that organization.
We recomment that you make a "appOrganizations" query on the SalesCloud Graph to get a list of organizations that have installed your app.
curl --verbose --header "SalesCloud-Application: xxx" --header "SalesCloud-Application-Public-Key: xxx" --header "Authorization: App xxx"--data '{ "query": "{ query appOrganizations { uuid, label } }"}' --request "POST" "https://graph.salescloud.is?"
# Authorization
This header contains a cryptographically signed string using the app uuid, public key and the request body with the secret.
This header will be computed in the graph with the same values and compared to this header. Only if both signatures are the same is your request considered valid.
The Authorization header is followed by an App prefix where you would normally see Bearer, like so: "Authorization: App .....".
Below is an example of how to generate the authorization header.
const crypto = require('crypto')
const applicationUUID = 'edadd893-9472-4324-a4db-b1707c563184'
const organizationUUID = '7b371391-1561-4cac-8f86-9b7bcba83db2'
const applicationPublicKey = '849015eb35e25eee9b36b36481b55ec3a4efc4c6351873f98d33601448b80139e4ca2ca2adc314df182edc1848dcef713b448f982bcf8d8382813a5547e0a87b21e7119ef83349e176ac49a0a35be0197a1bb41e8660a33eaeeae3ffc6e61174b4462b833e18a1586a7a847deb1f2605a38cce7e1e29cce4295fbd2bfa37108abdc00399c2b4b8a7e4cbe5073530a6737550f5c497c1d09d0c4ed86b3fefbe2eb97381dcc645611ae47b2bdc8c481f1d99dd36b2cb0e56d24cf292f5ddaead29000fb806b7577272f6f1440b69cd4808094c1e042fa1753e8e563d1f8d1da46b6eb7346c179322f57a06134adf3bc508b815c3e6fc42b2bb82bf27836aa23432'
const applicationSecretKey = 'dd14918184be8aacfcb44b939804f0d3efb09e35d7945f8bf91c71984f41db0646c69412d1795ae7da766d04153344b04d4dcb8eb28171c7d21b43ff5afd4aa6b8ee1d22d9c5bef82d82c540aebdc67f10f46275c2fc924a764f1849b4b2fd0640a9afc00174efca544d56c6ca02c048af802ba2f1992943f83f04cd0f177b8b867291700b236cab7e17defb92b51554d0d04368e637f02d3ccd2ebafb6ccc65b4809a3f6d38c8332f94a4008d01238e2818da89d5c978be85473f6f874bd3499b3fc1e2d4e992f81822ccb2ae4b50aa20f196ce4b5780df38badb749c6c6b85c2baeb2d7afeaaa13dfbe72d4bd86cc437bc8043beaf8d60bcdad8d26fafe7c0'
// Simple Example Request
const bodyOfRequestAsJsonString = '{ "query": { systemTimeInMillis } }'
// The string that must be cryptographically signed
const sign = applicationUUID + ':' + applicationPublicKey + ':' + organizationUUID + ':' + bodyOfRequestAsJsonString
// The computed signature for Authorization header
const computedSignature = crypto.createHmac('sha256', applicationSecretKey).update(sign).digest('base64')
# Read Access Tokens
Read access tokens allow you to easily query data from the graph. As the name suggests, you can only read information with those tokens.
All that is required is an header like this: "Authorization: ReadAccessToken {TokenHere}"
# Axios Example
const crypto = require('crypto')
const axios = require('axios')
function CreateHeaders(appUUID, organizationUUID, publicKey, privateKey, query, variables) {
let formattedQuery = ''
if (variables) {
formattedQuery = JSON.stringify({ query: query, variables: variables })
} else {
formattedQuery = JSON.stringify({ query: query })
}
let stringMeantForSigning = appUUID + ':' + publicKey + ':' + organizationUUID + ':' + formattedQuery
const SIGNED = crypto.createHmac('sha256', privateKey).update(stringMeantForSigning).digest('base64')
let headers = {
"SalesCloud-Application": appUUID,
"SalesCloud-Application-Public-Key": publicKey,
"Authorization": "App " + SIGNED,
"SalesCloud-Organization": organizationUUID
}
return headers
}
function SendData() {
let query = 'mutation createLog($log: NewLog!) {createLog(log: $log)}'
let variables = { log: { msg: "hello!" } }
const headers = CreateHeaders(query, variables)
let response = axios.post(
"https://graph.salescloud.is",
{ query: query, variables: variables },
{
timeout: 10000,
headers: { ...headers, 'content-type': 'application/json' },
},
).then((response) => {
return response
}).catch((error) => {
return error
})
console.dir(response)
}