ducimusipsa 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 (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
+ }