authentication in angular

2209
10
08-26-2022 05:53 AM
Mannus_Etten
Occasional Contributor

i find many examples pretty useful but all written with amd / require-syntax.

so also the example with oauth login.

so in the example there is:
  esriId.registerOAuthInfos([info]);
but that doesn't work in an angular app with es-modules. How does I do this now?
 
HHow do I get the OAuth-popup now?
 
i am looking for an example with es-modules. No amd-modules and also no "require(xxxx)"-syntax.
CEO the Right Direction BV/Portal Genius
10 Replies
ReneRubalcava
Honored Contributor

Check this video out. It's all in ESM and can be integrated into Angular projects.

https://community.esri.com/t5/arcgis-api-for-javascript-videos/identitymanager-in-the-arcgis-api-for...

Here's a blog post on the topic too.

https://odoe.net/blog/my-secret-arcgis-identity

 

0 Kudos
AndyGup
Esri Regular Contributor

@Mannus_Ettenthere are just a couple gotchas in Angular. If you aren't using an oauth popup, make sure you are adding the sign-in divs to your main component's html file. Also make sure to set the redirect_url when you register your app in your Portal (or ArcGIS Online), you may have to experiment with that a bit to get it right for your installation.  Here are some example snippets:

 

  @ViewChild('mapViewNode', { static: true }) private mapViewEl!: ElementRef;
  @ViewChild('anonymousPanel', { static: true }) private anonEl!: ElementRef;
  @ViewChild('personalizedPanel', {static: true}) private personalEl!: ElementRef;
  @ViewChild('signIn', {static: true}) private signInEl!: ElementRef;          

  . . . 
  this.anonEl.nativeElement.style.display = "none";
  this.personalEl.nativeElement.style.display = "block";

  this.signInEl.nativeElement.addEventListener("click", () => {
    // user will be redirected to OAuth Sign In page
    esriId.getCredential(info.portalUrl + "/sharing");
  });

 

 

 

Werkwijze_R_beheerder
New Contributor

hi Andy,

i prefer to have the popup-implementation. The popup shows, I can login and then i see in the popup the original angular-app... when i close the popup the console shows me that the login has been canceled 😞 I used the oauth-callback.html from the esri resources as callback url in the angular-app

Werkwijze_R_beheerder_0-1661587164644.png

 

0 Kudos
AndyGup
Esri Regular Contributor

Hi @Werkwijze_R_beheerder are you working with @Mannus_Etten on the same application? It's a little unclear, and I wanted to make sure the original question got answered, if possible. Your question seems more related to a potential configuration issue.

0 Kudos
Mannus_Etten
Occasional Contributor

I logged on to the wrong user to place the previous reply 🙂 What kind of configuration can I do to make sure that popup window can be closed and return the login-info and not "login canceled" ?

CEO the Right Direction BV/Portal Genius
0 Kudos
AndyGup
Esri Regular Contributor

Can you clarify what you mean by making sure the login popup can be closed? It should close automatically upon successful login. If a user manually closes the login popup, then it is expected to cancel the login process. That behavior is an industry-standard best practice for all login popups.

Can you provide a simple github repo that reproduces the issue? It's hard to say what's happening without seeing an example since there are a lot of pieces involved in authentication. Have you built a non-Angular, plain JavaScript app that is able to log in, just to verify the login functionality?

One easy thing to check, when getting credentials be sure to set oAuthPopupConfirmation to false:

 

document.getElementById("sign-in").addEventListener("click", () => {
  // user will be redirected to OAuth sign-in page
  esriId.getCredential((info.portalUrl + "/sharing"), {
    oAuthPopupConfirmation: false
  }).then(function() {
    displayItems();
  });
});

 

 

0 Kudos
Mannus_Etten
Occasional Contributor

i have added you to the repo, thanks already for your help!

CEO the Right Direction BV/Portal Genius
0 Kudos
AndyGup
Esri Regular Contributor

Hi @Mannus_Etten I got it working okay using the inline login pattern. The sample you sent me wasn't working correctly because of how Angular routing works. I think you already suspected that because I saw you started to implement a router.

Here's the example app.component.ts (Angular 13, "@arcgis/core" version 4.24). You'll need to figure out all the CSS and routing, etc that happens after the log in process.

import { Component } from '@angular/core';
import OAuthInfo from "@arcgis/core/identity/OAuthInfo";
import esriId from "@arcgis/core/identity/IdentityManager";
import Portal from "@arcgis/core/portal/Portal";
import PortalQueryParams from "@arcgis/core/portal/PortalQueryParams";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Test Login Page';

  private info: OAuthInfo = new OAuthInfo({
    // Swap this ID out with registered application ID
    appId: "YOUR_APPID_GOES_HERE",
    popup: false
  });

  ngOnInit(): void {
    esriId.registerOAuthInfos([this.info]);
    esriId.checkSignInStatus(this.info.portalUrl + "/sharing")
    .then(() => {
      console.log("checkSignInStatus: User is signed in.");
      this.displayItems();
    })
    .catch(() => { 
      console.error("checkSignInStatus: User not signed in.") 
    });
  }

  displayItems(): void  {
    const portal = new Portal();
    // Setting authMode to immediate signs the user in once loaded
    portal.authMode = "immediate";
    // Once loaded, user is signed in
    portal.load().then(() => {
      // Create query parameters for the portal search
      const queryParams = new PortalQueryParams({
        query: "owner:" + portal.user.username,
        sortField: "num-views",
        sortOrder: "desc",
        num: 20
      });
      console.log("User name: ", portal.user.username);
  
      // Query the items based on the queryParams created from portal above
      portal.queryItems(queryParams).then((q) => {
        console.log("Portal Query results:", q.results);
      });
    });
  }  

  // Call from app.component.html page
  onLogin() {
    esriId.getCredential(this.info.portalUrl + "/sharing");
  }

  // Call from app.component.html page  
  onLogout() {
    esriId.destroyCredentials();
    window.location.reload();
  }
}

 

 And here is the example app.component.html:

<!-- app.component.html -->
<div><button type="submit" (click)="onLogin()"><b>Login</b></button></div>
<div><button type="submit" (click)="onLogout()"><b>Logout</b></button></div>

 

0 Kudos
Mannus_Etten
Occasional Contributor

yeah thanks Andy, yesterday I had a look about what happened and the fact that my callback-html was never called did my realize that the routing is probably the issue, the popup is still my preferred way to do it so I have to dive deeper into that

CEO the Right Direction BV/Portal Genius
0 Kudos