Open Abdulmalick-Dimnang opened 8 months ago
Hello, @Abdulmalick-Dimnang 👋. I've marked this as a feature request and it appears to have some aspects of version parity from v4 to v6 as you found. Let me review this with the team internally, and I'll follow up with any questions from here.
@Abdulmalick-Dimnang, are you able to share some more details on how you were achieving this in v4 with Amplify? I don't see where we documented this anywhere in the v4 or v5 code base.
hi @cwomack
we had to patch "@aws-amplify+auth+4.6.6.patch" as follows
diff --git a/node_modules/@aws-amplify/auth/lib-esm/Auth.js b/node_modules/@aws-amplify/auth/lib-esm/Auth.js
index 8fffcfa..57054b4 100644
--- a/node_modules/@aws-amplify/auth/lib-esm/Auth.js
+++ b/node_modules/@aws-amplify/auth/lib-esm/Auth.js
@@ -152,7 +152,7 @@ var AuthClass = /** @class */ (function () {
logger.debug('configure Auth');
var conf = Object.assign({}, this._config, Parser.parseMobilehubConfig(config).Auth, config);
this._config = conf;
- var _a = this._config, userPoolId = _a.userPoolId, userPoolWebClientId = _a.userPoolWebClientId, cookieStorage = _a.cookieStorage, oauth = _a.oauth, region = _a.region, identityPoolId = _a.identityPoolId, mandatorySignIn = _a.mandatorySignIn, refreshHandlers = _a.refreshHandlers, identityPoolRegion = _a.identityPoolRegion, clientMetadata = _a.clientMetadata, endpoint = _a.endpoint;
+ var _a = this._config, userPoolId = _a.userPoolId, userPoolWebClientId = _a.userPoolWebClientId, cookieStorage = _a.cookieStorage, oauth = _a.oauth, region = _a.region, identityPoolId = _a.identityPoolId, mandatorySignIn = _a.mandatorySignIn, refreshHandlers = _a.refreshHandlers, identityPoolRegion = _a.identityPoolRegion, clientMetadata = _a.clientMetadata, endpoint = _a.endpoint, headersInterceptor = _a.headersInterceptor;
if (!this._config.storage) {
// backward compatability
if (cookieStorage)
@@ -181,7 +181,7 @@ var AuthClass = /** @class */ (function () {
endpoint: endpoint,
};
userPoolData.Storage = this._storage;
- this.userPool = new CognitoUserPool(userPoolData, this.wrapRefreshSessionCallback);
+ this.userPool = new CognitoUserPool(userPoolData, this.wrapRefreshSessionCallback, headersInterceptor);
}
this.Credentials.configure({
mandatorySignIn: mandatorySignIn,
and "amazon-cognito-identity-js+5.2.10.patch"
diff --git a/node_modules/amazon-cognito-identity-js/src/Client.js b/node_modules/amazon-cognito-identity-js/src/Client.js
index ebdbb64..42db2f4 100644
--- a/node_modules/amazon-cognito-identity-js/src/Client.js
+++ b/node_modules/amazon-cognito-identity-js/src/Client.js
@@ -19,10 +19,11 @@ export default class Client {
* @param {string} endpoint endpoint
* @param {object} fetchOptions options for fetch API (only credentials is supported)
*/
- constructor(region, endpoint, fetchOptions) {
+ constructor(region, endpoint, fetchOptions, headersInterceptor) {
this.endpoint = endpoint || `https://cognito-idp.${region}.amazonaws.com/`;
const { credentials } = fetchOptions || {};
this.fetchOptions = credentials ? { credentials } : {};
+ this.headersInterceptor = headersInterceptor;
}
/**
@@ -71,75 +72,77 @@ export default class Client {
* @returns {void}
*/
request(operation, params, callback) {
- const headers = {
- 'Content-Type': 'application/x-amz-json-1.1',
- 'X-Amz-Target': `AWSCognitoIdentityProviderService.${operation}`,
- 'X-Amz-User-Agent': UserAgent.prototype.userAgent,
- };
-
- const options = Object.assign({}, this.fetchOptions, {
- headers,
- method: 'POST',
- mode: 'cors',
- cache: 'no-cache',
- body: JSON.stringify(params),
- });
+ this.headersInterceptor(extraHeaders => {
+ const headers = {
+ 'Content-Type': 'application/x-amz-json-1.1',
+ 'X-Amz-Target': `AWSCognitoIdentityProviderService.${operation}`,
+ 'X-Amz-User-Agent': UserAgent.prototype.userAgent,
+ ...extraHeaders
+ };
+ const options = Object.assign({}, this.fetchOptions, {
+ headers,
+ method: 'POST',
+ mode: 'cors',
+ cache: 'no-cache',
+ body: JSON.stringify(params),
+ });
- let response;
- let responseJsonData;
-
- fetch(this.endpoint, options)
- .then(
- resp => {
- response = resp;
- return resp;
- },
- err => {
- // If error happens here, the request failed
- // if it is TypeError throw network error
- if (err instanceof TypeError) {
- throw new Error('Network error');
+ let response;
+ let responseJsonData;
+
+ fetch(this.endpoint, options)
+ .then(
+ resp => {
+ response = resp;
+ return resp;
+ },
+ err => {
+ // If error happens here, the request failed
+ // if it is TypeError throw network error
+ if (err instanceof TypeError) {
+ throw new Error('Network error');
+ }
+ throw err;
}
- throw err;
- }
- )
- .then(resp => resp.json().catch(() => ({})))
- .then(data => {
- // return parsed body stream
- if (response.ok) return callback(null, data);
- responseJsonData = data;
-
- // Taken from aws-sdk-js/lib/protocol/json.js
- // eslint-disable-next-line no-underscore-dangle
- const code = (data.__type || data.code).split('#').pop();
- const error = new Error(data.message || data.Message || null)
- error.name = code
- error.code = code
- return callback(error);
- })
- .catch(err => {
- // first check if we have a service error
- if (
- response &&
- response.headers &&
- response.headers.get('x-amzn-errortype')
- ) {
- try {
- const code = response.headers.get('x-amzn-errortype').split(':')[0];
- const error = new Error(response.status ? response.status.toString() : null)
- error.code = code
- error.name = code
- error.statusCode = response.status
- return callback(error);
- } catch (ex) {
- return callback(err);
+ )
+ .then(resp => resp.json().catch(() => ({})))
+ .then(data => {
+ // return parsed body stream
+ if (response.ok) return callback(null, data);
+ responseJsonData = data;
+
+ // Taken from aws-sdk-js/lib/protocol/json.js
+ // eslint-disable-next-line no-underscore-dangle
+ const code = (data.__type || data.code).split('#').pop();
+ const error = new Error(data.message || data.Message || null)
+ error.name = code
+ error.code = code
+ return callback(error);
+ })
+ .catch(err => {
+ // first check if we have a service error
+ if (
+ response &&
+ response.headers &&
+ response.headers.get('x-amzn-errortype')
+ ) {
+ try {
+ const code = response.headers.get('x-amzn-errortype').split(':')[0];
+ const error = new Error(response.status ? response.status.toString() : null)
+ error.code = code
+ error.name = code
+ error.statusCode = response.status
+ return callback(error);
+ } catch (ex) {
+ return callback(err);
+ }
+ // otherwise check if error is Network error
+ } else if (err instanceof Error && err.message === 'Network error') {
+ err.code = 'NetworkError'
}
- // otherwise check if error is Network error
- } else if (err instanceof Error && err.message === 'Network error') {
- err.code = 'NetworkError'
- }
- return callback(err);
- });
+ return callback(err);
+ });
+ });
}
}
diff --git a/node_modules/amazon-cognito-identity-js/src/CognitoUserPool.js b/node_modules/amazon-cognito-identity-js/src/CognitoUserPool.js
index 87a134c..b1246e5 100644
--- a/node_modules/amazon-cognito-identity-js/src/CognitoUserPool.js
+++ b/node_modules/amazon-cognito-identity-js/src/CognitoUserPool.js
@@ -25,7 +25,7 @@ export default class CognitoUserPool {
* to support cognito advanced security features. By default, this
* flag is set to true.
*/
- constructor(data, wrapRefreshSessionCallback) {
+ constructor(data, wrapRefreshSessionCallback, headersInterceptor) {
const {
UserPoolId,
ClientId,
@@ -44,7 +44,7 @@ export default class CognitoUserPool {
this.userPoolId = UserPoolId;
this.clientId = ClientId;
- this.client = new Client(region, endpoint, fetchOptions);
+ this.client = new Client(region, endpoint, fetchOptions, headersInterceptor);
/**
* By default, AdvancedSecurityDataCollectionFlag is set to true,
apologies for now clearing it up, even with v4 it's not possible unless we have to patch it 🙏
Related to #12308
@cwomack just to follow up, this update might not be in the near road map?
We also have this issue
@Abdulmalick-Dimnang and @yonatanganot (as well as anyone else following this issue), wanted to provide a quick response here and let you know we haven't forgotten about this.
While there are no updates for this feature request at this point, it's still on our radar. If there's any progress to report, I'll follow up with a comment as soon as possible! Appreciate your patience.
Hello @cwomack
May I please know if there is any workarounds for this since it is supported in aws-sdk but not in amplify?
Thanks
@ThisisBada, the only way to implement a workaround is to patch the node_modules
(similar to what @Abdulmalick-Dimnang did in the comment above). However, that comment/patch is only viable for v5 since the amazon-cognito-identity-js
package is not used in v6. If you're on v6, you'd have to implement a similar patch/workaround.
Right now we don't have an ETA on a fix, but we'll update this issue once we have progress to communicate.
Is this related to a new or existing framework?
React Native
Is this related to a new or existing API?
Authentication
Is this related to another service?
No response
Describe the feature you'd like to request
Feature: Able to intercept authentication Cognito requests such as (signIn, signUp, signOut etc..) with custom headers
We know there's an option to intercept REST & GraphQL but we're looking forward to intercept Authentication requests. We believe we have searched the documentation but sadly it's not possible atm with V6
Our current use case is intercept custom headers to be able to send app check and WAF tokens to be able to validated in AWS cloudfront and we're migrating aws-amplify from V4 to V6 and we were able to intercept requests headers with v4 upon patching as follows with add "headersInterceptor" as a property to intercept with
For example, "signOut" authentication will run as follows
If there's a possible solution we would appreciate if someone can share it 🙏🏼
Describe the solution you'd like
It would be great to intercept authentication Cognito requests with custom headers while init Amplify as follows where "headers" would be an option to add your own custom headers
Describe alternatives you've considered
We haven't searched for any alternative except for keep using amplify v4 since we managed to patch aws-amplify & amazon-cognito-identity-js but we're looking for a clean solution where this option can be provided out of the box
Additional context
No response
Is this something that you'd be interested in working on?