delectusnon 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/.prettierignore +2 -0
  2. package/.travis.yml +33 -0
  3. package/.vscode/launch.json +24 -0
  4. package/.vscode/settings.json +3 -0
  5. package/demos/ago-node-cli/README.md +29 -0
  6. package/demos/ago-node-cli/ago.js +32 -0
  7. package/demos/ago-node-cli/index.js +11 -0
  8. package/demos/ago-node-cli/lib/item-export-command.js +48 -0
  9. package/demos/ago-node-cli/lib/item-search-command.js +35 -0
  10. package/demos/ago-node-cli/package-lock.json +172 -0
  11. package/demos/ago-node-cli/package.json +30 -0
  12. package/demos/attachments/README.md +5 -0
  13. package/demos/attachments/index.html +164 -0
  14. package/demos/attachments/package-lock.json +182 -0
  15. package/demos/attachments/package.json +18 -0
  16. package/demos/batch-geocoder-node/NYC_Restaurant_Inspection_Results.csv +100 -0
  17. package/demos/batch-geocoder-node/README.md +15 -0
  18. package/demos/batch-geocoder-node/batch-geocode.js +118 -0
  19. package/demos/batch-geocoder-node/config-template.js +18 -0
  20. package/demos/batch-geocoder-node/package-lock.json +116 -0
  21. package/demos/batch-geocoder-node/package.json +39 -0
  22. package/demos/express/README.md +10 -0
  23. package/demos/express/config.json.template +3 -0
  24. package/demos/express/package-lock.json +473 -0
  25. package/demos/express/package.json +18 -0
  26. package/demos/express/server.js +28 -0
  27. package/demos/feature-service-browser/README.md +6 -0
  28. package/demos/feature-service-browser/index.html +122 -0
  29. package/demos/feature-service-browser/package-lock.json +182 -0
  30. package/demos/feature-service-browser/package.json +18 -0
  31. package/demos/geocoder-browser/README.md +10 -0
  32. package/demos/geocoder-browser/config.js.template +1 -0
  33. package/demos/geocoder-browser/index.html +131 -0
  34. package/demos/geocoder-browser/package-lock.json +182 -0
  35. package/demos/geocoder-browser/package.json +19 -0
  36. package/demos/geocoder-browser/post-sign-in.html +25 -0
  37. package/demos/jsapi-integration/README.md +8 -0
  38. package/demos/jsapi-integration/config.js +6 -0
  39. package/demos/jsapi-integration/index.html +79 -0
  40. package/demos/jsapi-integration/package-lock.json +184 -0
  41. package/demos/jsapi-integration/package.json +19 -0
  42. package/demos/oauth2-browser/README.md +12 -0
  43. package/demos/oauth2-browser/authenticate.html +32 -0
  44. package/demos/oauth2-browser/config.js.template +6 -0
  45. package/demos/oauth2-browser/index.html +202 -0
  46. package/demos/oauth2-browser/logo.svg +4 -0
  47. package/demos/oauth2-browser/package-lock.json +163 -0
  48. package/demos/oauth2-browser/package.json +18 -0
  49. package/demos/oauth2-browser/style.css +36 -0
  50. package/demos/oauth2-browser-retry/README.md +25 -0
  51. package/demos/oauth2-browser-retry/authenticate.html +21 -0
  52. package/demos/oauth2-browser-retry/index.html +116 -0
  53. package/demos/oauth2-browser-retry/logo.svg +4 -0
  54. package/demos/vue/.env.example +11 -0
  55. package/demos/vue/.eslintrc.js +17 -0
  56. package/demos/vue/.postcssrc.js +5 -0
  57. package/demos/vue/README.md +17 -0
  58. package/demos/vue/babel.config.js +3 -0
  59. package/demos/vue/package-lock.json +11323 -0
  60. package/demos/vue/package.json +33 -0
  61. package/demos/vue/public/favicon.ico +0 -0
  62. package/demos/vue/public/index.html +24 -0
  63. package/demos/vue/src/assets/logo.svg +29 -0
  64. package/demos/vue/src/components/App.vue +308 -0
  65. package/demos/vue/src/components/Authenticate.vue +65 -0
  66. package/demos/vue/src/components/Loader.vue +230 -0
  67. package/demos/vue/src/main.js +92 -0
  68. package/docs/FAQ.md +28 -0
  69. package/docs/HISTORY.md +62 -0
  70. package/docs/acetate.config.js +223 -0
  71. package/docs/build-typedoc.js +301 -0
  72. package/docs/src/_layout.html +82 -0
  73. package/docs/src/api/_declaration.html +496 -0
  74. package/docs/src/api/_layout.html +127 -0
  75. package/docs/src/api/_package.html +13 -0
  76. package/docs/src/api/index.html +23 -0
  77. package/docs/src/guides/_layout.html +24 -0
  78. package/docs/src/guides/amd-requirejs-dojo.md +40 -0
  79. package/docs/src/guides/babel-and-rollup.md +30 -0
  80. package/docs/src/guides/babel-and-webpack.md +30 -0
  81. package/docs/src/guides/browser-authentication.md +31 -0
  82. package/docs/src/guides/browserify.md +9 -0
  83. package/docs/src/guides/cli-authentication.md +9 -0
  84. package/docs/src/guides/client-server-authentication.md +9 -0
  85. package/docs/src/guides/from-a-cdn.md +36 -0
  86. package/docs/src/guides/index.md +52 -0
  87. package/docs/src/guides/node.md +70 -0
  88. package/docs/src/guides/package-overview.md +8 -0
  89. package/docs/src/guides/server-authentication.md +9 -0
  90. package/docs/src/guides/typescript-and-webpack.md +9 -0
  91. package/docs/src/img/icons.png +0 -0
  92. package/docs/src/img/icons@2x.png +0 -0
  93. package/docs/src/index.html +12 -0
  94. package/docs/src/js/api-search.js +112 -0
  95. package/docs/src/js/nav-toggle.js +41 -0
  96. package/docs/src/sass/_highlight.scss +96 -0
  97. package/docs/src/sass/_icons.scss +157 -0
  98. package/docs/src/sass/style.scss +169 -0
  99. package/jasmine.json +7 -0
  100. package/karma.conf.js +100 -0
  101. package/lerna.json +8 -0
  102. package/notes/README.md +88 -0
  103. package/package.json +88 -0
  104. package/packages/arcgis-rest-auth/README.md +64 -0
  105. package/packages/arcgis-rest-auth/package-lock.json +11 -0
  106. package/packages/arcgis-rest-auth/package.json +51 -0
  107. package/packages/arcgis-rest-auth/src/ApplicationSession.ts +109 -0
  108. package/packages/arcgis-rest-auth/src/UserSession.ts +873 -0
  109. package/packages/arcgis-rest-auth/src/authenticated-request-options.ts +24 -0
  110. package/packages/arcgis-rest-auth/src/fetch-token.ts +52 -0
  111. package/packages/arcgis-rest-auth/src/generate-token.ts +39 -0
  112. package/packages/arcgis-rest-auth/src/index.ts +8 -0
  113. package/packages/arcgis-rest-auth/test/ApplicationSession.test.ts +124 -0
  114. package/packages/arcgis-rest-auth/test/UserSession.test.ts +995 -0
  115. package/packages/arcgis-rest-auth/test/fetchToken.test.ts +112 -0
  116. package/packages/arcgis-rest-auth/test/generateToken.test.ts +130 -0
  117. package/packages/arcgis-rest-auth/test/utils.ts +14 -0
  118. package/packages/arcgis-rest-auth/tsconfig.json +6 -0
  119. package/packages/arcgis-rest-common-types/README.md +61 -0
  120. package/packages/arcgis-rest-common-types/package.json +38 -0
  121. package/packages/arcgis-rest-common-types/src/group.ts +54 -0
  122. package/packages/arcgis-rest-common-types/src/index.ts +467 -0
  123. package/packages/arcgis-rest-common-types/src/item.ts +45 -0
  124. package/packages/arcgis-rest-common-types/src/webmap.ts +1232 -0
  125. package/packages/arcgis-rest-common-types/tsconfig.json +11 -0
  126. package/packages/arcgis-rest-feature-service/README.md +70 -0
  127. package/packages/arcgis-rest-feature-service/package-lock.json +11 -0
  128. package/packages/arcgis-rest-feature-service/package.json +50 -0
  129. package/packages/arcgis-rest-feature-service/src/add.ts +81 -0
  130. package/packages/arcgis-rest-feature-service/src/addAttachment.ts +65 -0
  131. package/packages/arcgis-rest-feature-service/src/delete.ts +85 -0
  132. package/packages/arcgis-rest-feature-service/src/deleteAttachments.ts +68 -0
  133. package/packages/arcgis-rest-feature-service/src/getAttachments.ts +64 -0
  134. package/packages/arcgis-rest-feature-service/src/helpers.ts +80 -0
  135. package/packages/arcgis-rest-feature-service/src/index.ts +12 -0
  136. package/packages/arcgis-rest-feature-service/src/query.ts +172 -0
  137. package/packages/arcgis-rest-feature-service/src/queryRelated.ts +91 -0
  138. package/packages/arcgis-rest-feature-service/src/update.ts +81 -0
  139. package/packages/arcgis-rest-feature-service/src/updateAttachment.ts +74 -0
  140. package/packages/arcgis-rest-feature-service/test/attachments.test.ts +203 -0
  141. package/packages/arcgis-rest-feature-service/test/features.test.ts +252 -0
  142. package/packages/arcgis-rest-feature-service/test/mocks/feature.ts +279 -0
  143. package/packages/arcgis-rest-feature-service/test/mocks/foo.txt +1 -0
  144. package/packages/arcgis-rest-feature-service/tsconfig.json +6 -0
  145. package/packages/arcgis-rest-feature-service-admin/README.md +66 -0
  146. package/packages/arcgis-rest-feature-service-admin/package-lock.json +11 -0
  147. package/packages/arcgis-rest-feature-service-admin/package.json +53 -0
  148. package/packages/arcgis-rest-feature-service-admin/src/addTo.ts +70 -0
  149. package/packages/arcgis-rest-feature-service-admin/src/create.ts +195 -0
  150. package/packages/arcgis-rest-feature-service-admin/src/index.ts +2 -0
  151. package/packages/arcgis-rest-feature-service-admin/test/addTo.test.ts +310 -0
  152. package/packages/arcgis-rest-feature-service-admin/test/create.test.ts +412 -0
  153. package/packages/arcgis-rest-feature-service-admin/test/mocks/move.ts +14 -0
  154. package/packages/arcgis-rest-feature-service-admin/test/mocks/service.ts +72 -0
  155. package/packages/arcgis-rest-feature-service-admin/tsconfig.json +6 -0
  156. package/packages/arcgis-rest-geocoder/README.md +79 -0
  157. package/packages/arcgis-rest-geocoder/package-lock.json +11 -0
  158. package/packages/arcgis-rest-geocoder/package.json +52 -0
  159. package/packages/arcgis-rest-geocoder/src/bulk.ts +102 -0
  160. package/packages/arcgis-rest-geocoder/src/geocode.ts +117 -0
  161. package/packages/arcgis-rest-geocoder/src/helpers.ts +79 -0
  162. package/packages/arcgis-rest-geocoder/src/index.ts +8 -0
  163. package/packages/arcgis-rest-geocoder/src/reverse.ts +84 -0
  164. package/packages/arcgis-rest-geocoder/src/suggest.ts +72 -0
  165. package/packages/arcgis-rest-geocoder/test/bulk.test.ts +113 -0
  166. package/packages/arcgis-rest-geocoder/test/geocode.test.ts +121 -0
  167. package/packages/arcgis-rest-geocoder/test/helpers.test.ts +113 -0
  168. package/packages/arcgis-rest-geocoder/test/mocks/responses.ts +591 -0
  169. package/packages/arcgis-rest-geocoder/test/reverse.test.ts +126 -0
  170. package/packages/arcgis-rest-geocoder/test/suggest.test.ts +77 -0
  171. package/packages/arcgis-rest-geocoder/tsconfig.json +6 -0
  172. package/packages/arcgis-rest-groups/README.md +64 -0
  173. package/packages/arcgis-rest-groups/package-lock.json +11 -0
  174. package/packages/arcgis-rest-groups/package.json +52 -0
  175. package/packages/arcgis-rest-groups/src/create.ts +34 -0
  176. package/packages/arcgis-rest-groups/src/get.ts +95 -0
  177. package/packages/arcgis-rest-groups/src/helpers.ts +26 -0
  178. package/packages/arcgis-rest-groups/src/index.ts +11 -0
  179. package/packages/arcgis-rest-groups/src/notification.ts +77 -0
  180. package/packages/arcgis-rest-groups/src/protect.ts +40 -0
  181. package/packages/arcgis-rest-groups/src/remove.ts +23 -0
  182. package/packages/arcgis-rest-groups/src/search.ts +64 -0
  183. package/packages/arcgis-rest-groups/src/update.ts +36 -0
  184. package/packages/arcgis-rest-groups/test/crud.test.ts +104 -0
  185. package/packages/arcgis-rest-groups/test/get.test.ts +101 -0
  186. package/packages/arcgis-rest-groups/test/mocks/responses.ts +141 -0
  187. package/packages/arcgis-rest-groups/test/notification.test.ts +102 -0
  188. package/packages/arcgis-rest-groups/test/protect.test.ts +64 -0
  189. package/packages/arcgis-rest-groups/test/search.test.ts +85 -0
  190. package/packages/arcgis-rest-groups/tsconfig.json +6 -0
  191. package/packages/arcgis-rest-items/README.md +66 -0
  192. package/packages/arcgis-rest-items/package-lock.json +11 -0
  193. package/packages/arcgis-rest-items/package.json +52 -0
  194. package/packages/arcgis-rest-items/src/add.ts +103 -0
  195. package/packages/arcgis-rest-items/src/create.ts +110 -0
  196. package/packages/arcgis-rest-items/src/get.ts +79 -0
  197. package/packages/arcgis-rest-items/src/helpers.ts +147 -0
  198. package/packages/arcgis-rest-items/src/index.ts +11 -0
  199. package/packages/arcgis-rest-items/src/protect.ts +38 -0
  200. package/packages/arcgis-rest-items/src/remove.ts +58 -0
  201. package/packages/arcgis-rest-items/src/search.ts +78 -0
  202. package/packages/arcgis-rest-items/src/update.ts +134 -0
  203. package/packages/arcgis-rest-items/test/add.test.ts +256 -0
  204. package/packages/arcgis-rest-items/test/create.test.ts +371 -0
  205. package/packages/arcgis-rest-items/test/get.test.ts +181 -0
  206. package/packages/arcgis-rest-items/test/mocks/foo.zip +0 -0
  207. package/packages/arcgis-rest-items/test/mocks/item.ts +33 -0
  208. package/packages/arcgis-rest-items/test/mocks/resources.ts +31 -0
  209. package/packages/arcgis-rest-items/test/mocks/search.ts +63 -0
  210. package/packages/arcgis-rest-items/test/protect.test.ts +122 -0
  211. package/packages/arcgis-rest-items/test/remove.test.ts +161 -0
  212. package/packages/arcgis-rest-items/test/search.test.ts +159 -0
  213. package/packages/arcgis-rest-items/test/update.test.ts +450 -0
  214. package/packages/arcgis-rest-items/tsconfig.json +6 -0
  215. package/packages/arcgis-rest-request/README.md +65 -0
  216. package/packages/arcgis-rest-request/package-lock.json +11 -0
  217. package/packages/arcgis-rest-request/package.json +42 -0
  218. package/packages/arcgis-rest-request/src/index.ts +13 -0
  219. package/packages/arcgis-rest-request/src/request.ts +293 -0
  220. package/packages/arcgis-rest-request/src/utils/ArcGISAuthError.ts +67 -0
  221. package/packages/arcgis-rest-request/src/utils/ArcGISRequestError.ts +76 -0
  222. package/packages/arcgis-rest-request/src/utils/ErrorTypes.ts +29 -0
  223. package/packages/arcgis-rest-request/src/utils/check-for-errors.ts +65 -0
  224. package/packages/arcgis-rest-request/src/utils/encode-form-data.ts +34 -0
  225. package/packages/arcgis-rest-request/src/utils/encode-query-string.ts +23 -0
  226. package/packages/arcgis-rest-request/src/utils/get-portal-url.ts +25 -0
  227. package/packages/arcgis-rest-request/src/utils/get-portal.ts +45 -0
  228. package/packages/arcgis-rest-request/src/utils/process-params.ts +99 -0
  229. package/packages/arcgis-rest-request/test/mocks/errors.ts +68 -0
  230. package/packages/arcgis-rest-request/test/mocks/geojson-feature-collection.ts +13 -0
  231. package/packages/arcgis-rest-request/test/mocks/portal.ts +112 -0
  232. package/packages/arcgis-rest-request/test/mocks/sharing-rest-info.ts +41 -0
  233. package/packages/arcgis-rest-request/test/mocks/webmap.ts +41 -0
  234. package/packages/arcgis-rest-request/test/request.test.ts +299 -0
  235. package/packages/arcgis-rest-request/test/utils/ArcGISAuthError.test.ts +170 -0
  236. package/packages/arcgis-rest-request/test/utils/ArcGISRequestError.test.ts +51 -0
  237. package/packages/arcgis-rest-request/test/utils/check-for-errors.test.ts +111 -0
  238. package/packages/arcgis-rest-request/test/utils/encode-form-data.test.ts +133 -0
  239. package/packages/arcgis-rest-request/test/utils/get-portal-url.test.ts +37 -0
  240. package/packages/arcgis-rest-request/test/utils/portal.test.ts +97 -0
  241. package/packages/arcgis-rest-request/test/utils/process-params.test.ts +193 -0
  242. package/packages/arcgis-rest-request/tsconfig.json +6 -0
  243. package/packages/arcgis-rest-sharing/README.md +67 -0
  244. package/packages/arcgis-rest-sharing/package-lock.json +11 -0
  245. package/packages/arcgis-rest-sharing/package.json +57 -0
  246. package/packages/arcgis-rest-sharing/src/access.ts +85 -0
  247. package/packages/arcgis-rest-sharing/src/group-sharing.ts +211 -0
  248. package/packages/arcgis-rest-sharing/src/helpers.ts +82 -0
  249. package/packages/arcgis-rest-sharing/src/index.ts +5 -0
  250. package/packages/arcgis-rest-sharing/test/access.test.ts +154 -0
  251. package/packages/arcgis-rest-sharing/test/group-sharing.test.ts +566 -0
  252. package/packages/arcgis-rest-sharing/test/helpers.test.ts +55 -0
  253. package/packages/arcgis-rest-sharing/test/mocks/sharing.ts +18 -0
  254. package/packages/arcgis-rest-sharing/tsconfig.json +6 -0
  255. package/packages/arcgis-rest-users/README.md +71 -0
  256. package/packages/arcgis-rest-users/package-lock.json +11 -0
  257. package/packages/arcgis-rest-users/package.json +51 -0
  258. package/packages/arcgis-rest-users/src/get.ts +69 -0
  259. package/packages/arcgis-rest-users/src/index.ts +6 -0
  260. package/packages/arcgis-rest-users/src/invitation.ts +166 -0
  261. package/packages/arcgis-rest-users/src/notification.ts +73 -0
  262. package/packages/arcgis-rest-users/test/get.test.ts +99 -0
  263. package/packages/arcgis-rest-users/test/invitation.test.ts +169 -0
  264. package/packages/arcgis-rest-users/test/mocks/invitation.ts +70 -0
  265. package/packages/arcgis-rest-users/test/mocks/notification.ts +34 -0
  266. package/packages/arcgis-rest-users/test/mocks/user.ts +173 -0
  267. package/packages/arcgis-rest-users/test/notification.test.ts +83 -0
  268. package/packages/arcgis-rest-users/tsconfig.json +6 -0
  269. package/support/changelog.js +394 -0
  270. package/support/deploy-doc-site.js +16 -0
  271. package/support/publish.sh +43 -0
  272. package/support/test-helpers.js +8 -0
  273. package/tsconfig.json +69 -0
  274. package/tslint.json +15 -0
  275. package/umd-base-profile.js +82 -0
  276. package/umd-production-profile.js +13 -0
