Created
February 6, 2023 02:17
-
-
Save ortonomy/fdfb2b92e04089aadd1440f8ff2cb5c8 to your computer and use it in GitHub Desktop.
Altair GraphQL client pre-request script for AWS Cognito confidential client login
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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