Skip to content

Instantly share code, notes, and snippets.

@ortonomy
Created February 6, 2023 02:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ortonomy/fdfb2b92e04089aadd1440f8ff2cb5c8 to your computer and use it in GitHub Desktop.
Save ortonomy/fdfb2b92e04089aadd1440f8ff2cb5c8 to your computer and use it in GitHub Desktop.
Altair GraphQL client pre-request script for AWS Cognito confidential client login
const CryptoJS = await altair.importModule('crypto-js');
const b64Decode = await altair.importModule('atob');
const collectEnvironmentVariables = () => {
const clientId = altair.helpers.getEnvironment('AwsCognitoClientId')
const clientSecret = altair.helpers.getEnvironment('AwsCognitoClientSecret')
const region = altair.helpers.getEnvironment('AwsCognitoRegion')
const username = altair.helpers.getEnvironment('AwsCognitoUsername')
const password = altair.helpers.getEnvironment('AwsCognitoPassword')
if ( !clientId || !clientSecret || !region || !username || !password) {
altair.log("AWS Cognito set up is not complete. Missing ENV vars")
throw new Error("AWS Cognito set up is not complete. Missing ENV vars")
}
altair.log("AWS Inputs: " + JSON.stringify({
clientId,
clientSecret: Boolean(clientSecret),
region,
username,
password: Boolean(password)
}))
return {
clientId,
clientSecret,
region,
username,
password
}
}
const jwtPartLabels = new Map([
[0, 'algo'],
[1, 'content']
])
const decodeAWSCognitoJWTToken = jwtString => {
return jwtString.split('.').reduce((parts, next, i) => {
if (jwtPartLabels.has(i)) {
parts.set(jwtPartLabels.get(i), JSON.parse(atob(next)))
}
return parts
}, new Map())
}
const unixTimestampAtNow = () => {
return Math.round(Date.now() / 1000)
}
const isAWSCognitoJWTokenValid = jwtContent => {
const { exp } = jwtContent
return unixTimestampAtNow() < exp
}
const getRequestSecretHash = (requestSettings) => {
return CryptoJS.enc.Base64.stringify(
CryptoJS.HmacSHA256(
[requestSettings.username, requestSettings.clientId].join(''),
requestSettings.clientSecret
)
)
}
const getAWSCognitoAuthURI = (region) => {
return `https://cognito-idp.${region}.amazonaws.com`
}
const generateRequestBody = requestSettings => {
return {
AuthFlow: "USER_PASSWORD_AUTH",
ClientId: requestSettings.clientId,
AuthParameters: {
USERNAME: requestSettings.username,
PASSWORD: requestSettings.password,
SECRET_HASH: getRequestSecretHash(requestSettings)
}
}
}
const getNewAWSCognitoIdToken = async requestSettings => {
const { AuthenticationResult: { IdToken } } = await altair.helpers.request(
'POST',
getAWSCognitoAuthURI(requestSettings.region),
{
headers: {
"content-type": "application/x-amz-json-1.1",
"x-amz-target": "AWSCognitoIdentityProviderService.InitiateAuth",
},
body: JSON.stringify(generateRequestBody(requestSettings))
}
);
altair.log("Id token retrieved: " + IdToken)
return IdToken
}
const getExistingAWSCognitoSession = () => {
return localStorage.getItem("AWSCognitoIdToken") || null
}
const getSessionAWSCognitoToken = () => {
let token = getExistingAWSCognitoSession()
if ( !token || ( token && !isAWSCognitoJWTokenValid(token) ) ) {
// no existing session or it's expired, get a new one
token = getNewAWSCognitoIdToken(collectEnvironmentVariables())
}
return token
}
const addAuthenticationToRequest = async () => {
const token = await getSessionAWSCognitoToken()
altair.helpers.setEnvironment('AwsCognitoIdToken', token)
}
await addAuthenticationToRequest()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment