ducimusipsa 1.0.0

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