Using Auth.currentCredentials() server side
See original GitHub issueWhich Category is your question related to?
Using Auth.currentCredentials()
server side.
What AWS Services are you utilising?
aws-amplify
, aws-appsync
Provide additional details e.g. code snippets
Hi!
I’m using AWSAppSyncClient
with my nuxt.js
project and I stumbled into an issue. I’m running nuxt
app in the AWS Lambda behind API Gateway.
When I’m using the AWSAppSyncClient
on the client side (in the browser) everything works as expected. However using it on the server side, the credentials returned by the Auth.currentCredentials()
are totally different than on the client side. This results in a 401
http error when querying the AppSync
.
I’m storing user credentials in the cookies and I’m passing them via request headers to the server side. I’ve also written the custom CredentialsStorage
class, so it can be used server and client side.
Code samples
CredentialsStorage
Used for storing credentials in the cookies. I’ve verified the getItem
returns the same result server and client side.
import * as Cookies from 'js-cookie'
// This implementation is based on the amazon-cognito-auth-js/es/CookieStorage.js
class CredentialsStorage {
constructor(req, params) {
this.logger = new Logger('CredentialsStorageLogger', 'DEBUG')
this.logger.debug('params: %j', params)
this.req = req
this.path = params.path
this.expires = params.expires
this.domain = params.domain
this.secure = params.secure
this.isClient = params.isClient
}
setItem(key, value) {
Cookies.set(key, value, {
path: this.path,
expires: this.expires,
domain: this.domain,
secure: this.secure,
})
return Cookies.get(key)
}
getItemClient(key) {
return Cookies.get(key)
}
getItemServer(passedKey) {
const req = this.req
const key = encodeURIComponent(passedKey) // there are @ symbols in the passedKey sometimes
const cookieItem = req.cookies && req.cookies[key]
this.logger.debug('key', key)
this.logger.debug('cookieItem', cookieItem)
return cookieItem
}
getItem(key) {
return this.isClient ? this.getItemClient(key) : this.getItemServer(key)
}
removeItem(key) {
return Cookies.remove(key, {
path: this.path,
domain: this.domain,
secure: this.secure,
})
}
clear() {
const cookies = Cookies.get()
for (let index = 0; index < cookies.length; ++index) {
Cookies.remove(cookies[index])
}
return {}
}
}
Auth configuration
This is how I configured the Auth:
req
- is coming from nuxtjs
and is a usual nodejs
request.
const credentialsStorage = new CredentialsStorage(req, {
domain: process.env.hostname, // example.com
path: '/',
expires: 365,
secure: process.env.isProduction, // true or false
isClient: process.client, // true or false
})
Auth.configure({
identityPoolId: process.env.awsCognitoIdentityPoolId, // eu-central-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
region: process.env.awsCognitoRegion, // eu-central-1
userPoolId: process.env.awsCognitoUserPoolId, // eu-central-1_XXXXXXXX
userPoolWebClientId: process.env.awsCognitoClientId, // cognito client id
authenticationFlowType: 'USER_PASSWORD_AUTH',
storage: credentialsStorage,
})
import { Auth } from 'aws-amplify'
const apolloDefaultClient = new AWSAppSyncClient(
{
url: process.env.awsAppsyncGraphqlEndpoint, // App sync url
region: process.env.awsAppsyncRegion, // eu-central-1
auth: {
type: 'AWS_IAM',
credentials: () => Auth.currentCredentials(),
},
disableOffline: true,
},
{
ssrMode: true,
},
)
Credentials received from Auth.currentCredentials() the client side
{
expired: false,
expireTime: 2019-03-01T13:21:51.000Z,
accessKeyId: 'XXXXXXXXXXXXXXXXXXXX',
sessionToken: 'some-session-token',
params:
{ IdentityPoolId: 'eu-central-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
Logins:
{ 'cognito-idp.eu-central-1.amazonaws.com/eu-central-1_XXXXXXXX': 'some-id-token' },
RoleSessionName: 'web-identity',
IdentityId: 'eu-central-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' },
data:
{ IdentityId: 'eu-central-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
Credentials:
{ AccessKeyId: 'XXXXXXXXXXXXXXXXXXXX',
SecretKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
SessionToken: 'some-session-token',
Expiration: 2019-03-01T13:21:51.000Z } },
_identityId: 'eu-central-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
_clientConfig: { region: 'eu-central-1' },
webIdentityCredentials:
WebIdentityCredentials {
expired: true,
expireTime: null,
accessKeyId: undefined,
sessionToken: undefined,
params:
{ IdentityPoolId: 'eu-central-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
Logins: [Object],
RoleSessionName: 'web-identity',
IdentityId: 'eu-central-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' },
data: null,
_clientConfig: { region: 'eu-central-1' } },
cognito:
Service {
config:
Config {
credentials: null,
credentialProvider: [Object],
region: 'eu-central-1',
logger: null,
apiVersions: {},
apiVersion: null,
endpoint: 'cognito-identity.eu-central-1.amazonaws.com',
httpOptions: [Object],
maxRetries: undefined,
maxRedirects: 10,
paramValidation: true,
sslEnabled: true,
s3ForcePathStyle: false,
s3BucketEndpoint: false,
s3DisableBodySigning: true,
computeChecksums: true,
convertResponseTypes: true,
correctClockSkew: false,
customUserAgent: 'aws-amplify/1.0.22 js',
dynamoDbCrc32: true,
systemClockOffset: 0,
signatureVersion: 'v4',
signatureCache: true,
retryDelayOptions: {},
useAccelerateEndpoint: false,
clientSideMonitoring: false,
params: [Object] },
isGlobalEndpoint: false,
endpoint:
Endpoint {
protocol: 'https:',
host: 'cognito-identity.eu-central-1.amazonaws.com',
port: 443,
hostname: 'cognito-identity.eu-central-1.amazonaws.com',
pathname: '/',
path: '/',
href: 'https://cognito-identity.eu-central-1.amazonaws.com/' },
_events: { apiCallAttempt: [Array], apiCall: [Array] },
MONITOR_EVENTS_BUBBLE: [Function: EVENTS_BUBBLE],
CALL_EVENTS_BUBBLE: [Function: CALL_EVENTS_BUBBLE],
_clientId: 1 },
sts:
Service {
config:
Config {
credentials: null,
credentialProvider: [Object],
region: 'eu-central-1',
logger: null,
apiVersions: {},
apiVersion: null,
endpoint: 'https://sts.amazonaws.com',
httpOptions: [Object],
maxRetries: undefined,
maxRedirects: 10,
paramValidation: true,
sslEnabled: true,
s3ForcePathStyle: false,
s3BucketEndpoint: false,
s3DisableBodySigning: true,
computeChecksums: true,
convertResponseTypes: true,
correctClockSkew: false,
customUserAgent: 'aws-amplify/1.0.22 js',
dynamoDbCrc32: true,
systemClockOffset: 0,
signatureVersion: 'v4',
signatureCache: true,
retryDelayOptions: {},
useAccelerateEndpoint: false,
clientSideMonitoring: false },
isGlobalEndpoint: true,
endpoint:
Endpoint {
protocol: 'https:',
host: 'sts.amazonaws.com',
port: 443,
hostname: 'sts.amazonaws.com',
pathname: '/',
path: '/',
href: 'https://sts.amazonaws.com/' },
_events: { apiCallAttempt: [Array], apiCall: [Array] },
MONITOR_EVENTS_BUBBLE: [Function: EVENTS_BUBBLE],
CALL_EVENTS_BUBBLE: [Function: CALL_EVENTS_BUBBLE],
_clientId: 2 },
authenticated: true }
Credentials received from Auth.currentCredentials() the server side
{
expired: false,
expireTime: null,
accessKeyId: 'XXXXXXXXXXXXXXXX',
sessionToken: 'some-session-token',
envPrefix: 'AWS' }
As you can see credentials on the server side are missing these params:
- data
- webIdentityCredentials
- cognito
I am however unable to reproduce this issue locally. It only happens in the lambda. Thank you for any idea / hint you might have.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:1
- Comments:12
Top GitHub Comments
actually calling
Auth.currentUserCredentials()
instead ofAuth.currentCredentials()
did the trick for me.@mihaerzen imo you do get different credentials on the server, because your lambda environment has credentials from the current lambda role. and the same should be the case for a fargate container.
Also if you look into the sourcecode of the amplify Auth.ts (thats how i found the solution) you can see that just using
currentCredentials()
does not set the credentials according to the amplify auth configuration, while the methodcurrentUserCredentials()
does.So if you configure the auth store properly on the server, so the server side can read it, there should be no issues with using the
Auth.currentUserCredentials()
method i guess.