Select to view content in your preferred language

Creating a new Geodatabase object using ServiceConnectionProperties + username and password with a token-secured FeatureServer

1948
3
06-20-2023 07:03 AM
ThomasRea
Occasional Contributor

ThomasRea_0-1687269578471.png

 

My requirements are pretty straightforward. WE have an AGO hosted feature server that is token secured, but I need to create a direct geodatabase connection using the .NET SDK via a Core Host application (note: this code works just fine through an add-in context). However, I'm getting the following error: 

ArcGIS.Core.Data.GeodatabaseNotFoundOrOpenedException: Cannot find or open the specified geodatabase or data store. ---> ArcGIS.Core.Data.ServiceException: Authentication token required. ---> System.Runtime.InteropServices.COMException: Exception from HRESULT: 0x8004021A

Which is strange, because I'm supplying the username and password. The SDK offers no way to set the Token. Also, even stranger, is that when I use the same code to create a connection to the same service from within an add-in, the username and password are not used, and the connection works. I'm guessing it's because the COM call is already authenticated since pro is open and I am logged in with my AGO credentials already. Any ideas?

0 Kudos
3 Replies
CharlesMacleod
Esri Regular Contributor

Rather buried in the documentation, I'm afraid, is the explanation for why this isnt working:

https://pro.arcgis.com/en/pro-app/latest/sdk/api-reference/topic15000.html

the User and PWD properties are for use with legacy ArcGIS Server hosted services that are _not_ federated.

Instead, I think this is the pattern u r looking for:

ArcGIS.Core.System.Core.ArcGISSignOn: https://pro.arcgis.com/en/pro-app/latest/sdk/api-reference/topic25971.html

Ideally u register a sign-on handler and resolve the credentials in your sign-on handler based on which service is calling u back (on your handler). However, if u know, upfront, that u r always calling just one service then u can bypass the callback handler pattern and just go against ArcGIS.Core.System.Core.ArcGISSignOn.SignInWIthCredentials directly.

Here's what it would look like tho' there is a complete example here: https://pro.arcgis.com/en/pro-app/latest/sdk/api-reference/topic25964.html

No callback:

//just call SignInwithCredentials directly....no call back:
var scp = new ServiceConnectionProperties(feature_service_uri);
//authenticate
string referer = "";
string token = "";
var ok = ArcGIS.Core.SystemCore.ArcGISSignOn.Instance.SignInWithCredentials(
				 portal_uri, user, superSecretPwd, out referer, out token);
//connect
using (var federatedFeatureService = new Geodatabase(scp)) {
   ...

 

With callback:

internal class ChallengeHandler : ISignOnHandler {

  private void GetStoredUserNameAndPassword(
       string url, out string user, out string pwd) {
    user = "";
    pwd = "";
    if (url == "https://your_portal/portal/")
    {
       //TODO retrieve the relevant credentials
    }
    else if (url == "https://your_portal2/portal/")
    {
       //etc.
    }
  }

   //Call back when the service requires authentication
   public void GenerateCredentials(ref SIGNONHANDLERINFO info){

    string user = "";
    string superSecretPwd = "";

    GetStoredUserNameAndPassword(
          info.agoURL, out user, out superSecretPwd);

    //Authenticate
    var uri = new Uri(info.agoURL, UriKind.Absolute);
    string referer = "";
    string token = "";
    var ok = 
     ArcGIS.Core.SystemCore.ArcGISSignOn.Instance.SignInWithCredentials(
    	 uri, user, superSecretPwd, out referer, out token);
    if (ok) {
    	//TODO: for example, if you want to retain the token and referer
    	//for your own purposes that code would go here...
    }
  }
}

 //elsewhere - in your console Main(...)
 //Set your challenge handler...
 ArcGIS.Core.SystemCore.ArcGISSignOn.Instance.SetSignonHandler(new ChallengeHandler());

 var scp = new ServiceConnectionProperties(feature_service_uri);

 //connect - if authentication is required, your callback will be invoked...
 using (var federatedFeatureService = new Geodatabase(scp)) {
   ...

 

 

 

 

 

 

 

 

0 Kudos
ThomasRea
Occasional Contributor

Thank you! Ultimately, that's the conclusion I came too as well after discussing with ESRI support. Unfortunately, though, the ISignOnHandler.GenerateCredentials doesn't seem to be called by the Geodatabase constructor (I get the same exception as before). When I do it explicitly by directly calling ArcGISSignOn.Instance.SignInWithCredentials, it does work, but then I'm encountering unexpected caching behavior, so this solution also isn't ideal for me. The ideal scenario is that GenerateCredentials would not cache tokens between processes/executions and would expose some way to revoke a token after execution. However, the ArcGISSignOn.Instance.SignOut doesn't seem to work as expected, because follow-up executions remain authenticated, even after calling this method. Very strange.

0 Kudos
CharlesMacleod
Esri Regular Contributor

It is probably related to this:

https://pro.arcgis.com/en/pro-app/latest/help/projects/sign-in-to-your-organization.htm

note option 3:

  • Check Sign in automatically to have ArcGIS Pro store your credentials and sign in to the portal automatically; this option is checked by default.
  • Uncheck Sign in automatically if you prefer to provide your credentials each time you start ArcGIS Pro.

 

 

0 Kudos