chore(plugin-cloud): refresh session on ExpiredToken error code (#8904)
Fixes https://github.com/payloadcms/payload/issues/8404 This code will refresh the session token upon receiving an `ExpiredToken` error when `storageClient.getObject()` receives that error. - The `Error Code` detected is determined by the error reported in the issue, and is an actual code from [AWS documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html) for Error Responses. - If the request fails again, the error is thrown.
This commit is contained in:
@@ -1,19 +1,13 @@
|
|||||||
|
import type * as AWS from '@aws-sdk/client-s3'
|
||||||
import type { CognitoUserSession } from 'amazon-cognito-identity-js'
|
import type { CognitoUserSession } from 'amazon-cognito-identity-js'
|
||||||
|
|
||||||
import { CognitoIdentityClient } from '@aws-sdk/client-cognito-identity'
|
import type { GetStorageClient } from './refreshSession.js'
|
||||||
import * as AWS from '@aws-sdk/client-s3'
|
|
||||||
import { fromCognitoIdentityPool } from '@aws-sdk/credential-providers'
|
|
||||||
|
|
||||||
import { authAsCognitoUser } from './authAsCognitoUser.js'
|
import { refreshSession } from './refreshSession.js'
|
||||||
|
|
||||||
export type GetStorageClient = () => Promise<{
|
export let storageClient: AWS.S3 | null = null
|
||||||
identityID: string
|
export let session: CognitoUserSession | null = null
|
||||||
storageClient: AWS.S3
|
export let identityID: string
|
||||||
}>
|
|
||||||
|
|
||||||
let storageClient: AWS.S3 | null = null
|
|
||||||
let session: CognitoUserSession | null = null
|
|
||||||
let identityID: string
|
|
||||||
|
|
||||||
export const getStorageClient: GetStorageClient = async () => {
|
export const getStorageClient: GetStorageClient = async () => {
|
||||||
if (storageClient && session?.isValid()) {
|
if (storageClient && session?.isValid()) {
|
||||||
@@ -23,6 +17,8 @@ export const getStorageClient: GetStorageClient = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
;({ identityID, session, storageClient } = await refreshSession())
|
||||||
|
|
||||||
if (!process.env.PAYLOAD_CLOUD_PROJECT_ID) {
|
if (!process.env.PAYLOAD_CLOUD_PROJECT_ID) {
|
||||||
throw new Error('PAYLOAD_CLOUD_PROJECT_ID is required')
|
throw new Error('PAYLOAD_CLOUD_PROJECT_ID is required')
|
||||||
}
|
}
|
||||||
@@ -33,34 +29,6 @@ export const getStorageClient: GetStorageClient = async () => {
|
|||||||
throw new Error('PAYLOAD_CLOUD_COGNITO_IDENTITY_POOL_ID is required')
|
throw new Error('PAYLOAD_CLOUD_COGNITO_IDENTITY_POOL_ID is required')
|
||||||
}
|
}
|
||||||
|
|
||||||
session = await authAsCognitoUser(
|
|
||||||
process.env.PAYLOAD_CLOUD_PROJECT_ID,
|
|
||||||
process.env.PAYLOAD_CLOUD_COGNITO_PASSWORD,
|
|
||||||
)
|
|
||||||
|
|
||||||
const cognitoIdentity = new CognitoIdentityClient({
|
|
||||||
credentials: fromCognitoIdentityPool({
|
|
||||||
clientConfig: {
|
|
||||||
region: 'us-east-1',
|
|
||||||
},
|
|
||||||
identityPoolId: process.env.PAYLOAD_CLOUD_COGNITO_IDENTITY_POOL_ID,
|
|
||||||
logins: {
|
|
||||||
[`cognito-idp.us-east-1.amazonaws.com/${process.env.PAYLOAD_CLOUD_COGNITO_USER_POOL_ID}`]:
|
|
||||||
session.getIdToken().getJwtToken(),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
|
|
||||||
const credentials = await cognitoIdentity.config.credentials()
|
|
||||||
|
|
||||||
// @ts-expect-error - Incorrect AWS types
|
|
||||||
identityID = credentials.identityId
|
|
||||||
|
|
||||||
storageClient = new AWS.S3({
|
|
||||||
credentials,
|
|
||||||
region: process.env.PAYLOAD_CLOUD_BUCKET_REGION,
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
identityID,
|
identityID,
|
||||||
storageClient,
|
storageClient,
|
||||||
|
|||||||
46
packages/payload-cloud/src/utilities/refreshSession.ts
Normal file
46
packages/payload-cloud/src/utilities/refreshSession.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { CognitoIdentityClient } from '@aws-sdk/client-cognito-identity'
|
||||||
|
import * as AWS from '@aws-sdk/client-s3'
|
||||||
|
import { fromCognitoIdentityPool } from '@aws-sdk/credential-providers'
|
||||||
|
|
||||||
|
import { authAsCognitoUser } from './authAsCognitoUser.js'
|
||||||
|
|
||||||
|
export type GetStorageClient = () => Promise<{
|
||||||
|
identityID: string
|
||||||
|
storageClient: AWS.S3
|
||||||
|
}>
|
||||||
|
|
||||||
|
export const refreshSession = async () => {
|
||||||
|
const session = await authAsCognitoUser(
|
||||||
|
process.env.PAYLOAD_CLOUD_PROJECT_ID || '',
|
||||||
|
process.env.PAYLOAD_CLOUD_COGNITO_PASSWORD || '',
|
||||||
|
)
|
||||||
|
|
||||||
|
const cognitoIdentity = new CognitoIdentityClient({
|
||||||
|
credentials: fromCognitoIdentityPool({
|
||||||
|
clientConfig: {
|
||||||
|
region: 'us-east-1',
|
||||||
|
},
|
||||||
|
identityPoolId: process.env.PAYLOAD_CLOUD_COGNITO_IDENTITY_POOL_ID || '',
|
||||||
|
logins: {
|
||||||
|
[`cognito-idp.us-east-1.amazonaws.com/${process.env.PAYLOAD_CLOUD_COGNITO_USER_POOL_ID}`]:
|
||||||
|
session.getIdToken().getJwtToken(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
const credentials = await cognitoIdentity.config.credentials()
|
||||||
|
|
||||||
|
// @ts-expect-error - Incorrect AWS types
|
||||||
|
const identityID = credentials.identityId
|
||||||
|
|
||||||
|
const storageClient = new AWS.S3({
|
||||||
|
credentials,
|
||||||
|
region: process.env.PAYLOAD_CLOUD_BUCKET_REGION,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
identityID,
|
||||||
|
session,
|
||||||
|
storageClient,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user