token_provider_chain.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. var AWS = require('../core');
  2. /**
  3. * Creates a token provider chain that searches for token in a list of
  4. * token providers specified by the {providers} property.
  5. *
  6. * By default, the chain will use the {defaultProviders} to resolve token.
  7. *
  8. * ## Setting Providers
  9. *
  10. * Each provider in the {providers} list should be a function that returns
  11. * a {AWS.Token} object, or a hardcoded token object. The function
  12. * form allows for delayed execution of the Token construction.
  13. *
  14. * ## Resolving Token from a Chain
  15. *
  16. * Call {resolve} to return the first valid token object that can be
  17. * loaded by the provider chain.
  18. *
  19. * For example, to resolve a chain with a custom provider that checks a file
  20. * on disk after the set of {defaultProviders}:
  21. *
  22. * ```javascript
  23. * var diskProvider = new FileTokenProvider('./token.json');
  24. * var chain = new AWS.TokenProviderChain();
  25. * chain.providers.push(diskProvider);
  26. * chain.resolve();
  27. * ```
  28. *
  29. * The above code will return the `diskProvider` object if the
  30. * file contains token and the `defaultProviders` do not contain
  31. * any token.
  32. *
  33. * @!attribute providers
  34. * @return [Array<AWS.Token, Function>]
  35. * a list of token objects or functions that return token
  36. * objects. If the provider is a function, the function will be
  37. * executed lazily when the provider needs to be checked for valid
  38. * token. By default, this object will be set to the {defaultProviders}.
  39. * @see defaultProviders
  40. */
  41. AWS.TokenProviderChain = AWS.util.inherit(AWS.Token, {
  42. /**
  43. * Creates a new TokenProviderChain with a default set of providers
  44. * specified by {defaultProviders}.
  45. */
  46. constructor: function TokenProviderChain(providers) {
  47. if (providers) {
  48. this.providers = providers;
  49. } else {
  50. this.providers = AWS.TokenProviderChain.defaultProviders.slice(0);
  51. }
  52. this.resolveCallbacks = [];
  53. },
  54. /**
  55. * @!method resolvePromise()
  56. * Returns a 'thenable' promise.
  57. * Resolves the provider chain by searching for the first token in {providers}.
  58. *
  59. * Two callbacks can be provided to the `then` method on the returned promise.
  60. * The first callback will be called if the promise is fulfilled, and the second
  61. * callback will be called if the promise is rejected.
  62. * @callback fulfilledCallback function(token)
  63. * Called if the promise is fulfilled and the provider resolves the chain
  64. * to a token object
  65. * @param token [AWS.Token] the token object resolved by the provider chain.
  66. * @callback rejectedCallback function(error)
  67. * Called if the promise is rejected.
  68. * @param err [Error] the error object returned if no token is found.
  69. * @return [Promise] A promise that represents the state of the `resolve` method call.
  70. * @example Calling the `resolvePromise` method.
  71. * var promise = chain.resolvePromise();
  72. * promise.then(function(token) { ... }, function(err) { ... });
  73. */
  74. /**
  75. * Resolves the provider chain by searching for the first token in {providers}.
  76. *
  77. * @callback callback function(err, token)
  78. * Called when the provider resolves the chain to a token object
  79. * or null if no token can be found.
  80. *
  81. * @param err [Error] the error object returned if no token is found.
  82. * @param token [AWS.Token] the token object resolved by the provider chain.
  83. * @return [AWS.TokenProviderChain] the provider, for chaining.
  84. */
  85. resolve: function resolve(callback) {
  86. var self = this;
  87. if (self.providers.length === 0) {
  88. callback(new Error('No providers'));
  89. return self;
  90. }
  91. if (self.resolveCallbacks.push(callback) === 1) {
  92. var index = 0;
  93. var providers = self.providers.slice(0);
  94. function resolveNext(err, token) {
  95. if ((!err && token) || index === providers.length) {
  96. AWS.util.arrayEach(self.resolveCallbacks, function (callback) {
  97. callback(err, token);
  98. });
  99. self.resolveCallbacks.length = 0;
  100. return;
  101. }
  102. var provider = providers[index++];
  103. if (typeof provider === 'function') {
  104. token = provider.call();
  105. } else {
  106. token = provider;
  107. }
  108. if (token.get) {
  109. token.get(function (getErr) {
  110. resolveNext(getErr, getErr ? null : token);
  111. });
  112. } else {
  113. resolveNext(null, token);
  114. }
  115. }
  116. resolveNext();
  117. }
  118. return self;
  119. }
  120. });
  121. /**
  122. * The default set of providers used by a vanilla TokenProviderChain.
  123. *
  124. * In the browser:
  125. *
  126. * ```javascript
  127. * AWS.TokenProviderChain.defaultProviders = []
  128. * ```
  129. *
  130. * In Node.js:
  131. *
  132. * ```javascript
  133. * AWS.TokenProviderChain.defaultProviders = [
  134. * function () { return new AWS.SSOTokenProvider(); },
  135. * ]
  136. * ```
  137. */
  138. AWS.TokenProviderChain.defaultProviders = [];
  139. /**
  140. * @api private
  141. */
  142. AWS.TokenProviderChain.addPromisesToClass = function addPromisesToClass(PromiseDependency) {
  143. this.prototype.resolvePromise = AWS.util.promisifyMethod('resolve', PromiseDependency);
  144. };
  145. /**
  146. * @api private
  147. */
  148. AWS.TokenProviderChain.deletePromisesFromClass = function deletePromisesFromClass() {
  149. delete this.prototype.resolvePromise;
  150. };
  151. AWS.util.addPromises(AWS.TokenProviderChain);