@@ -0,0 +1,873 @@
1
+ /* Copyright (c) 2017-2018 Environmental Systems Research Institute, Inc.
2
+ * Apache-2.0 */
3
+
4
+ import * as http from "http";
5
+ import {
6
+ request,
7
+ IRequestOptions,
8
+ ArcGISAuthError,
9
+ IAuthenticationManager,
10
+ ITokenRequestOptions
11
+ } from "@esri/arcgis-rest-request";
12
+ import { generateToken } from "./generate-token";
13
+ import { fetchToken, IFetchTokenResponse } from "./fetch-token";
14
+ import { IUser } from "@esri/arcgis-rest-common-types";
15
+
16
+ /**
17
+ * Internal utility for resolving a Promise from outside its constructor.
18
+ *
19
+ * See: http://lea.verou.me/2016/12/resolve-promises-externally-with-this-one-weird-trick/
20
+ */
21
+ interface IDeferred<T> {
22
+ promise: Promise<T>;
23
+ resolve: (v: T) => void;
24
+ reject: (v: any) => void;
25
+ }
26
+
27
+ export type AuthenticationProvider = "arcgis" | "facebook" | "google";
28
+
29
+ /**
30
+ * Represents a [credential]((https://developers.arcgis.com/javascript/latest/api-reference/esri-identity-Credential.html)) object used to access a secure ArcGIS resource.
31
+ */
32
+ export interface ICredential {
33
+ expires: number;
34
+ server: string;
35
+ ssl: boolean;
36
+ token: string;
37
+ userId: string;
38
+ }
39
+
40
+ function defer<T>(): IDeferred<T> {
41
+ const deferred: any = {
42
+ promise: null,
43
+ resolve: null,
44
+ reject: null
45
+ };
46
+
47
+ deferred.promise = new Promise((resolve, reject) => {
48
+ deferred.resolve = resolve;
49
+ deferred.reject = reject;
50
+ });
51
+
52
+ return deferred as IDeferred<T>;
53
+ }
54
+
55
+ /**
56
+ * Options for static OAuth 2.0 helper methods on `UserSession`.
57
+ */
58
+ export interface IOauth2Options {
59
+ /**
60
+ * Client ID of your application. Can be obtained by registering an application
61
+ * on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application),
62
+ * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise.
63
+ */
64
+ clientId: string;
65
+
66
+ /**
67
+ * A valid URL to redirect to after a user authorizes your application. Can be set on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application),
68
+ * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise.
69
+ */
70
+ redirectUri: string;
71
+
72
+ /**
73
+ * The ArcGIS Online or ArcGIS Enterprise portal you want to use for authentication. Defaults to `https://www.arcgis.com/sharing/rest` for the ArcGIS Online portal.
74
+ */
75
+ portal?: string;
76
+
77
+ /**
78
+ * ArcGIS Authentication is used by default. Specifying an alternative will take users directly to the corresponding provider's OAuth page.
79
+ */
80
+ provider?: AuthenticationProvider;
81
+
82
+ /**
83
+ * Duration (in minutes) that a token will be valid. Defaults to 20160 (two weeks).
84
+ */
85
+ duration?: number;
86
+
87
+ /**
88
+ * Determines whether to open the authorization window in a new tab/window or in the current window.
89
+ *
90
+ * @browserOnly
91
+ */
92
+ popup?: boolean;
93
+
94
+ /**
95
+ * Duration (in minutes) that a refresh token will be valid.
96
+ *
97
+ * @nodeOnly
98
+ */
99
+ refreshTokenTTL?: number;
100
+
101
+ /**
102
+ * The locale assumed to render the login page.
103
+ *
104
+ * @browserOnly
105
+ */
106
+ locale?: string;
107
+
108
+ /**
109
+ * Applications can specify an opaque value for this parameter to correlate the authorization request sent with the received response. By default, clientId is used.
110
+ *
111
+ * @browserOnly
112
+ */
113
+ state?: string;
114
+ }
115
+
116
+ /**
117
+ * Options for the `UserSession` constructor.
118
+ */
119
+ export interface IUserSessionOptions {
120
+ /**
121
+ * Client ID of your application. Can be obtained by registering an application
122
+ * on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application),
123
+ * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise.
124
+ */
125
+ clientId?: string;
126
+
127
+ /**
128
+ * A valid URL to redirect to after a user authorizes your application. Can be set on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application),
129
+ * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise.
130
+ */
131
+ redirectUri?: string;
132
+
133
+ /**
134
+ * OAuth 2.0 refresh token from a previous user session.
135
+ */
136
+ refreshToken?: string;
137
+
138
+ /**
139
+ * Expiration date of the `refreshToken`
140
+ */
141
+ refreshTokenExpires?: Date;
142
+
143
+ /**
144
+ * The authenticated user's username. Guaranteed to be unique across ArcGIS Online or your instance of ArcGIS Enterprise.
145
+ */
146
+ username?: string;
147
+
148
+ /**
149
+ * Password for this user. Used in CLI apps where users cannot do OAuth 2.0.
150
+ */
151
+ password?: string;
152
+
153
+ /**
154
+ * OAuth 2.0 access token from a previous user session.
155
+ */
156
+ token?: string;
157
+
158
+ /**
159
+ * Expiration date for the `token`
160
+ */
161
+ tokenExpires?: Date;
162
+
163
+ /**
164
+ * The ArcGIS Online or ArcGIS Enterprise portal you want to use for authentication. Defaults to `https://www.arcgis.com/sharing/rest` for the ArcGIS Online portal.
165
+ */
166
+ portal?: string;
167
+
168
+ /**
169
+ * This value is set to true automatically if the ArcGIS Organization requires that requests be made over https.
170
+ */
171
+ ssl?: boolean;
172
+
173
+ /**
174
+ * ArcGIS Authentication is used by default. Specifying an alternative will take users directly to the corresponding provider's OAuth page.
175
+ */
176
+ provider?: AuthenticationProvider;
177
+
178
+ /**
179
+ * Duration of requested token validity in minutes. Used when requesting tokens with `username` and `password` or when validating the identity of unknown servers. Defaults to two weeks.
180
+ */
181
+ tokenDuration?: number;
182
+
183
+ /**
184
+ * Duration (in minutes) that a refresh token will be valid.
185
+ */
186
+ refreshTokenTTL?: number;
187
+ }
188
+
189
+ /**
190
+ * ```js
191
+ * const session = new UserSession({
192
+ * username: "jsmith",
193
+ * password: "123456"
194
+ * })
195
+ * ```
196
+ * Used to manage the authentication of ArcGIS Online and ArcGIS Enterprise users
197
+ * in `request`. This class also includes several
198
+ * helper methods for authenticating users with [OAuth 2.0](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/browser-based-user-logins/) in both browser and
199
+ * server applications.
200
+ *
201
+ */
202
+ export class UserSession implements IAuthenticationManager {
203
+ /**
204
+ * Client ID being used for authentication if provided in the `constructor`.
205
+ */
206
+ readonly clientId: string;
207
+
208
+ /**
209
+ * The currently authenticated user if provided in the `constructor`.
210
+ */
211
+ readonly username: string;
212
+
213
+ /**
214
+ * The currently authenticated user's password if provided in the `constructor`.
215
+ */
216
+ readonly password: string;
217
+
218
+ /**
219
+ * The current portal the user is authenticated with.
220
+ */
221
+ readonly portal: string;
222
+
223
+ /**
224
+ * This value is set to true automatically if the ArcGIS Organization requires that requests be made over https.
225
+ */
226
+ readonly ssl: boolean;
227
+
228
+ /**
229
+ * The authentication provider to use.
230
+ */
231
+ readonly provider: AuthenticationProvider;
232
+
233
+ /**
234
+ * Determines how long new tokens requested are valid.
235
+ */
236
+ readonly tokenDuration: number;
237
+
238
+ /**
239
+ * A valid redirect URI for this application if provided in the `constructor`.
240
+ */
241
+ readonly redirectUri: string;
242
+
243
+ /**
244
+ * Duration of new OAuth 2.0 refresh token validity.
245
+ */
246
+ readonly refreshTokenTTL: number;
247
+
248
+ /**
249
+ * Hydrated by a call to [getUser()](#getUser-summary).
250
+ */
251
+ _user: IUser;
252
+
253
+ private _token: string;
254
+ private _tokenExpires: Date;
255
+ private _refreshToken: string;
256
+ private _refreshTokenExpires: Date;
257
+
258
+ /**
259
+ * Internal object to keep track of pending token requests. Used to prevent
260
+ * duplicate token requests.
261
+ */
262
+ private _pendingTokenRequests: {
263
+ [key: string]: Promise<string>;
264
+ };
265
+
266
+ /**
267
+ * Internal list of trusted 3rd party servers (federated servers) that have
268
+ * been validated with `generateToken`.
269
+ */
270
+ private trustedServers: {
271
+ [key: string]: {
272
+ token: string;
273
+ expires: Date;
274
+ };
275
+ };
276
+
277
+ /**
278
+ * The current ArcGIS Online or ArcGIS Enterprise `token`.
279
+ */
280
+ get token() {
281
+ return this._token;
282
+ }
283
+
284
+ /**
285
+ * The expiration time of the current `token`.
286
+ */
287
+ get tokenExpires() {
288
+ return this._tokenExpires;
289
+ }
290
+
291
+ /**
292
+ * The current token to ArcGIS Online or ArcGIS Enterprise.
293
+ */
294
+ get refreshToken() {
295
+ return this._refreshToken;
296
+ }
297
+
298
+ /**
299
+ * The expiration time of the current `refreshToken`.
300
+ */
301
+ get refreshTokenExpires() {
302
+ return this._refreshTokenExpires;
303
+ }
304
+
305
+ constructor(options: IUserSessionOptions) {
306
+ this.clientId = options.clientId;
307
+ this._refreshToken = options.refreshToken;
308
+ this._refreshTokenExpires = options.refreshTokenExpires;
309
+ this.username = options.username;
310
+ this.password = options.password;
311
+ this._token = options.token;
312
+ this._tokenExpires = options.tokenExpires;
313
+ this.portal = options.portal || "https://www.arcgis.com/sharing/rest";
314
+ this.ssl = options.ssl;
315
+ this.provider = options.provider || "arcgis";
316
+ this.tokenDuration = options.tokenDuration || 20160;
317
+ this.redirectUri = options.redirectUri;
318
+ this.refreshTokenTTL = options.refreshTokenTTL || 1440;
319
+
320
+ this.trustedServers = {};
321
+ this._pendingTokenRequests = {};
322
+ }
323
+
324
+ /**
325
+ * Begins a new browser-based OAuth 2.0 sign in. If `options.popup` is true the
326
+ * authentication window will open in a new tab/window otherwise the user will
327
+ * be redirected to the authorization page in their current tab.
328
+ *
329
+ * @browserOnly
330
+ */
331
+ /* istanbul ignore next */
332
+ static beginOAuth2(options: IOauth2Options, win: any = window) {
333
+ const {
334
+ portal,
335
+ provider,
336
+ clientId,
337
+ duration,
338
+ redirectUri,
339
+ popup,
340
+ state,
341
+ locale
342
+ }: IOauth2Options = {
343
+ ...{
344
+ portal: "https://www.arcgis.com/sharing/rest",
345
+ provider: "arcgis",
346
+ duration: 20160,
347
+ popup: true,
348
+ state: options.clientId,
349
+ locale: ""
350
+ },
351
+ ...options
352
+ };
353
+ let url: string;
354
+ if (provider === "arcgis") {
355
+ url = `${portal}/oauth2/authorize?client_id=${clientId}&response_type=token&expiration=${duration}&redirect_uri=${encodeURIComponent(
356
+ redirectUri
357
+ )}&state=${state}&locale=${locale}`;
358
+ } else {
359
+ url = `${portal}/oauth2/social/authorize?client_id=${clientId}&socialLoginProviderName=${provider}&autoAccountCreateForSocial=true&response_type=token&expiration=${duration}&redirect_uri=${encodeURIComponent(
360
+ redirectUri
361
+ )}&state=${state}&locale=${locale}`;
362
+ }
363
+
364
+ if (!popup) {
365
+ win.location.href = url;
366
+ return undefined;
367
+ }
368
+
369
+ const session = defer<UserSession>();
370
+
371
+ win[`__ESRI_REST_AUTH_HANDLER_${clientId}`] = function(
372
+ errorString: any,
373
+ oauthInfoString: string
374
+ ) {
375
+ if (errorString) {
376
+ const error = JSON.parse(errorString);
377
+ session.reject(new ArcGISAuthError(error.errorMessage, error.error));
378
+ return;
379
+ }
380
+
381
+ if (oauthInfoString) {
382
+ const oauthInfo = JSON.parse(oauthInfoString);
383
+ session.resolve(
384
+ new UserSession({
385
+ clientId,
386
+ portal,
387
+ ssl: oauthInfo.ssl,
388
+ token: oauthInfo.token,
389
+ tokenExpires: new Date(oauthInfo.expires),
390
+ username: oauthInfo.username
391
+ })
392
+ );
393
+ }
394
+ };
395
+
396
+ win.open(
397
+ url,
398
+ "oauth-window",
399
+ "height=400,width=600,menubar=no,location=yes,resizable=yes,scrollbars=yes,status=yes"
400
+ );
401
+
402
+ return session.promise;
403
+ }
404
+
405
+ /**
406
+ * Completes a browser-based OAuth 2.0 sign if `options.popup` is true the user
407
+ * will be returned to the previous window. Otherwise a new `UserSession`
408
+ * will be returned.
409
+ *
410
+ * @browserOnly
411
+ */
412
+ /* istanbul ignore next */
413
+ static completeOAuth2(options: IOauth2Options, win: any = window) {
414
+ const { portal, clientId }: IOauth2Options = {
415
+ ...{ portal: "https://www.arcgis.com/sharing/rest" },
416
+ ...options
417
+ };
418
+
419
+ function completeSignIn(error: any, oauthInfo?: IFetchTokenResponse) {
420
+ if (win.opener && win.opener.parent) {
421
+ win.opener.parent[`__ESRI_REST_AUTH_HANDLER_${clientId}`](
422
+ error ? JSON.stringify(error) : undefined,
423
+ JSON.stringify(oauthInfo)
424
+ );
425
+ win.close();
426
+ return undefined;
427
+ }
428
+
429
+ if (win !== win.parent) {
430
+ win.parent[`__ESRI_REST_AUTH_HANDLER_${clientId}`](
431
+ error ? JSON.stringify(error) : undefined,
432
+ JSON.stringify(oauthInfo)
433
+ );
434
+ win.close();
435
+ return undefined;
436
+ }
437
+
438
+ if (error) {
439
+ throw new ArcGISAuthError(error.errorMessage, error.error);
440
+ }
441
+
442
+ return new UserSession({
443
+ clientId,
444
+ portal,
445
+ ssl: oauthInfo.ssl,
446
+ token: oauthInfo.token,
447
+ tokenExpires: oauthInfo.expires,
448
+ username: oauthInfo.username
449
+ });
450
+ }
451
+
452
+ const match = win.location.href.match(
453
+ /access_token=(.+)&expires_in=(.+)&username=([^&]+)/
454
+ );
455
+
456
+ if (!match) {
457
+ const errorMatch = win.location.href.match(
458
+ /error=(.+)&error_description=(.+)/
459
+ );
460
+
461
+ const error = errorMatch[1];
462
+ const errorMessage = decodeURIComponent(errorMatch[2]);
463
+
464
+ return completeSignIn({ error, errorMessage });
465
+ }
466
+
467
+ const token = match[1];
468
+ const expires = new Date(
469
+ Date.now() + parseInt(match[2], 10) * 1000 - 60 * 1000
470
+ );
471
+ const username = decodeURIComponent(match[3]);
472
+ const ssl =
473
+ win.location.href.indexOf("&ssl=true") > -1 ||
474
+ win.location.href.indexOf("#ssl=true") > -1;
475
+
476
+ return completeSignIn(undefined, {
477
+ token,
478
+ expires,
479
+ ssl,
480
+ username
481
+ });
482
+ }
483
+
484
+ /**
485
+ * Begins a new server-based OAuth 2.0 sign in. This will redirect the user to
486
+ * the ArcGIS Online or ArcGIS Enterprise authorization page.
487
+ *
488
+ * @nodeOnly
489
+ */
490
+ static authorize(options: IOauth2Options, response: http.ServerResponse) {
491
+ const { portal, clientId, duration, redirectUri }: IOauth2Options = {
492
+ ...{ portal: "https://arcgis.com/sharing/rest", duration: 20160 },
493
+ ...options
494
+ };
495
+
496
+ response.writeHead(301, {
497
+ Location: `${portal}/oauth2/authorize?client_id=${clientId}&duration=${duration}&response_type=code&redirect_uri=${encodeURIComponent(
498
+ redirectUri
499
+ )}`
500
+ });
501
+
502
+ response.end();
503
+ }
504
+
505
+ /**
506
+ * Completes the server-based OAuth 2.0 sign in process by exchanging the `authorizationCode`
507
+ * for a `access_token`.
508
+ *
509
+ * @nodeOnly
510
+ */
511
+ static exchangeAuthorizationCode(
512
+ options: IOauth2Options,
513
+ authorizationCode: string
514
+ ): Promise<UserSession> {
515
+ const { portal, clientId, redirectUri, refreshTokenTTL }: IOauth2Options = {
516
+ ...{
517
+ portal: "https://www.arcgis.com/sharing/rest",
518
+ refreshTokenTTL: 1440
519
+ },
520
+ ...options
521
+ };
522
+
523
+ return fetchToken(`${portal}/oauth2/token`, {
524
+ grant_type: "authorization_code",
525
+ client_id: clientId,
526
+ redirect_uri: redirectUri,
527
+ code: authorizationCode
528
+ }).then(response => {
529
+ return new UserSession({
530
+ clientId,
531
+ portal,
532
+ ssl: response.ssl,
533
+ redirectUri,
534
+ refreshToken: response.refreshToken,
535
+ refreshTokenTTL,
536
+ refreshTokenExpires: new Date(
537
+ Date.now() + (refreshTokenTTL - 1) * 1000
538
+ ),
539
+ token: response.token,
540
+ tokenExpires: response.expires,
541
+ username: response.username
542
+ });
543
+ });
544
+ }
545
+
546
+ static deserialize(str: string) {
547
+ const options = JSON.parse(str);
548
+ return new UserSession({
549
+ clientId: options.clientId,
550
+ refreshToken: options.refreshToken,
551
+ refreshTokenExpires: new Date(options.refreshTokenExpires),
552
+ username: options.username,
553
+ password: options.password,
554
+ token: options.token,
555
+ tokenExpires: new Date(options.tokenExpires),
556
+ portal: options.portal,
557
+ ssl: options.ssl,
558
+ tokenDuration: options.tokenDuration,
559
+ redirectUri: options.redirectUri,
560
+ refreshTokenTTL: options.refreshTokenTTL
561
+ });
562
+ }
563
+
564
+ /**
565
+ * Translates authentication from the format used in the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/).
566
+ *
567
+ * ```js
568
+ * UserSession.fromCredential({
569
+ * userId: "jsmith",
570
+ * token: "secret"
571
+ * });
572
+ * ```
573
+ *
574
+ * @returns UserSession
575
+ */
576
+ static fromCredential(credential: ICredential) {
577
+ return new UserSession({
578
+ portal: credential.server + `/sharing/rest`,
579
+ ssl: credential.ssl,
580
+ token: credential.token,
581
+ username: credential.userId,
582
+ tokenExpires: new Date(credential.expires)
583
+ });
584
+ }
585
+
586
+ /**
587
+ * Returns authentication in a format useable in the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/).
588
+ *
589
+ * ```js
590
+ * esriId.registerToken(session.toCredential());
591
+ * ```
592
+ *
593
+ * @returns ICredential
594
+ */
595
+ toCredential(): ICredential {
596
+ return {
597
+ expires: this.tokenExpires.getTime(),
598
+ server: this.portal,
599
+ ssl: this.ssl,
600
+ token: this.token,
601
+ userId: this.username
602
+ };
603
+ }
604
+
605
+ /**
606
+ * Returns information about the currently logged in [user](https://developers.arcgis.com/rest/users-groups-and-items/user.htm). Subsequent calls will *not* result in additional web traffic.
607
+ *
608
+ * ```js
609
+ * session.getUser()
610
+ * .then(response => {
611
+ * console.log(response.role); // "org_admin"
612
+ * })
613
+ * ```
614
+ *
615
+ * @returns A Promise that will resolve with the data from the response.
616
+ */
617
+ getUser(requestOptions?: IRequestOptions): Promise<IUser> {
618
+ if (this._user && this._user.username === this.username) {
619
+ return Promise.resolve(this._user);
620
+ } else {
621
+ const url = `${this.portal}/community/users/${encodeURIComponent(
622
+ this.username
623
+ )}`;
624
+
625
+ const options = {
626
+ httpMethod: "GET",
627
+ authentication: this,
628
+ ...requestOptions
629
+ } as IRequestOptions;
630
+ return request(url, options).then(response => {
631
+ this._user = response;
632
+ return response;
633
+ });
634
+ }
635
+ }
636
+
637
+ /**
638
+ * Gets an appropriate token for the given URL. If `portal` is ArcGIS Online and
639
+ * the request is to an ArcGIS Online domain `token` will be used. If the request
640
+ * is to the current `portal` the current `token` will also be used. However if
641
+ * the request is to an unknown server we will validate the server with a request
642
+ * to our current `portal`.
643
+ */
644
+ getToken(url: string, requestOptions?: ITokenRequestOptions) {
645
+ if (
646
+ /^https?:\/\/\S+\.arcgis\.com\/sharing\/rest/.test(this.portal) &&
647
+ /^https?:\/\/\S+\.arcgis\.com.+/.test(url)
648
+ ) {
649
+ return this.getFreshToken(requestOptions);
650
+ } else if (new RegExp(this.portal).test(url)) {
651
+ return this.getFreshToken(requestOptions);
652
+ } else {
653
+ return this.getTokenForServer(url, requestOptions);
654
+ }
655
+ }
656
+
657
+ toJSON(): IUserSessionOptions {
658
+ return {
659
+ clientId: this.clientId,
660
+ refreshToken: this.refreshToken,
661
+ refreshTokenExpires: this.refreshTokenExpires,
662
+ username: this.username,
663
+ password: this.password,
664
+ token: this.token,
665
+ tokenExpires: this.tokenExpires,
666
+ portal: this.portal,
667
+ ssl: this.ssl,
668
+ tokenDuration: this.tokenDuration,
669
+ redirectUri: this.redirectUri,
670
+ refreshTokenTTL: this.refreshTokenTTL
671
+ };
672
+ }
673
+
674
+ serialize() {
675
+ return JSON.stringify(this);
676
+ }
677
+
678
+ /**
679
+ * Manually refreshes the current `token` and `tokenExpires`.
680
+ */
681
+ refreshSession(requestOptions?: ITokenRequestOptions): Promise<UserSession> {
682
+ if (this.username && this.password) {
683
+ return this.refreshWithUsernameAndPassword(requestOptions);
684
+ }
685
+
686
+ if (this.clientId && this.refreshToken) {
687
+ return this.refreshWithRefreshToken();
688
+ }
689
+
690
+ return Promise.reject(new ArcGISAuthError("Unable to refresh token."));
691
+ }
692
+
693
+ /**
694
+ * Validates that a given URL is properly federated with our current `portal`.
695
+ * Attempts to use the internal `trustedServers` cache first.
696
+ */
697
+ private getTokenForServer(
698
+ url: string,
699
+ requestOptions?: ITokenRequestOptions
700
+ ) {
701
+ // requests to /rest/services/ and /rest/admin/services/ are both valid
702
+ const [root] = url.split(/\/rest(\/admin)?\/services\//);
703
+ const existingToken = this.trustedServers[root];
704
+
705
+ if (existingToken && existingToken.expires.getTime() > Date.now()) {
706
+ return Promise.resolve(existingToken.token);
707
+ }
708
+
709
+ if (this._pendingTokenRequests[root]) {
710
+ return this._pendingTokenRequests[root];
711
+ }
712
+
713
+ this._pendingTokenRequests[root] = request(`${root}/rest/info`)
714
+ .then((response: any) => {
715
+ return response.owningSystemUrl;
716
+ })
717
+ .then(owningSystemUrl => {
718
+ /**
719
+ * if this server is not owned by this portal or the stand-alone
720
+ * instance of ArcGIS Server doesn't advertise federation,
721
+ * bail out with an error since we know we wont
722
+ * be able to generate a token
723
+ */
724
+ if (
725
+ !owningSystemUrl ||
726
+ !new RegExp(owningSystemUrl).test(this.portal)
727
+ ) {
728
+ throw new ArcGISAuthError(
729
+ `${url} is not federated with ${this.portal}.`,
730
+ "NOT_FEDERATED"
731
+ );
732
+ }
733
+ return request(`${owningSystemUrl}/sharing/rest/info`, requestOptions);
734
+ })
735
+ .then((response: any) => {
736
+ return response.authInfo.tokenServicesUrl;
737
+ })
738
+ .then((tokenServicesUrl: string) => {
739
+ if (this.token) {
740
+ return generateToken(tokenServicesUrl, {
741
+ params: {
742
+ token: this.token,
743
+ serverUrl: url,
744
+ expiration: this.tokenDuration
745
+ }
746
+ });
747
+ // generate an entirely fresh token if necessary
748
+ } else {
749
+ return generateToken(tokenServicesUrl, {
750
+ params: {
751
+ username: this.username,
752
+ password: this.password,
753
+ expiration: this.tokenDuration
754
+ }
755
+ }).then((response: any) => {
756
+ this._token = response.token;
757
+ this._tokenExpires = new Date(response.expires);
758
+ return response;
759
+ });
760
+ }
761
+ })
762
+ .then(response => {
763
+ this.trustedServers[root] = {
764
+ expires: new Date(response.expires),
765
+ token: response.token
766
+ };
767
+ return response.token;
768
+ });
769
+
770
+ return this._pendingTokenRequests[root];
771
+ }
772
+
773
+ /**
774
+ * Returns an unexpired token for the current `portal`.
775
+ */
776
+ private getFreshToken(requestOptions?: ITokenRequestOptions) {
777
+ if (
778
+ this.token &&
779
+ this.tokenExpires &&
780
+ this.tokenExpires.getTime() > Date.now()
781
+ ) {
782
+ return Promise.resolve(this.token);
783
+ }
784
+
785
+ if (!this._pendingTokenRequests[this.portal]) {
786
+ this._pendingTokenRequests[this.portal] = this.refreshSession(
787
+ requestOptions
788
+ ).then(session => {
789
+ this._pendingTokenRequests[this.portal] = null;
790
+ return session.token;
791
+ });
792
+ }
793
+
794
+ return this._pendingTokenRequests[this.portal];
795
+ }
796
+
797
+ /**
798
+ * Refreshes the current `token` and `tokenExpires` with `username` and
799
+ * `password`.
800
+ */
801
+ private refreshWithUsernameAndPassword(
802
+ requestOptions?: ITokenRequestOptions
803
+ ) {
804
+ const options = {
805
+ params: {
806
+ username: this.username,
807
+ password: this.password,
808
+ expiration: this.tokenDuration
809
+ },
810
+ ...requestOptions
811
+ };
812
+ return generateToken(`${this.portal}/generateToken`, options).then(
813
+ (response: any) => {
814
+ this._token = response.token;
815
+ this._tokenExpires = new Date(response.expires);
816
+ return this;
817
+ }
818
+ );
819
+ }
820
+
821
+ /**
822
+ * Refreshes the current `token` and `tokenExpires` with `refreshToken`.
823
+ */
824
+ private refreshWithRefreshToken(requestOptions?: ITokenRequestOptions) {
825
+ if (
826
+ this.refreshToken &&
827
+ this.refreshTokenExpires &&
828
+ this.refreshTokenExpires.getTime() < Date.now()
829
+ ) {
830
+ return this.refreshRefreshToken(requestOptions);
831
+ }
832
+
833
+ const options: ITokenRequestOptions = {
834
+ params: {
835
+ client_id: this.clientId,
836
+ refresh_token: this.refreshToken,
837
+ grant_type: "refresh_token"
838
+ },
839
+ ...requestOptions
840
+ };
841
+ return fetchToken(`${this.portal}/oauth2/token`, options).then(response => {
842
+ this._token = response.token;
843
+ this._tokenExpires = response.expires;
844
+ return this;
845
+ });
846
+ }
847
+
848
+ /**
849
+ * Exchanges an expired `refreshToken` for a new one also updates `token` and
850
+ * `tokenExpires`.
851
+ */
852
+ private refreshRefreshToken(requestOptions?: ITokenRequestOptions) {
853
+ const options: ITokenRequestOptions = {
854
+ params: {
855
+ client_id: this.clientId,
856
+ refresh_token: this.refreshToken,
857
+ redirect_uri: this.redirectUri,
858
+ grant_type: "exchange_refresh_token"
859
+ },
860
+ ...requestOptions
861
+ };
862
+
863
+ return fetchToken(`${this.portal}/oauth2/token`, options).then(response => {
864
+ this._token = response.token;
865
+ this._tokenExpires = response.expires;
866
+ this._refreshToken = response.refreshToken;
867
+ this._refreshTokenExpires = new Date(
868
+ Date.now() + (this.refreshTokenTTL - 1) * 60 * 1000
869
+ );
870
+ return this;
871
+ });
872
+ }
873
+ }