Search code examples
javascriptarcgisarcgis-js-api

Setting up App based login with ArcGIS JavaScript API


I'm trying to implement an ArcGIS map into an existing JavaScript app (Node.js/React) and started seeing an ArcGIS login pop up window appear in my app when trying to load layers from ArcGIS Online. Since not all of my users will have ArcGIS accounts, I want to enable app based login.

From the documentation (which seems like it's leading me around in circles) it looks like I need to setup my Nodejs server with my client id/secret so that it can get access tokens and then send them to the client so that the client can in turn have access to the resources from ArcGIS Online.

The server side part of that seems easy enough - just make a request and get a valid token back. But I'm not clear what to do once my client app gets the token from my Nodejs server. Since my client side code is written using React I'm using the @esri/react-arcgis npm package to load the ArcGIS modules. I've been playing around with the IdentityManager module but am having no success.

If anyone has any idea how to setup the app based login I'd really appreciate it. Here's my client side React code.

import React from 'react';
import {loadModules} from '@esri/react-arcgis';
const options = {url: 'https://js.arcgis.com/4.6/'};

const styles = {
  container: {
    height: '100%',
    width: '100%'
  },
  mapDiv: {
    padding: 0,
    margin: 0,
    height: '100%',
    width: '100%'
  },
}

export default class MapTab extends React.Component {

    constructor(props) {
      super(props);
      this.state = {
        status: 'loading'
      }

      loadModules(['esri/Map', 'esri/views/MapView', 'esri/layers/MapImageLayer'], options)
        .then(([Map, MapView, MapImageLayer]) => {

          // how do I implement app based login here once I have the access token?

          var layer3 = new MapImageLayer({
            url: "https://livefeeds.arcgis.com/arcgis/rest/services/LiveFeeds/NWS_Watches_Warnings_and_Advisories/MapServer"
          });

          const map = new Map({
            basemap: "hybrid",
            layers: [layer3]
          });

          const view = new MapView({
            container: "viewDiv",
            map,
            center: [this.props.latLng.lng, this.props.latLng.lat],
            zoom: 5,
          });

          view.when(() => {
            this.setState({
              map,
              view,
              status: 'loaded'
            });
          });
        })

    }
        renderMap() {
          if(this.state.status === 'loading') {
            return <h1>loading</h1>;
          }
        }

        render() {
          if(this.state.view){
            this.state.view.goTo([this.props.latLng.lng, this.props.latLng.lat])
          }

          return(
                <div id='parent' style={styles.container}>
                  <div id='viewDiv' style={ styles.mapDiv } >
                    {this.renderMap()}
                  </div>
                </div>
          )
        }
      }

Solution

  • I ended up using this solution where the comment code is in my example.

    esriId.registerToken({
            server: 'https://www.arcgis.com/sharing',
            token: 'access token here'
          });
    

    Previously I had been using the registerToken method with specific servers that only granted me access to those specific servers when a token was registered under them. Using "https://www.arcgis.com/sharing" as the server value seems to give me access to all the public/premium resources I wanted to use at the same time.

    It works for my use case although I can't find any similar examples in the documentation.