From 041f96ce1cb76e9edb288984f26f7e7242abc289 Mon Sep 17 00:00:00 2001 From: William Newman <3382274+newmanw@users.noreply.github.com> Date: Fri, 1 Nov 2024 12:36:23 -0600 Subject: [PATCH] [service] OAuth refresh token flow in work --- .../src/ArcGISIdentityManagerFactory.ts | 45 ++++++++++--------- .../arcgis/service/src/FeatureServiceAdmin.ts | 24 ++-------- .../service/src/ObservationProcessor.ts | 9 ++-- plugins/arcgis/service/src/index.ts | 4 +- 4 files changed, 32 insertions(+), 50 deletions(-) diff --git a/plugins/arcgis/service/src/ArcGISIdentityManagerFactory.ts b/plugins/arcgis/service/src/ArcGISIdentityManagerFactory.ts index dafadec96..ee5d17cf7 100644 --- a/plugins/arcgis/service/src/ArcGISIdentityManagerFactory.ts +++ b/plugins/arcgis/service/src/ArcGISIdentityManagerFactory.ts @@ -1,13 +1,12 @@ import { ArcGISIdentityManager, request } from "@esri/arcgis-rest-request" import { ArcGISAuthConfig, AuthType, FeatureServiceConfig, OAuthAuthConfig, TokenAuthConfig, UsernamePasswordAuthConfig } from './ArcGISConfig' -import { ObservationProcessor } from "./ObservationProcessor"; interface ArcGISIdentityManagerFactory { - create(portal: string, server: string, config: ArcGISAuthConfig, processor?: ObservationProcessor): Promise + create(portal: string, server: string, config: ArcGISAuthConfig): Promise } const OAuthIdentityManagerFactory: ArcGISIdentityManagerFactory = { - async create(portal: string, server: string, auth: OAuthAuthConfig, processor: ObservationProcessor): Promise { + async create(portal: string, server: string, auth: OAuthAuthConfig): Promise { console.debug('Client ID provided for authentication') const { clientId, authToken, authTokenExpires, refreshToken, refreshTokenExpires } = auth @@ -27,24 +26,27 @@ const OAuthIdentityManagerFactory: ArcGISIdentityManagerFactory = { httpMethod: 'GET' }); + // TODO Factory should not handle config changes // Update authToken to new token - const config = await processor.safeGetConfig(); - let service = config.featureServices.find(service => service.url === portal)?.auth as OAuthAuthConfig; - const date = new Date(); - date.setSeconds(date.getSeconds() + response.expires_in || 0); - service = { - ...service, - authToken: response.access_token, - authTokenExpires: date.getTime() - } + // const config = await processor.safeGetConfig(); + // let service = config.featureServices.find(service => service.url === portal)?.auth as OAuthAuthConfig; + // const date = new Date(); + // date.setSeconds(date.getSeconds() + response.expires_in || 0); + // service = { + // ...service, + // authToken: response.access_token, + // authTokenExpires: date.getTime() + // } + // await processor.putConfig(config) - await processor.putConfig(config) - return ArcGISIdentityManager.fromToken({ - clientId: clientId, - token: response.access_token, - tokenExpires: date, - portal: portal - }); + // return ArcGISIdentityManager.fromToken({ + // clientId: clientId, + // token: response.access_token, + // tokenExpires: date, + // portal: portal + // }); + + throw new Error('TODO Unsupported') } catch (error) { throw new Error('Error occurred when using refresh token') } @@ -86,8 +88,7 @@ const authConfigMap: { [key: string]: ArcGISIdentityManagerFactory } = { } export function getIdentityManager( - config: FeatureServiceConfig, - processor: ObservationProcessor + config: FeatureServiceConfig ): Promise { const auth = config.auth const authType = config.auth?.type @@ -98,7 +99,7 @@ export function getIdentityManager( if (!factory) { throw new Error(`No factory found for type ${authType}`) } - return factory.create(getPortalUrl(config.url), getServerUrl(config.url), auth, processor) + return factory.create(getPortalUrl(config.url), getServerUrl(config.url), auth) } diff --git a/plugins/arcgis/service/src/FeatureServiceAdmin.ts b/plugins/arcgis/service/src/FeatureServiceAdmin.ts index eb371c84a..16dbcebd1 100644 --- a/plugins/arcgis/service/src/FeatureServiceAdmin.ts +++ b/plugins/arcgis/service/src/FeatureServiceAdmin.ts @@ -4,7 +4,6 @@ import { MageEvent, MageEventRepository } from '@ngageoint/mage.service/lib/enti import { Layer, Field } from "./AddLayersRequest" import { Form, FormField, FormFieldType, FormId } from '@ngageoint/mage.service/lib/entities/events/entities.events.forms' import { ObservationsTransformer } from "./ObservationsTransformer" -import { HttpClient } from './HttpClient' import { LayerInfoResult, LayerField } from "./LayerInfoResult" import FormData from 'form-data' import { request } from '@esri/arcgis-rest-request' @@ -433,8 +432,7 @@ export class FeatureServiceAdmin { */ private async create(service: FeatureServiceConfig, layer: Layer) { - const httpClient = this.httpClient(service) - const identityManager = await getIdentityManager(service, httpClient) + const identityManager = await getIdentityManager(service) const url = this.adminUrl(service) + 'addToDefinition' this._console.info('ArcGIS feature service addToDefinition (create layer) url ' + url) @@ -461,8 +459,7 @@ export class FeatureServiceAdmin { const layer = { fields: fields} as Layer - const httpClient = this.httpClient(service) - const identityManager = await getIdentityManager(service, httpClient) + const identityManager = await getIdentityManager(service) const url = this.adminUrl(service) + featureLayer.layer.toString() + '/addToDefinition' this._console.info('ArcGIS feature layer addToDefinition (add fields) url ' + url) @@ -501,8 +498,7 @@ export class FeatureServiceAdmin { const layer = {} as Layer layer.fields = deleteFields - const httpClient = this.httpClient(service) - const identityManager = await getIdentityManager(service, httpClient) + const identityManager = await getIdentityManager(service) const url = this.adminUrl(service) + featureLayer.layer.toString() + '/deleteFromDefinition' this._console.info('ArcGIS feature layer deleteFromDefinition (delete fields) url ' + url) @@ -532,18 +528,4 @@ export class FeatureServiceAdmin { } return url } - - /** - * Get a HTTP Client with administration token - * @param service feature service - * @returns http client - */ - private httpClient(service: FeatureServiceConfig): HttpClient { - let token = service.adminToken - if (token == null) { - token = service.auth?.type == 'token' ? service.auth.token : "" - } - return new HttpClient(console, token) - } - } diff --git a/plugins/arcgis/service/src/ObservationProcessor.ts b/plugins/arcgis/service/src/ObservationProcessor.ts index 89a6fb6c4..045541a1a 100644 --- a/plugins/arcgis/service/src/ObservationProcessor.ts +++ b/plugins/arcgis/service/src/ObservationProcessor.ts @@ -14,10 +14,9 @@ import { EventTransform } from './EventTransform'; import { GeometryChangedHandler } from './GeometryChangedHandler'; import { EventDeletionHandler } from './EventDeletionHandler'; import { EventLayerProcessorOrganizer } from './EventLayerProcessorOrganizer'; -import { FeatureServiceConfig, FeatureLayerConfig, AuthType, OAuthAuthConfig } from "./ArcGISConfig" +import { FeatureServiceConfig, FeatureLayerConfig, AuthType } from "./ArcGISConfig" import { PluginStateRepository } from '@ngageoint/mage.service/lib/plugins.api' import { FeatureServiceAdmin } from './FeatureServiceAdmin'; -import { HttpClient } from './HttpClient' import { getIdentityManager } from "./ArcGISIdentityManagerFactory" import { request } from '@esri/arcgis-rest-request'; @@ -218,7 +217,7 @@ export class ObservationProcessor { for (const serv of services) { try { - const identityManager = await getIdentityManager(serv, new HttpClient(console)) + const identityManager = await getIdentityManager(serv) const response = await request(serv.url, { authentication: identityManager }) as FeatureServiceResult @@ -292,7 +291,7 @@ export class ObservationProcessor { if (layerId != null) { featureLayer.layer = layerId - const identityManager = await getIdentityManager(featureServiceConfig, new HttpClient(console)) + const identityManager = await getIdentityManager(featureServiceConfig) const featureService = new FeatureService(console, featureServiceConfig, identityManager) const layerInfo = await featureService.queryLayerInfo(layerId); const url = `${featureServiceConfig.url}/${layerId}`; @@ -320,7 +319,7 @@ export class ObservationProcessor { await admin.updateLayer(featureServiceConfig, featureLayer, layerInfo, this._eventRepo) } const info = new LayerInfo(url, events, layerInfo, featureLayer.token) - const identityManager = await getIdentityManager(featureServiceConfig, new HttpClient(console)) + const identityManager = await getIdentityManager(featureServiceConfig) const layerProcessor = new FeatureLayerProcessor(info, config, identityManager,this._console); this._layerProcessors.push(layerProcessor); // clearTimeout(this._nextTimeout); // TODO why is this needed? diff --git a/plugins/arcgis/service/src/index.ts b/plugins/arcgis/service/src/index.ts index c3d9e02f6..657e21e51 100644 --- a/plugins/arcgis/service/src/index.ts +++ b/plugins/arcgis/service/src/index.ts @@ -193,7 +193,7 @@ const arcgisPluginHooks: InitPluginHook = { try { // Create the IdentityManager instance to validate credentials - await getIdentityManager(service!, processor) + await getIdentityManager(service) let existingService = config.featureServices.find(service => service.url === url) if (existingService) { existingService = { ...existingService } @@ -216,7 +216,7 @@ const arcgisPluginHooks: InitPluginHook = { } try { - const identityManager = await getIdentityManager(featureService, processor) + const identityManager = await getIdentityManager(featureService) const response = await request(url, { authentication: identityManager })