credentials.js (9024B)
1 var AWS = require('./core'); 2 3 /** 4 * Represents your AWS security credentials, specifically the 5 * {accessKeyId}, {secretAccessKey}, and optional {sessionToken}. 6 * Creating a `Credentials` object allows you to pass around your 7 * security information to configuration and service objects. 8 * 9 * Note that this class typically does not need to be constructed manually, 10 * as the {AWS.Config} and {AWS.Service} classes both accept simple 11 * options hashes with the three keys. These structures will be converted 12 * into Credentials objects automatically. 13 * 14 * ## Expiring and Refreshing Credentials 15 * 16 * Occasionally credentials can expire in the middle of a long-running 17 * application. In this case, the SDK will automatically attempt to 18 * refresh the credentials from the storage location if the Credentials 19 * class implements the {refresh} method. 20 * 21 * If you are implementing a credential storage location, you 22 * will want to create a subclass of the `Credentials` class and 23 * override the {refresh} method. This method allows credentials to be 24 * retrieved from the backing store, be it a file system, database, or 25 * some network storage. The method should reset the credential attributes 26 * on the object. 27 * 28 * @!attribute expired 29 * @return [Boolean] whether the credentials have been expired and 30 * require a refresh. Used in conjunction with {expireTime}. 31 * @!attribute expireTime 32 * @return [Date] a time when credentials should be considered expired. Used 33 * in conjunction with {expired}. 34 * @!attribute accessKeyId 35 * @return [String] the AWS access key ID 36 * @!attribute secretAccessKey 37 * @return [String] the AWS secret access key 38 * @!attribute sessionToken 39 * @return [String] an optional AWS session token 40 */ 41 AWS.Credentials = AWS.util.inherit({ 42 /** 43 * A credentials object can be created using positional arguments or an options 44 * hash. 45 * 46 * @overload AWS.Credentials(accessKeyId, secretAccessKey, sessionToken=null) 47 * Creates a Credentials object with a given set of credential information 48 * as positional arguments. 49 * @param accessKeyId [String] the AWS access key ID 50 * @param secretAccessKey [String] the AWS secret access key 51 * @param sessionToken [String] the optional AWS session token 52 * @example Create a credentials object with AWS credentials 53 * var creds = new AWS.Credentials('akid', 'secret', 'session'); 54 * @overload AWS.Credentials(options) 55 * Creates a Credentials object with a given set of credential information 56 * as an options hash. 57 * @option options accessKeyId [String] the AWS access key ID 58 * @option options secretAccessKey [String] the AWS secret access key 59 * @option options sessionToken [String] the optional AWS session token 60 * @example Create a credentials object with AWS credentials 61 * var creds = new AWS.Credentials({ 62 * accessKeyId: 'akid', secretAccessKey: 'secret', sessionToken: 'session' 63 * }); 64 */ 65 constructor: function Credentials() { 66 // hide secretAccessKey from being displayed with util.inspect 67 AWS.util.hideProperties(this, ['secretAccessKey']); 68 69 this.expired = false; 70 this.expireTime = null; 71 if (arguments.length === 1 && typeof arguments[0] === 'object') { 72 var creds = arguments[0].credentials || arguments[0]; 73 this.accessKeyId = creds.accessKeyId; 74 this.secretAccessKey = creds.secretAccessKey; 75 this.sessionToken = creds.sessionToken; 76 } else { 77 this.accessKeyId = arguments[0]; 78 this.secretAccessKey = arguments[1]; 79 this.sessionToken = arguments[2]; 80 } 81 }, 82 83 /** 84 * @return [Integer] the window size in seconds to attempt refreshing of 85 * credentials before the expireTime occurs. 86 */ 87 expiryWindow: 15, 88 89 /** 90 * @return [Boolean] whether the credentials object should call {refresh} 91 * @note Subclasses should override this method to provide custom refresh 92 * logic. 93 */ 94 needsRefresh: function needsRefresh() { 95 var currentTime = AWS.util.date.getDate().getTime(); 96 var adjustedTime = new Date(currentTime + this.expiryWindow * 1000); 97 98 if (this.expireTime && adjustedTime > this.expireTime) { 99 return true; 100 } else { 101 return this.expired || !this.accessKeyId || !this.secretAccessKey; 102 } 103 }, 104 105 /** 106 * Gets the existing credentials, refreshing them if they are not yet loaded 107 * or have expired. Users should call this method before using {refresh}, 108 * as this will not attempt to reload credentials when they are already 109 * loaded into the object. 110 * 111 * @callback callback function(err) 112 * When this callback is called with no error, it means either credentials 113 * do not need to be refreshed or refreshed credentials information has 114 * been loaded into the object (as the `accessKeyId`, `secretAccessKey`, 115 * and `sessionToken` properties). 116 * @param err [Error] if an error occurred, this value will be filled 117 */ 118 get: function get(callback) { 119 var self = this; 120 if (this.needsRefresh()) { 121 this.refresh(function(err) { 122 if (!err) self.expired = false; // reset expired flag 123 if (callback) callback(err); 124 }); 125 } else if (callback) { 126 callback(); 127 } 128 }, 129 130 /** 131 * @!method getPromise() 132 * Returns a 'thenable' promise. 133 * Gets the existing credentials, refreshing them if they are not yet loaded 134 * or have expired. Users should call this method before using {refresh}, 135 * as this will not attempt to reload credentials when they are already 136 * loaded into the object. 137 * 138 * Two callbacks can be provided to the `then` method on the returned promise. 139 * The first callback will be called if the promise is fulfilled, and the second 140 * callback will be called if the promise is rejected. 141 * @callback fulfilledCallback function() 142 * Called if the promise is fulfilled. When this callback is called, it 143 * means either credentials do not need to be refreshed or refreshed 144 * credentials information has been loaded into the object (as the 145 * `accessKeyId`, `secretAccessKey`, and `sessionToken` properties). 146 * @callback rejectedCallback function(err) 147 * Called if the promise is rejected. 148 * @param err [Error] if an error occurred, this value will be filled 149 * @return [Promise] A promise that represents the state of the `get` call. 150 * @example Calling the `getPromise` method. 151 * var promise = credProvider.getPromise(); 152 * promise.then(function() { ... }, function(err) { ... }); 153 */ 154 155 /** 156 * @!method refreshPromise() 157 * Returns a 'thenable' promise. 158 * Refreshes the credentials. Users should call {get} before attempting 159 * to forcibly refresh credentials. 160 * 161 * Two callbacks can be provided to the `then` method on the returned promise. 162 * The first callback will be called if the promise is fulfilled, and the second 163 * callback will be called if the promise is rejected. 164 * @callback fulfilledCallback function() 165 * Called if the promise is fulfilled. When this callback is called, it 166 * means refreshed credentials information has been loaded into the object 167 * (as the `accessKeyId`, `secretAccessKey`, and `sessionToken` properties). 168 * @callback rejectedCallback function(err) 169 * Called if the promise is rejected. 170 * @param err [Error] if an error occurred, this value will be filled 171 * @return [Promise] A promise that represents the state of the `refresh` call. 172 * @example Calling the `refreshPromise` method. 173 * var promise = credProvider.refreshPromise(); 174 * promise.then(function() { ... }, function(err) { ... }); 175 */ 176 177 /** 178 * Refreshes the credentials. Users should call {get} before attempting 179 * to forcibly refresh credentials. 180 * 181 * @callback callback function(err) 182 * When this callback is called with no error, it means refreshed 183 * credentials information has been loaded into the object (as the 184 * `accessKeyId`, `secretAccessKey`, and `sessionToken` properties). 185 * @param err [Error] if an error occurred, this value will be filled 186 * @note Subclasses should override this class to reset the 187 * {accessKeyId}, {secretAccessKey} and optional {sessionToken} 188 * on the credentials object and then call the callback with 189 * any error information. 190 * @see get 191 */ 192 refresh: function refresh(callback) { 193 this.expired = false; 194 callback(); 195 } 196 }); 197 198 /** 199 * @api private 200 */ 201 AWS.Credentials.addPromisesToClass = function addPromisesToClass(PromiseDependency) { 202 this.prototype.getPromise = AWS.util.promisifyMethod('get', PromiseDependency); 203 this.prototype.refreshPromise = AWS.util.promisifyMethod('refresh', PromiseDependency); 204 }; 205 206 /** 207 * @api private 208 */ 209 AWS.Credentials.deletePromisesFromClass = function deletePromisesFromClass() { 210 delete this.prototype.getPromise; 211 delete this.prototype.refreshPromise; 212 }; 213 214 AWS.util.addPromises(AWS.Credentials);