aws-rum-web
Advanced tools
Comparing version 1.16.1 to 1.16.2
@@ -5,2 +5,10 @@ # Changelog | ||
### [1.16.2](https://github.com/aws-observability/aws-rum-web/compare/v1.16.1...v1.16.2) (2024-01-30) | ||
### Bug Fixes | ||
* Invalidate cognito identity and re-try ([#498](https://github.com/aws-observability/aws-rum-web/issues/498)) ([afe87e8](https://github.com/aws-observability/aws-rum-web/commit/afe87e8949da1826991591c20139bbf5407e2add)) | ||
* Record 0 for headerSize if transferSize is 0 ([#496](https://github.com/aws-observability/aws-rum-web/issues/496)) ([6773ffa](https://github.com/aws-observability/aws-rum-web/commit/6773ffabdf699b913f712d455db97eabebb7aa4b)) | ||
### [1.16.1](https://github.com/aws-observability/aws-rum-web/compare/v1.16.0...v1.16.1) (2023-12-13) | ||
@@ -7,0 +15,0 @@ |
@@ -0,8 +1,8 @@ | ||
import { CognitoIdentityClient } from './CognitoIdentityClient'; | ||
import { Config } from '../orchestration/Orchestration'; | ||
import { Credentials } from '@aws-sdk/types'; | ||
export declare class Authentication { | ||
private cognitoIdentityClient; | ||
private stsClient; | ||
private config; | ||
private credentials; | ||
import { AwsCredentialIdentity } from '@aws-sdk/types'; | ||
export declare abstract class Authentication { | ||
protected cognitoIdentityClient: CognitoIdentityClient; | ||
protected config: Config; | ||
protected credentials: AwsCredentialIdentity | undefined; | ||
constructor(config: Config); | ||
@@ -18,3 +18,3 @@ /** | ||
* | ||
* While storing credentials in localStorage puts the cookie at greater risk of being leaked through an | ||
* While storing credentials in localStorage puts the credential at greater risk of being leaked through an | ||
* XSS attack, there is no impact if the credentials were to be leaked. This is because (1) the identity pool ID | ||
@@ -37,9 +37,9 @@ * and role ARN are public and (2) the credentials are for an anonymous (guest) user. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
ChainAnonymousCredentialsProvider: () => Promise<Credentials>; | ||
ChainAnonymousCredentialsProvider: () => Promise<AwsCredentialIdentity>; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from a member variable. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
@@ -50,15 +50,18 @@ private AnonymousCredentialsProvider; | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
private AnonymousStorageCredentialsProvider; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's basic | ||
* (classic) authflow. | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's enhanced | ||
* authflow. | ||
* | ||
* See https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
private AnonymousCognitoCredentialsProvider; | ||
protected abstract AnonymousCognitoCredentialsProvider: () => Promise<AwsCredentialIdentity>; | ||
/** | ||
* Returns {@code true} when the credentials need to be renewed. | ||
*/ | ||
private renewCredentials; | ||
} |
@@ -53,3 +53,2 @@ "use strict"; | ||
var fetch_http_handler_1 = require("@aws-sdk/fetch-http-handler"); | ||
var StsClient_1 = require("./StsClient"); | ||
var constants_1 = require("../utils/constants"); | ||
@@ -68,3 +67,3 @@ var Authentication = /** @class */ (function () { | ||
* | ||
* While storing credentials in localStorage puts the cookie at greater risk of being leaked through an | ||
* While storing credentials in localStorage puts the credential at greater risk of being leaked through an | ||
* XSS attack, there is no impact if the credentials were to be leaked. This is because (1) the identity pool ID | ||
@@ -87,3 +86,3 @@ * and role ARN are public and (2) the credentials are for an anonymous (guest) user. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
@@ -100,3 +99,3 @@ this.ChainAnonymousCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
@@ -118,3 +117,3 @@ this.AnonymousCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
@@ -145,45 +144,4 @@ this.AnonymousStorageCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
}); }; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's basic | ||
* (classic) authflow. | ||
* | ||
* See https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
this.AnonymousCognitoCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, this.cognitoIdentityClient | ||
.getId({ | ||
IdentityPoolId: this.config.identityPoolId | ||
}) | ||
.then(function (getIdResponse) { | ||
return _this.cognitoIdentityClient.getOpenIdToken(getIdResponse); | ||
}) | ||
.then(function (getOpenIdTokenResponse) { | ||
return _this.stsClient.assumeRoleWithWebIdentity({ | ||
RoleArn: _this.config.guestRoleArn, | ||
RoleSessionName: 'cwr', | ||
WebIdentityToken: getOpenIdTokenResponse.Token | ||
}); | ||
}) | ||
.then(function (credentials) { | ||
_this.credentials = credentials; | ||
try { | ||
localStorage.setItem(constants_1.CRED_KEY, JSON.stringify(credentials)); | ||
} | ||
catch (e) { | ||
// Ignore | ||
} | ||
return credentials; | ||
})]; | ||
}); | ||
}); }; | ||
var region = config.identityPoolId.split(':')[0]; | ||
this.config = config; | ||
this.stsClient = new StsClient_1.StsClient({ | ||
fetchRequestHandler: new fetch_http_handler_1.FetchHttpHandler(), | ||
region: region | ||
}); | ||
this.cognitoIdentityClient = new CognitoIdentityClient_1.CognitoIdentityClient({ | ||
@@ -194,2 +152,5 @@ fetchRequestHandler: new fetch_http_handler_1.FetchHttpHandler(), | ||
} | ||
/** | ||
* Returns {@code true} when the credentials need to be renewed. | ||
*/ | ||
Authentication.prototype.renewCredentials = function () { | ||
@@ -196,0 +157,0 @@ if (!this.credentials || !this.credentials.expiration) { |
import { HttpHandler } from '@aws-sdk/protocol-http'; | ||
import { Credentials } from '@aws-sdk/types'; | ||
import { AwsCredentialIdentity } from '@aws-sdk/types'; | ||
interface OpenIdTokenResponse { | ||
@@ -24,3 +24,4 @@ IdentityId: string; | ||
}) => Promise<OpenIdTokenResponse>; | ||
getCredentialsForIdentity: (identityId: string) => Promise<Credentials>; | ||
getCredentialsForIdentity: (identityId: string) => Promise<AwsCredentialIdentity>; | ||
private validateOpenIdTokenResponse; | ||
private validateCredenentialsResponse; | ||
@@ -27,0 +28,0 @@ private getHttpRequest; |
@@ -94,7 +94,7 @@ "use strict"; | ||
this.getOpenIdToken = function (request) { return __awaiter(_this, void 0, void 0, function () { | ||
var requestPayload, tokenRequest, response, e_2; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
var requestPayload, tokenRequest, response, _a, e_2; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_a.trys.push([0, 3, , 4]); | ||
_b.trys.push([0, 3, , 4]); | ||
requestPayload = JSON.stringify(request); | ||
@@ -104,7 +104,9 @@ tokenRequest = this.getHttpRequest(GET_TOKEN_TARGET, requestPayload); | ||
case 1: | ||
response = (_a.sent()).response; | ||
response = (_b.sent()).response; | ||
_a = this.validateOpenIdTokenResponse; | ||
return [4 /*yield*/, (0, utils_1.responseToJson)(response)]; | ||
case 2: return [2 /*return*/, (_a.sent())]; | ||
case 2: return [2 /*return*/, _a.apply(this, [_b.sent()])]; | ||
case 3: | ||
e_2 = _a.sent(); | ||
e_2 = _b.sent(); | ||
localStorage.removeItem(constants_1.IDENTITY_KEY); | ||
throw new Error("CWR: Failed to retrieve Cognito OpenId token: ".concat(e_2)); | ||
@@ -116,7 +118,7 @@ case 4: return [2 /*return*/]; | ||
this.getCredentialsForIdentity = function (identityId) { return __awaiter(_this, void 0, void 0, function () { | ||
var requestPayload, credentialRequest, response, credentialsResponse, Credentials, AccessKeyId, Expiration, SecretKey, SessionToken, e_3; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
var requestPayload, credentialRequest, response, _a, AccessKeyId, Expiration, SecretKey, SessionToken, _b, e_3; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
_a.trys.push([0, 3, , 4]); | ||
_c.trys.push([0, 3, , 4]); | ||
requestPayload = JSON.stringify({ IdentityId: identityId }); | ||
@@ -126,9 +128,7 @@ credentialRequest = this.getHttpRequest(GET_CREDENTIALS_TARGET, requestPayload); | ||
case 1: | ||
response = (_a.sent()).response; | ||
response = (_c.sent()).response; | ||
_b = this.validateCredenentialsResponse; | ||
return [4 /*yield*/, (0, utils_1.responseToJson)(response)]; | ||
case 2: | ||
credentialsResponse = (_a.sent()); | ||
this.validateCredenentialsResponse(credentialsResponse); | ||
Credentials = credentialsResponse.Credentials; | ||
AccessKeyId = Credentials.AccessKeyId, Expiration = Credentials.Expiration, SecretKey = Credentials.SecretKey, SessionToken = Credentials.SessionToken; | ||
_a = _b.apply(this, [_c.sent()]), AccessKeyId = _a.AccessKeyId, Expiration = _a.Expiration, SecretKey = _a.SecretKey, SessionToken = _a.SessionToken; | ||
return [2 /*return*/, { | ||
@@ -141,3 +141,4 @@ accessKeyId: AccessKeyId, | ||
case 3: | ||
e_3 = _a.sent(); | ||
e_3 = _c.sent(); | ||
localStorage.removeItem(constants_1.IDENTITY_KEY); | ||
throw new Error("CWR: Failed to retrieve credentials for Cognito identity: ".concat(e_3)); | ||
@@ -148,7 +149,7 @@ case 4: return [2 /*return*/]; | ||
}); }; | ||
this.validateCredenentialsResponse = function (cr) { | ||
if (cr && | ||
cr.__type && | ||
(cr.__type === 'ResourceNotFoundException' || | ||
cr.__type === 'ValidationException')) { | ||
this.validateOpenIdTokenResponse = function (r) { | ||
if ('IdentityId' in r && 'Token' in r) { | ||
return r; | ||
} | ||
else if (r && '__type' in r && 'message' in r) { | ||
// The request may have failed because of ValidationException or | ||
@@ -158,6 +159,25 @@ // ResourceNotFoundException, which means the identity Id is bad. In | ||
// be re-tried. | ||
localStorage.removeItem(constants_1.IDENTITY_KEY); | ||
throw new Error("".concat(cr.__type, ": ").concat(cr.message)); | ||
throw new Error("".concat(r.__type, ": ").concat(r.message)); | ||
} | ||
else { | ||
// We don't recognize ths response format. | ||
throw new Error('Unknown OpenIdToken response'); | ||
} | ||
}; | ||
this.validateCredenentialsResponse = function (r) { | ||
if ('IdentityId' in r && 'Credentials' in r) { | ||
return r.Credentials; | ||
} | ||
else if (r && '__type' in r && 'message' in r) { | ||
// The request may have failed because of ValidationException or | ||
// ResourceNotFoundException, which means the identity Id is bad. In | ||
// any case, we invalidate the identity Id so the entire process can | ||
// be re-tried. | ||
throw new Error("".concat(r.__type, ": ").concat(r.message)); | ||
} | ||
else { | ||
// We don't recognize ths response format. | ||
throw new Error('Unknown Credentials response'); | ||
} | ||
}; | ||
this.getHttpRequest = function (target, payload) { | ||
@@ -164,0 +184,0 @@ return new protocol_http_1.HttpRequest({ |
@@ -1,6 +0,6 @@ | ||
import { CredentialProvider, Credentials, HttpResponse } from '@aws-sdk/types'; | ||
import { AwsCredentialIdentityProvider, AwsCredentialIdentity, HttpResponse } from '@aws-sdk/types'; | ||
import { EventCache } from '../event-cache/EventCache'; | ||
import { DataPlaneClient } from './DataPlaneClient'; | ||
import { Config } from '../orchestration/Orchestration'; | ||
export declare type ClientBuilder = (endpoint: URL, region: string, credentials: CredentialProvider | Credentials | undefined) => DataPlaneClient; | ||
export declare type ClientBuilder = (endpoint: URL, region: string, credentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider) => DataPlaneClient; | ||
export declare class Dispatch { | ||
@@ -30,3 +30,3 @@ private region; | ||
*/ | ||
setAwsCredentials(credentialProvider: Credentials | CredentialProvider): void; | ||
setAwsCredentials(credentialProvider: AwsCredentialIdentity | AwsCredentialIdentityProvider): void; | ||
/** | ||
@@ -33,0 +33,0 @@ * Send meta data and events to the AWS RUM data plane service via fetch. |
import { Config } from '../orchestration/Orchestration'; | ||
import { Credentials } from '@aws-sdk/types'; | ||
export declare class EnhancedAuthentication { | ||
private cognitoIdentityClient; | ||
private config; | ||
private credentials; | ||
import { AwsCredentialIdentity } from '@aws-sdk/types'; | ||
import { Authentication } from './Authentication'; | ||
export declare class EnhancedAuthentication extends Authentication { | ||
constructor(config: Config); | ||
/** | ||
* A credential provider which provides AWS credentials for an anonymous | ||
* (guest) user. These credentials are retrieved from the first successful | ||
* provider in a chain. | ||
* | ||
* Credentials are stored in and retrieved from localStorage. This prevents the client from having to | ||
* re-authenticate every time the client loads, which (1) improves the performance of the RUM web client and (2) | ||
* reduces the load on AWS services Cognito and STS. | ||
* | ||
* While storing credentials in localStorage puts the credential at greater risk of being leaked through an | ||
* XSS attack, there is no impact if the credentials were to be leaked. This is because (1) the identity pool ID | ||
* and role ARN are public and (2) the credentials are for an anonymous (guest) user. | ||
* | ||
* Regarding (1), the identity pool ID and role ARN are, by necessity, public. These identifiers are shipped with | ||
* each application as part of Cognito's Basic (Classic) authentication flow. The identity pool ID and role ARN | ||
* are not secret. | ||
* | ||
* Regarding (2), the authentication chain implemented in this file only supports anonymous (guest) | ||
* authentication. When the Cognito authentication flow is executed, {@code AnonymousCognitoCredentialsProvider} | ||
* does not communicate with a login provider such as Amazon, Facebook or Google. Instead, it relies on (a) the | ||
* identity pool supporting unauthenticated identities and (b) the IAM role policy enabling login through the | ||
* identity pool. If the identity pool does not support unauthenticated identities, this authentication chain | ||
* will not succeed. | ||
* | ||
* Taken together, (1) and (2) mean that if these temporary credentials were to be leaked, the leaked credentials | ||
* would not allow a bad actor to gain access to anything which they did not already have public access to. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
ChainAnonymousCredentialsProvider: () => Promise<Credentials>; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from a member variable. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
private AnonymousCredentialsProvider; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from localStorage. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
private AnonymousStorageCredentialsProvider; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's enhanced | ||
@@ -56,6 +12,5 @@ * authflow. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
private AnonymousCognitoCredentialsProvider; | ||
private renewCredentials; | ||
protected AnonymousCognitoCredentialsProvider: () => Promise<AwsCredentialIdentity>; | ||
} |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -51,91 +55,9 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
exports.EnhancedAuthentication = void 0; | ||
var CognitoIdentityClient_1 = require("./CognitoIdentityClient"); | ||
var fetch_http_handler_1 = require("@aws-sdk/fetch-http-handler"); | ||
var constants_1 = require("../utils/constants"); | ||
var EnhancedAuthentication = /** @class */ (function () { | ||
var Authentication_1 = require("./Authentication"); | ||
var EnhancedAuthentication = /** @class */ (function (_super) { | ||
__extends(EnhancedAuthentication, _super); | ||
function EnhancedAuthentication(config) { | ||
var _this = this; | ||
var _this = _super.call(this, config) || this; | ||
/** | ||
* A credential provider which provides AWS credentials for an anonymous | ||
* (guest) user. These credentials are retrieved from the first successful | ||
* provider in a chain. | ||
* | ||
* Credentials are stored in and retrieved from localStorage. This prevents the client from having to | ||
* re-authenticate every time the client loads, which (1) improves the performance of the RUM web client and (2) | ||
* reduces the load on AWS services Cognito and STS. | ||
* | ||
* While storing credentials in localStorage puts the credential at greater risk of being leaked through an | ||
* XSS attack, there is no impact if the credentials were to be leaked. This is because (1) the identity pool ID | ||
* and role ARN are public and (2) the credentials are for an anonymous (guest) user. | ||
* | ||
* Regarding (1), the identity pool ID and role ARN are, by necessity, public. These identifiers are shipped with | ||
* each application as part of Cognito's Basic (Classic) authentication flow. The identity pool ID and role ARN | ||
* are not secret. | ||
* | ||
* Regarding (2), the authentication chain implemented in this file only supports anonymous (guest) | ||
* authentication. When the Cognito authentication flow is executed, {@code AnonymousCognitoCredentialsProvider} | ||
* does not communicate with a login provider such as Amazon, Facebook or Google. Instead, it relies on (a) the | ||
* identity pool supporting unauthenticated identities and (b) the IAM role policy enabling login through the | ||
* identity pool. If the identity pool does not support unauthenticated identities, this authentication chain | ||
* will not succeed. | ||
* | ||
* Taken together, (1) and (2) mean that if these temporary credentials were to be leaked, the leaked credentials | ||
* would not allow a bad actor to gain access to anything which they did not already have public access to. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
this.ChainAnonymousCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, this.AnonymousCredentialsProvider() | ||
.catch(this.AnonymousStorageCredentialsProvider) | ||
.catch(this.AnonymousCognitoCredentialsProvider)]; | ||
}); | ||
}); }; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from a member variable. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
this.AnonymousCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, new Promise(function (resolve, reject) { | ||
if (_this.renewCredentials()) { | ||
// The credentials have expired. | ||
return reject(); | ||
} | ||
resolve(_this.credentials); | ||
})]; | ||
}); | ||
}); }; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from localStorage. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
this.AnonymousStorageCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, new Promise(function (resolve, reject) { | ||
var credentials; | ||
try { | ||
credentials = JSON.parse(localStorage.getItem(constants_1.CRED_KEY)); | ||
} | ||
catch (e) { | ||
// Error decoding or parsing the cookie -- abort | ||
return reject(); | ||
} | ||
// The expiration property of Credentials has a date type. Because the date was serialized as a string, | ||
// we need to convert it back into a date, otherwise the AWS SDK signing middleware | ||
// (@aws-sdk/middleware-signing) will throw an exception and no credentials will be returned. | ||
_this.credentials = __assign(__assign({}, credentials), { expiration: new Date(credentials.expiration) }); | ||
if (_this.renewCredentials()) { | ||
// The credentials have expired. | ||
return reject(); | ||
} | ||
resolve(_this.credentials); | ||
})]; | ||
}); | ||
}); }; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's enhanced | ||
@@ -146,14 +68,25 @@ * authflow. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
this.AnonymousCognitoCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
var _this = this; | ||
_this.AnonymousCognitoCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
var retries, getIdResponse, credentials, e_1; | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, this.cognitoIdentityClient | ||
.getId({ IdentityPoolId: this.config.identityPoolId }) | ||
.then(function (getIdResponse) { | ||
return _this.cognitoIdentityClient.getCredentialsForIdentity(getIdResponse.IdentityId); | ||
}) | ||
.then(function (credentials) { | ||
_this.credentials = credentials; | ||
switch (_a.label) { | ||
case 0: | ||
retries = 1; | ||
_a.label = 1; | ||
case 1: | ||
if (!true) return [3 /*break*/, 7]; | ||
_a.label = 2; | ||
case 2: | ||
_a.trys.push([2, 5, , 6]); | ||
return [4 /*yield*/, this.cognitoIdentityClient.getId({ | ||
IdentityPoolId: this.config.identityPoolId | ||
})]; | ||
case 3: | ||
getIdResponse = _a.sent(); | ||
return [4 /*yield*/, this.cognitoIdentityClient.getCredentialsForIdentity(getIdResponse.IdentityId)]; | ||
case 4: | ||
credentials = _a.sent(); | ||
this.credentials = credentials; | ||
try { | ||
@@ -165,22 +98,21 @@ localStorage.setItem(constants_1.CRED_KEY, JSON.stringify(credentials)); | ||
} | ||
return credentials; | ||
})]; | ||
return [2 /*return*/, credentials]; | ||
case 5: | ||
e_1 = _a.sent(); | ||
if (retries) { | ||
retries--; | ||
} | ||
else { | ||
throw e_1; | ||
} | ||
return [3 /*break*/, 6]; | ||
case 6: return [3 /*break*/, 1]; | ||
case 7: return [2 /*return*/]; | ||
} | ||
}); | ||
}); }; | ||
var region = config.identityPoolId.split(':')[0]; | ||
this.config = config; | ||
this.cognitoIdentityClient = new CognitoIdentityClient_1.CognitoIdentityClient({ | ||
fetchRequestHandler: new fetch_http_handler_1.FetchHttpHandler(), | ||
region: region | ||
}); | ||
return _this; | ||
} | ||
EnhancedAuthentication.prototype.renewCredentials = function () { | ||
if (!this.credentials || !this.credentials.expiration) { | ||
return true; | ||
} | ||
var renewalTime = new Date(this.credentials.expiration.getTime() - constants_1.CRED_RENEW_MS); | ||
return new Date() > renewalTime; | ||
}; | ||
return EnhancedAuthentication; | ||
}()); | ||
}(Authentication_1.Authentication)); | ||
exports.EnhancedAuthentication = EnhancedAuthentication; |
import { CognitoIdentityClientConfig } from './CognitoIdentityClient'; | ||
import { Credentials } from '@aws-sdk/types'; | ||
import { AwsCredentialIdentity } from '@aws-sdk/types'; | ||
export interface STSSendRequest { | ||
@@ -12,3 +12,3 @@ RoleArn: string; | ||
constructor(config: CognitoIdentityClientConfig); | ||
assumeRoleWithWebIdentity: (request: STSSendRequest) => Promise<Credentials>; | ||
assumeRoleWithWebIdentity: (request: STSSendRequest) => Promise<AwsCredentialIdentity>; | ||
} |
@@ -19,3 +19,3 @@ "use strict"; | ||
var EventBus_1 = require("../event-bus/EventBus"); | ||
var webClientVersion = '1.16.1'; | ||
var webClientVersion = '1.16.2'; | ||
/** | ||
@@ -22,0 +22,0 @@ * A cache which stores events generated by telemetry plugins. |
import { Plugin } from '../plugins/Plugin'; | ||
import { TargetDomEvent } from '../plugins/event-plugins/DomEventPlugin'; | ||
import { ClientBuilder } from '../dispatch/Dispatch'; | ||
import { CredentialProvider, Credentials } from '@aws-sdk/types'; | ||
import { AwsCredentialIdentityProvider, AwsCredentialIdentity } from '@aws-sdk/types'; | ||
import { PageAttributes } from '../sessions/PageManager'; | ||
@@ -152,3 +152,3 @@ export declare enum TelemetryEnum { | ||
*/ | ||
setAwsCredentials(credentials: Credentials | CredentialProvider): void; | ||
setAwsCredentials(credentials: AwsCredentialIdentity | AwsCredentialIdentityProvider): void; | ||
/** | ||
@@ -155,0 +155,0 @@ * Set custom session attributes to add them to all event metadata. |
@@ -35,3 +35,3 @@ "use strict"; | ||
exports.Orchestration = exports.defaultConfig = exports.defaultCookieAttributes = exports.PageIdFormatEnum = exports.TelemetryEnum = void 0; | ||
var Authentication_1 = require("../dispatch/Authentication"); | ||
var BasicAuthentication_1 = require("../dispatch/BasicAuthentication"); | ||
var EnhancedAuthentication_1 = require("../dispatch/EnhancedAuthentication"); | ||
@@ -265,3 +265,3 @@ var PluginManager_1 = require("../plugins/PluginManager"); | ||
if (this.config.identityPoolId && this.config.guestRoleArn) { | ||
dispatch.setAwsCredentials(new Authentication_1.Authentication(this.config) | ||
dispatch.setAwsCredentials(new BasicAuthentication_1.BasicAuthentication(this.config) | ||
.ChainAnonymousCredentialsProvider); | ||
@@ -268,0 +268,0 @@ } |
@@ -191,3 +191,5 @@ "use strict"; | ||
duration: entryData.duration, | ||
headerSize: entryData.transferSize - entryData.encodedBodySize, | ||
headerSize: entryData.transferSize > 0 | ||
? entryData.transferSize - entryData.encodedBodySize | ||
: 0, | ||
transferSize: entryData.transferSize, | ||
@@ -194,0 +196,0 @@ compressionRatio: entryData.encodedBodySize > 0 |
@@ -0,8 +1,8 @@ | ||
import { CognitoIdentityClient } from './CognitoIdentityClient'; | ||
import { Config } from '../orchestration/Orchestration'; | ||
import { Credentials } from '@aws-sdk/types'; | ||
export declare class Authentication { | ||
private cognitoIdentityClient; | ||
private stsClient; | ||
private config; | ||
private credentials; | ||
import { AwsCredentialIdentity } from '@aws-sdk/types'; | ||
export declare abstract class Authentication { | ||
protected cognitoIdentityClient: CognitoIdentityClient; | ||
protected config: Config; | ||
protected credentials: AwsCredentialIdentity | undefined; | ||
constructor(config: Config); | ||
@@ -18,3 +18,3 @@ /** | ||
* | ||
* While storing credentials in localStorage puts the cookie at greater risk of being leaked through an | ||
* While storing credentials in localStorage puts the credential at greater risk of being leaked through an | ||
* XSS attack, there is no impact if the credentials were to be leaked. This is because (1) the identity pool ID | ||
@@ -37,9 +37,9 @@ * and role ARN are public and (2) the credentials are for an anonymous (guest) user. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
ChainAnonymousCredentialsProvider: () => Promise<Credentials>; | ||
ChainAnonymousCredentialsProvider: () => Promise<AwsCredentialIdentity>; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from a member variable. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
@@ -50,15 +50,18 @@ private AnonymousCredentialsProvider; | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
private AnonymousStorageCredentialsProvider; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's basic | ||
* (classic) authflow. | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's enhanced | ||
* authflow. | ||
* | ||
* See https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
private AnonymousCognitoCredentialsProvider; | ||
protected abstract AnonymousCognitoCredentialsProvider: () => Promise<AwsCredentialIdentity>; | ||
/** | ||
* Returns {@code true} when the credentials need to be renewed. | ||
*/ | ||
private renewCredentials; | ||
} |
@@ -50,3 +50,2 @@ var __assign = (this && this.__assign) || function () { | ||
import { FetchHttpHandler } from '@aws-sdk/fetch-http-handler'; | ||
import { StsClient } from './StsClient'; | ||
import { CRED_KEY, CRED_RENEW_MS } from '../utils/constants'; | ||
@@ -65,3 +64,3 @@ var Authentication = /** @class */ (function () { | ||
* | ||
* While storing credentials in localStorage puts the cookie at greater risk of being leaked through an | ||
* While storing credentials in localStorage puts the credential at greater risk of being leaked through an | ||
* XSS attack, there is no impact if the credentials were to be leaked. This is because (1) the identity pool ID | ||
@@ -84,3 +83,3 @@ * and role ARN are public and (2) the credentials are for an anonymous (guest) user. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
@@ -97,3 +96,3 @@ this.ChainAnonymousCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
@@ -115,3 +114,3 @@ this.AnonymousCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
@@ -142,45 +141,4 @@ this.AnonymousStorageCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
}); }; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's basic | ||
* (classic) authflow. | ||
* | ||
* See https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
this.AnonymousCognitoCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, this.cognitoIdentityClient | ||
.getId({ | ||
IdentityPoolId: this.config.identityPoolId | ||
}) | ||
.then(function (getIdResponse) { | ||
return _this.cognitoIdentityClient.getOpenIdToken(getIdResponse); | ||
}) | ||
.then(function (getOpenIdTokenResponse) { | ||
return _this.stsClient.assumeRoleWithWebIdentity({ | ||
RoleArn: _this.config.guestRoleArn, | ||
RoleSessionName: 'cwr', | ||
WebIdentityToken: getOpenIdTokenResponse.Token | ||
}); | ||
}) | ||
.then(function (credentials) { | ||
_this.credentials = credentials; | ||
try { | ||
localStorage.setItem(CRED_KEY, JSON.stringify(credentials)); | ||
} | ||
catch (e) { | ||
// Ignore | ||
} | ||
return credentials; | ||
})]; | ||
}); | ||
}); }; | ||
var region = config.identityPoolId.split(':')[0]; | ||
this.config = config; | ||
this.stsClient = new StsClient({ | ||
fetchRequestHandler: new FetchHttpHandler(), | ||
region: region | ||
}); | ||
this.cognitoIdentityClient = new CognitoIdentityClient({ | ||
@@ -191,2 +149,5 @@ fetchRequestHandler: new FetchHttpHandler(), | ||
} | ||
/** | ||
* Returns {@code true} when the credentials need to be renewed. | ||
*/ | ||
Authentication.prototype.renewCredentials = function () { | ||
@@ -193,0 +154,0 @@ if (!this.credentials || !this.credentials.expiration) { |
import { HttpHandler } from '@aws-sdk/protocol-http'; | ||
import { Credentials } from '@aws-sdk/types'; | ||
import { AwsCredentialIdentity } from '@aws-sdk/types'; | ||
interface OpenIdTokenResponse { | ||
@@ -24,3 +24,4 @@ IdentityId: string; | ||
}) => Promise<OpenIdTokenResponse>; | ||
getCredentialsForIdentity: (identityId: string) => Promise<Credentials>; | ||
getCredentialsForIdentity: (identityId: string) => Promise<AwsCredentialIdentity>; | ||
private validateOpenIdTokenResponse; | ||
private validateCredenentialsResponse; | ||
@@ -27,0 +28,0 @@ private getHttpRequest; |
@@ -91,7 +91,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
this.getOpenIdToken = function (request) { return __awaiter(_this, void 0, void 0, function () { | ||
var requestPayload, tokenRequest, response, e_2; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
var requestPayload, tokenRequest, response, _a, e_2; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_a.trys.push([0, 3, , 4]); | ||
_b.trys.push([0, 3, , 4]); | ||
requestPayload = JSON.stringify(request); | ||
@@ -101,7 +101,9 @@ tokenRequest = this.getHttpRequest(GET_TOKEN_TARGET, requestPayload); | ||
case 1: | ||
response = (_a.sent()).response; | ||
response = (_b.sent()).response; | ||
_a = this.validateOpenIdTokenResponse; | ||
return [4 /*yield*/, responseToJson(response)]; | ||
case 2: return [2 /*return*/, (_a.sent())]; | ||
case 2: return [2 /*return*/, _a.apply(this, [_b.sent()])]; | ||
case 3: | ||
e_2 = _a.sent(); | ||
e_2 = _b.sent(); | ||
localStorage.removeItem(IDENTITY_KEY); | ||
throw new Error("CWR: Failed to retrieve Cognito OpenId token: ".concat(e_2)); | ||
@@ -113,7 +115,7 @@ case 4: return [2 /*return*/]; | ||
this.getCredentialsForIdentity = function (identityId) { return __awaiter(_this, void 0, void 0, function () { | ||
var requestPayload, credentialRequest, response, credentialsResponse, Credentials, AccessKeyId, Expiration, SecretKey, SessionToken, e_3; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
var requestPayload, credentialRequest, response, _a, AccessKeyId, Expiration, SecretKey, SessionToken, _b, e_3; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
_a.trys.push([0, 3, , 4]); | ||
_c.trys.push([0, 3, , 4]); | ||
requestPayload = JSON.stringify({ IdentityId: identityId }); | ||
@@ -123,9 +125,7 @@ credentialRequest = this.getHttpRequest(GET_CREDENTIALS_TARGET, requestPayload); | ||
case 1: | ||
response = (_a.sent()).response; | ||
response = (_c.sent()).response; | ||
_b = this.validateCredenentialsResponse; | ||
return [4 /*yield*/, responseToJson(response)]; | ||
case 2: | ||
credentialsResponse = (_a.sent()); | ||
this.validateCredenentialsResponse(credentialsResponse); | ||
Credentials = credentialsResponse.Credentials; | ||
AccessKeyId = Credentials.AccessKeyId, Expiration = Credentials.Expiration, SecretKey = Credentials.SecretKey, SessionToken = Credentials.SessionToken; | ||
_a = _b.apply(this, [_c.sent()]), AccessKeyId = _a.AccessKeyId, Expiration = _a.Expiration, SecretKey = _a.SecretKey, SessionToken = _a.SessionToken; | ||
return [2 /*return*/, { | ||
@@ -138,3 +138,4 @@ accessKeyId: AccessKeyId, | ||
case 3: | ||
e_3 = _a.sent(); | ||
e_3 = _c.sent(); | ||
localStorage.removeItem(IDENTITY_KEY); | ||
throw new Error("CWR: Failed to retrieve credentials for Cognito identity: ".concat(e_3)); | ||
@@ -145,7 +146,7 @@ case 4: return [2 /*return*/]; | ||
}); }; | ||
this.validateCredenentialsResponse = function (cr) { | ||
if (cr && | ||
cr.__type && | ||
(cr.__type === 'ResourceNotFoundException' || | ||
cr.__type === 'ValidationException')) { | ||
this.validateOpenIdTokenResponse = function (r) { | ||
if ('IdentityId' in r && 'Token' in r) { | ||
return r; | ||
} | ||
else if (r && '__type' in r && 'message' in r) { | ||
// The request may have failed because of ValidationException or | ||
@@ -155,6 +156,25 @@ // ResourceNotFoundException, which means the identity Id is bad. In | ||
// be re-tried. | ||
localStorage.removeItem(IDENTITY_KEY); | ||
throw new Error("".concat(cr.__type, ": ").concat(cr.message)); | ||
throw new Error("".concat(r.__type, ": ").concat(r.message)); | ||
} | ||
else { | ||
// We don't recognize ths response format. | ||
throw new Error('Unknown OpenIdToken response'); | ||
} | ||
}; | ||
this.validateCredenentialsResponse = function (r) { | ||
if ('IdentityId' in r && 'Credentials' in r) { | ||
return r.Credentials; | ||
} | ||
else if (r && '__type' in r && 'message' in r) { | ||
// The request may have failed because of ValidationException or | ||
// ResourceNotFoundException, which means the identity Id is bad. In | ||
// any case, we invalidate the identity Id so the entire process can | ||
// be re-tried. | ||
throw new Error("".concat(r.__type, ": ").concat(r.message)); | ||
} | ||
else { | ||
// We don't recognize ths response format. | ||
throw new Error('Unknown Credentials response'); | ||
} | ||
}; | ||
this.getHttpRequest = function (target, payload) { | ||
@@ -161,0 +181,0 @@ return new HttpRequest({ |
@@ -1,6 +0,6 @@ | ||
import { CredentialProvider, Credentials, HttpResponse } from '@aws-sdk/types'; | ||
import { AwsCredentialIdentityProvider, AwsCredentialIdentity, HttpResponse } from '@aws-sdk/types'; | ||
import { EventCache } from '../event-cache/EventCache'; | ||
import { DataPlaneClient } from './DataPlaneClient'; | ||
import { Config } from '../orchestration/Orchestration'; | ||
export declare type ClientBuilder = (endpoint: URL, region: string, credentials: CredentialProvider | Credentials | undefined) => DataPlaneClient; | ||
export declare type ClientBuilder = (endpoint: URL, region: string, credentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider) => DataPlaneClient; | ||
export declare class Dispatch { | ||
@@ -30,3 +30,3 @@ private region; | ||
*/ | ||
setAwsCredentials(credentialProvider: Credentials | CredentialProvider): void; | ||
setAwsCredentials(credentialProvider: AwsCredentialIdentity | AwsCredentialIdentityProvider): void; | ||
/** | ||
@@ -33,0 +33,0 @@ * Send meta data and events to the AWS RUM data plane service via fetch. |
import { Config } from '../orchestration/Orchestration'; | ||
import { Credentials } from '@aws-sdk/types'; | ||
export declare class EnhancedAuthentication { | ||
private cognitoIdentityClient; | ||
private config; | ||
private credentials; | ||
import { AwsCredentialIdentity } from '@aws-sdk/types'; | ||
import { Authentication } from './Authentication'; | ||
export declare class EnhancedAuthentication extends Authentication { | ||
constructor(config: Config); | ||
/** | ||
* A credential provider which provides AWS credentials for an anonymous | ||
* (guest) user. These credentials are retrieved from the first successful | ||
* provider in a chain. | ||
* | ||
* Credentials are stored in and retrieved from localStorage. This prevents the client from having to | ||
* re-authenticate every time the client loads, which (1) improves the performance of the RUM web client and (2) | ||
* reduces the load on AWS services Cognito and STS. | ||
* | ||
* While storing credentials in localStorage puts the credential at greater risk of being leaked through an | ||
* XSS attack, there is no impact if the credentials were to be leaked. This is because (1) the identity pool ID | ||
* and role ARN are public and (2) the credentials are for an anonymous (guest) user. | ||
* | ||
* Regarding (1), the identity pool ID and role ARN are, by necessity, public. These identifiers are shipped with | ||
* each application as part of Cognito's Basic (Classic) authentication flow. The identity pool ID and role ARN | ||
* are not secret. | ||
* | ||
* Regarding (2), the authentication chain implemented in this file only supports anonymous (guest) | ||
* authentication. When the Cognito authentication flow is executed, {@code AnonymousCognitoCredentialsProvider} | ||
* does not communicate with a login provider such as Amazon, Facebook or Google. Instead, it relies on (a) the | ||
* identity pool supporting unauthenticated identities and (b) the IAM role policy enabling login through the | ||
* identity pool. If the identity pool does not support unauthenticated identities, this authentication chain | ||
* will not succeed. | ||
* | ||
* Taken together, (1) and (2) mean that if these temporary credentials were to be leaked, the leaked credentials | ||
* would not allow a bad actor to gain access to anything which they did not already have public access to. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
ChainAnonymousCredentialsProvider: () => Promise<Credentials>; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from a member variable. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
private AnonymousCredentialsProvider; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from localStorage. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
private AnonymousStorageCredentialsProvider; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's enhanced | ||
@@ -56,6 +12,5 @@ * authflow. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
private AnonymousCognitoCredentialsProvider; | ||
private renewCredentials; | ||
protected AnonymousCognitoCredentialsProvider: () => Promise<AwsCredentialIdentity>; | ||
} |
@@ -1,12 +0,16 @@ | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
return function (d, b) { | ||
if (typeof b !== "function" && b !== null) | ||
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -48,91 +52,9 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
}; | ||
import { CognitoIdentityClient } from './CognitoIdentityClient'; | ||
import { FetchHttpHandler } from '@aws-sdk/fetch-http-handler'; | ||
import { CRED_KEY, CRED_RENEW_MS } from '../utils/constants'; | ||
var EnhancedAuthentication = /** @class */ (function () { | ||
import { CRED_KEY } from '../utils/constants'; | ||
import { Authentication } from './Authentication'; | ||
var EnhancedAuthentication = /** @class */ (function (_super) { | ||
__extends(EnhancedAuthentication, _super); | ||
function EnhancedAuthentication(config) { | ||
var _this = this; | ||
var _this = _super.call(this, config) || this; | ||
/** | ||
* A credential provider which provides AWS credentials for an anonymous | ||
* (guest) user. These credentials are retrieved from the first successful | ||
* provider in a chain. | ||
* | ||
* Credentials are stored in and retrieved from localStorage. This prevents the client from having to | ||
* re-authenticate every time the client loads, which (1) improves the performance of the RUM web client and (2) | ||
* reduces the load on AWS services Cognito and STS. | ||
* | ||
* While storing credentials in localStorage puts the credential at greater risk of being leaked through an | ||
* XSS attack, there is no impact if the credentials were to be leaked. This is because (1) the identity pool ID | ||
* and role ARN are public and (2) the credentials are for an anonymous (guest) user. | ||
* | ||
* Regarding (1), the identity pool ID and role ARN are, by necessity, public. These identifiers are shipped with | ||
* each application as part of Cognito's Basic (Classic) authentication flow. The identity pool ID and role ARN | ||
* are not secret. | ||
* | ||
* Regarding (2), the authentication chain implemented in this file only supports anonymous (guest) | ||
* authentication. When the Cognito authentication flow is executed, {@code AnonymousCognitoCredentialsProvider} | ||
* does not communicate with a login provider such as Amazon, Facebook or Google. Instead, it relies on (a) the | ||
* identity pool supporting unauthenticated identities and (b) the IAM role policy enabling login through the | ||
* identity pool. If the identity pool does not support unauthenticated identities, this authentication chain | ||
* will not succeed. | ||
* | ||
* Taken together, (1) and (2) mean that if these temporary credentials were to be leaked, the leaked credentials | ||
* would not allow a bad actor to gain access to anything which they did not already have public access to. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
this.ChainAnonymousCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, this.AnonymousCredentialsProvider() | ||
.catch(this.AnonymousStorageCredentialsProvider) | ||
.catch(this.AnonymousCognitoCredentialsProvider)]; | ||
}); | ||
}); }; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from a member variable. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
this.AnonymousCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, new Promise(function (resolve, reject) { | ||
if (_this.renewCredentials()) { | ||
// The credentials have expired. | ||
return reject(); | ||
} | ||
resolve(_this.credentials); | ||
})]; | ||
}); | ||
}); }; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from localStorage. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
this.AnonymousStorageCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, new Promise(function (resolve, reject) { | ||
var credentials; | ||
try { | ||
credentials = JSON.parse(localStorage.getItem(CRED_KEY)); | ||
} | ||
catch (e) { | ||
// Error decoding or parsing the cookie -- abort | ||
return reject(); | ||
} | ||
// The expiration property of Credentials has a date type. Because the date was serialized as a string, | ||
// we need to convert it back into a date, otherwise the AWS SDK signing middleware | ||
// (@aws-sdk/middleware-signing) will throw an exception and no credentials will be returned. | ||
_this.credentials = __assign(__assign({}, credentials), { expiration: new Date(credentials.expiration) }); | ||
if (_this.renewCredentials()) { | ||
// The credentials have expired. | ||
return reject(); | ||
} | ||
resolve(_this.credentials); | ||
})]; | ||
}); | ||
}); }; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's enhanced | ||
@@ -143,14 +65,25 @@ * authflow. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
this.AnonymousCognitoCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
var _this = this; | ||
_this.AnonymousCognitoCredentialsProvider = function () { return __awaiter(_this, void 0, void 0, function () { | ||
var retries, getIdResponse, credentials, e_1; | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, this.cognitoIdentityClient | ||
.getId({ IdentityPoolId: this.config.identityPoolId }) | ||
.then(function (getIdResponse) { | ||
return _this.cognitoIdentityClient.getCredentialsForIdentity(getIdResponse.IdentityId); | ||
}) | ||
.then(function (credentials) { | ||
_this.credentials = credentials; | ||
switch (_a.label) { | ||
case 0: | ||
retries = 1; | ||
_a.label = 1; | ||
case 1: | ||
if (!true) return [3 /*break*/, 7]; | ||
_a.label = 2; | ||
case 2: | ||
_a.trys.push([2, 5, , 6]); | ||
return [4 /*yield*/, this.cognitoIdentityClient.getId({ | ||
IdentityPoolId: this.config.identityPoolId | ||
})]; | ||
case 3: | ||
getIdResponse = _a.sent(); | ||
return [4 /*yield*/, this.cognitoIdentityClient.getCredentialsForIdentity(getIdResponse.IdentityId)]; | ||
case 4: | ||
credentials = _a.sent(); | ||
this.credentials = credentials; | ||
try { | ||
@@ -162,22 +95,21 @@ localStorage.setItem(CRED_KEY, JSON.stringify(credentials)); | ||
} | ||
return credentials; | ||
})]; | ||
return [2 /*return*/, credentials]; | ||
case 5: | ||
e_1 = _a.sent(); | ||
if (retries) { | ||
retries--; | ||
} | ||
else { | ||
throw e_1; | ||
} | ||
return [3 /*break*/, 6]; | ||
case 6: return [3 /*break*/, 1]; | ||
case 7: return [2 /*return*/]; | ||
} | ||
}); | ||
}); }; | ||
var region = config.identityPoolId.split(':')[0]; | ||
this.config = config; | ||
this.cognitoIdentityClient = new CognitoIdentityClient({ | ||
fetchRequestHandler: new FetchHttpHandler(), | ||
region: region | ||
}); | ||
return _this; | ||
} | ||
EnhancedAuthentication.prototype.renewCredentials = function () { | ||
if (!this.credentials || !this.credentials.expiration) { | ||
return true; | ||
} | ||
var renewalTime = new Date(this.credentials.expiration.getTime() - CRED_RENEW_MS); | ||
return new Date() > renewalTime; | ||
}; | ||
return EnhancedAuthentication; | ||
}()); | ||
}(Authentication)); | ||
export { EnhancedAuthentication }; |
import { CognitoIdentityClientConfig } from './CognitoIdentityClient'; | ||
import { Credentials } from '@aws-sdk/types'; | ||
import { AwsCredentialIdentity } from '@aws-sdk/types'; | ||
export interface STSSendRequest { | ||
@@ -12,3 +12,3 @@ RoleArn: string; | ||
constructor(config: CognitoIdentityClientConfig); | ||
assumeRoleWithWebIdentity: (request: STSSendRequest) => Promise<Credentials>; | ||
assumeRoleWithWebIdentity: (request: STSSendRequest) => Promise<AwsCredentialIdentity>; | ||
} |
@@ -16,3 +16,3 @@ var __assign = (this && this.__assign) || function () { | ||
import EventBus, { Topic } from '../event-bus/EventBus'; | ||
var webClientVersion = '1.16.1'; | ||
var webClientVersion = '1.16.2'; | ||
/** | ||
@@ -19,0 +19,0 @@ * A cache which stores events generated by telemetry plugins. |
import { Plugin } from '../plugins/Plugin'; | ||
import { TargetDomEvent } from '../plugins/event-plugins/DomEventPlugin'; | ||
import { ClientBuilder } from '../dispatch/Dispatch'; | ||
import { CredentialProvider, Credentials } from '@aws-sdk/types'; | ||
import { AwsCredentialIdentityProvider, AwsCredentialIdentity } from '@aws-sdk/types'; | ||
import { PageAttributes } from '../sessions/PageManager'; | ||
@@ -152,3 +152,3 @@ export declare enum TelemetryEnum { | ||
*/ | ||
setAwsCredentials(credentials: Credentials | CredentialProvider): void; | ||
setAwsCredentials(credentials: AwsCredentialIdentity | AwsCredentialIdentityProvider): void; | ||
/** | ||
@@ -155,0 +155,0 @@ * Set custom session attributes to add them to all event metadata. |
@@ -32,3 +32,3 @@ var __assign = (this && this.__assign) || function () { | ||
}; | ||
import { Authentication } from '../dispatch/Authentication'; | ||
import { BasicAuthentication } from '../dispatch/BasicAuthentication'; | ||
import { EnhancedAuthentication } from '../dispatch/EnhancedAuthentication'; | ||
@@ -260,3 +260,3 @@ import { PluginManager } from '../plugins/PluginManager'; | ||
if (this.config.identityPoolId && this.config.guestRoleArn) { | ||
dispatch.setAwsCredentials(new Authentication(this.config) | ||
dispatch.setAwsCredentials(new BasicAuthentication(this.config) | ||
.ChainAnonymousCredentialsProvider); | ||
@@ -263,0 +263,0 @@ } |
@@ -188,3 +188,5 @@ var __extends = (this && this.__extends) || (function () { | ||
duration: entryData.duration, | ||
headerSize: entryData.transferSize - entryData.encodedBodySize, | ||
headerSize: entryData.transferSize > 0 | ||
? entryData.transferSize - entryData.encodedBodySize | ||
: 0, | ||
transferSize: entryData.transferSize, | ||
@@ -191,0 +193,0 @@ compressionRatio: entryData.encodedBodySize > 0 |
@@ -0,8 +1,8 @@ | ||
import { CognitoIdentityClient } from './CognitoIdentityClient'; | ||
import { Config } from '../orchestration/Orchestration'; | ||
import { Credentials } from '@aws-sdk/types'; | ||
export declare class Authentication { | ||
private cognitoIdentityClient; | ||
private stsClient; | ||
private config; | ||
private credentials; | ||
import { AwsCredentialIdentity } from '@aws-sdk/types'; | ||
export declare abstract class Authentication { | ||
protected cognitoIdentityClient: CognitoIdentityClient; | ||
protected config: Config; | ||
protected credentials: AwsCredentialIdentity | undefined; | ||
constructor(config: Config); | ||
@@ -18,3 +18,3 @@ /** | ||
* | ||
* While storing credentials in localStorage puts the cookie at greater risk of being leaked through an | ||
* While storing credentials in localStorage puts the credential at greater risk of being leaked through an | ||
* XSS attack, there is no impact if the credentials were to be leaked. This is because (1) the identity pool ID | ||
@@ -37,9 +37,9 @@ * and role ARN are public and (2) the credentials are for an anonymous (guest) user. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
ChainAnonymousCredentialsProvider: () => Promise<Credentials>; | ||
ChainAnonymousCredentialsProvider: () => Promise<AwsCredentialIdentity>; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from a member variable. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
@@ -50,15 +50,18 @@ private AnonymousCredentialsProvider; | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
private AnonymousStorageCredentialsProvider; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's basic | ||
* (classic) authflow. | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's enhanced | ||
* authflow. | ||
* | ||
* See https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
private AnonymousCognitoCredentialsProvider; | ||
protected abstract AnonymousCognitoCredentialsProvider: () => Promise<AwsCredentialIdentity>; | ||
/** | ||
* Returns {@code true} when the credentials need to be renewed. | ||
*/ | ||
private renewCredentials; | ||
} |
import { HttpHandler } from '@aws-sdk/protocol-http'; | ||
import { Credentials } from '@aws-sdk/types'; | ||
import { AwsCredentialIdentity } from '@aws-sdk/types'; | ||
interface OpenIdTokenResponse { | ||
@@ -24,3 +24,4 @@ IdentityId: string; | ||
}) => Promise<OpenIdTokenResponse>; | ||
getCredentialsForIdentity: (identityId: string) => Promise<Credentials>; | ||
getCredentialsForIdentity: (identityId: string) => Promise<AwsCredentialIdentity>; | ||
private validateOpenIdTokenResponse; | ||
private validateCredenentialsResponse; | ||
@@ -27,0 +28,0 @@ private getHttpRequest; |
@@ -1,6 +0,6 @@ | ||
import { CredentialProvider, Credentials, HttpResponse } from '@aws-sdk/types'; | ||
import { AwsCredentialIdentityProvider, AwsCredentialIdentity, HttpResponse } from '@aws-sdk/types'; | ||
import { EventCache } from '../event-cache/EventCache'; | ||
import { DataPlaneClient } from './DataPlaneClient'; | ||
import { Config } from '../orchestration/Orchestration'; | ||
export declare type ClientBuilder = (endpoint: URL, region: string, credentials: CredentialProvider | Credentials | undefined) => DataPlaneClient; | ||
export declare type ClientBuilder = (endpoint: URL, region: string, credentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider) => DataPlaneClient; | ||
export declare class Dispatch { | ||
@@ -30,3 +30,3 @@ private region; | ||
*/ | ||
setAwsCredentials(credentialProvider: Credentials | CredentialProvider): void; | ||
setAwsCredentials(credentialProvider: AwsCredentialIdentity | AwsCredentialIdentityProvider): void; | ||
/** | ||
@@ -33,0 +33,0 @@ * Send meta data and events to the AWS RUM data plane service via fetch. |
import { Config } from '../orchestration/Orchestration'; | ||
import { Credentials } from '@aws-sdk/types'; | ||
export declare class EnhancedAuthentication { | ||
private cognitoIdentityClient; | ||
private config; | ||
private credentials; | ||
import { AwsCredentialIdentity } from '@aws-sdk/types'; | ||
import { Authentication } from './Authentication'; | ||
export declare class EnhancedAuthentication extends Authentication { | ||
constructor(config: Config); | ||
/** | ||
* A credential provider which provides AWS credentials for an anonymous | ||
* (guest) user. These credentials are retrieved from the first successful | ||
* provider in a chain. | ||
* | ||
* Credentials are stored in and retrieved from localStorage. This prevents the client from having to | ||
* re-authenticate every time the client loads, which (1) improves the performance of the RUM web client and (2) | ||
* reduces the load on AWS services Cognito and STS. | ||
* | ||
* While storing credentials in localStorage puts the credential at greater risk of being leaked through an | ||
* XSS attack, there is no impact if the credentials were to be leaked. This is because (1) the identity pool ID | ||
* and role ARN are public and (2) the credentials are for an anonymous (guest) user. | ||
* | ||
* Regarding (1), the identity pool ID and role ARN are, by necessity, public. These identifiers are shipped with | ||
* each application as part of Cognito's Basic (Classic) authentication flow. The identity pool ID and role ARN | ||
* are not secret. | ||
* | ||
* Regarding (2), the authentication chain implemented in this file only supports anonymous (guest) | ||
* authentication. When the Cognito authentication flow is executed, {@code AnonymousCognitoCredentialsProvider} | ||
* does not communicate with a login provider such as Amazon, Facebook or Google. Instead, it relies on (a) the | ||
* identity pool supporting unauthenticated identities and (b) the IAM role policy enabling login through the | ||
* identity pool. If the identity pool does not support unauthenticated identities, this authentication chain | ||
* will not succeed. | ||
* | ||
* Taken together, (1) and (2) mean that if these temporary credentials were to be leaked, the leaked credentials | ||
* would not allow a bad actor to gain access to anything which they did not already have public access to. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
ChainAnonymousCredentialsProvider: () => Promise<Credentials>; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from a member variable. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
private AnonymousCredentialsProvider; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are read from localStorage. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
*/ | ||
private AnonymousStorageCredentialsProvider; | ||
/** | ||
* Provides credentials for an anonymous (guest) user. These credentials are retrieved from Cognito's enhanced | ||
@@ -56,6 +12,5 @@ * authflow. | ||
* | ||
* Implements CredentialsProvider = Provider<Credentials> | ||
* Implements AwsCredentialIdentityProvider = Provider<AwsCredentialIdentity> | ||
*/ | ||
private AnonymousCognitoCredentialsProvider; | ||
private renewCredentials; | ||
protected AnonymousCognitoCredentialsProvider: () => Promise<AwsCredentialIdentity>; | ||
} |
import { CognitoIdentityClientConfig } from './CognitoIdentityClient'; | ||
import { Credentials } from '@aws-sdk/types'; | ||
import { AwsCredentialIdentity } from '@aws-sdk/types'; | ||
export interface STSSendRequest { | ||
@@ -12,3 +12,3 @@ RoleArn: string; | ||
constructor(config: CognitoIdentityClientConfig); | ||
assumeRoleWithWebIdentity: (request: STSSendRequest) => Promise<Credentials>; | ||
assumeRoleWithWebIdentity: (request: STSSendRequest) => Promise<AwsCredentialIdentity>; | ||
} |
import { Plugin } from '../plugins/Plugin'; | ||
import { TargetDomEvent } from '../plugins/event-plugins/DomEventPlugin'; | ||
import { ClientBuilder } from '../dispatch/Dispatch'; | ||
import { CredentialProvider, Credentials } from '@aws-sdk/types'; | ||
import { AwsCredentialIdentityProvider, AwsCredentialIdentity } from '@aws-sdk/types'; | ||
import { PageAttributes } from '../sessions/PageManager'; | ||
@@ -152,3 +152,3 @@ export declare enum TelemetryEnum { | ||
*/ | ||
setAwsCredentials(credentials: Credentials | CredentialProvider): void; | ||
setAwsCredentials(credentials: AwsCredentialIdentity | AwsCredentialIdentityProvider): void; | ||
/** | ||
@@ -155,0 +155,0 @@ * Set custom session attributes to add them to all event metadata. |
{ | ||
"name": "aws-rum-web", | ||
"version": "1.16.1", | ||
"version": "1.16.2", | ||
"sideEffects": false, | ||
@@ -5,0 +5,0 @@ "description": "The Amazon CloudWatch RUM web client.", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1357158
293
16855