How to display WFS layer with authentication (login/password)?

109
5
a week ago
Highlighted
New Contributor III

Hi,

I would like to use a WFS layer like in this example: https://developers.arcgis.com/net/latest/wpf/sample-code/display-wfs-layer/
but my wfs service requires a login + password authentication and i have no idea how to implement this authentication.
So how to do?
Thanks in advance for all the answers

Cordialement,

Jean-Christophe

 

Tags (2)
Reply
0 Kudos
5 Replies
Highlighted
Esri Contributor

Hi Jean-Cristophe. I recommend looking at our security samples for help with authentication workflows. Can you please share information about what type of authentication you're using for your WFS layer?

Zack

Reply
0 Kudos
Highlighted
New Contributor III

Hello Zack,

Authentication type should be Basic : WWW-Authenticate: Basic realm="mapservRLV"

Regards,

jcb

Reply
0 Kudos
Highlighted
Esri Contributor

Hello,

In this particular scenario, I would suggest going through Zack's recommendation first to see if that answers your questions. 

If you have already tried adding a NetworkCredential with username/password and still the server denies access (does not challenge the client for username/password). I would also suggest trying out the following code if your server implements a HTTP Basic authentication. 

 

private void EagerlyAddNetworkCredentials(object sender, HttpRequestMessage e)
{
    var anyCred = Esri.ArcGISRuntime.Security.AuthenticationManager.Current.FindCredential(e.RequestUri, AuthenticationType.NetworkCredential);
    if (anyCred is ArcGISNetworkCredential runtimeNetCred)
    {
        // If a NetworkCredential is found for this request, but we are still waiting to be challenged...
        if (!e.Headers.Contains("Authorization"))
        {
            // Generate an HTTP Basic Authorization header per RFC 2617
            var netCred = runtimeNetCred.Credentials.GetCredential(e.RequestUri, "Basic");
            var rawCredentialBytes = Encoding.GetEncoding("ISO-8859-1").GetBytes($"{netCred.UserName}:{netCred.Password}");

            // Add it to the request
            e.Headers.Add("Authorization", $"Basic {Convert.ToBase64String(rawCredentialBytes)}");
        }
    }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

//Loads the service
private async void WFSNetworkCred()
{
    ArcGISHttpClientHandler.HttpRequestBegin += EagerlyAddNetworkCredentials;

    MyView.Map = new Map(Basemap.CreateImagery());
    var am = Esri.ArcGISRuntime.Security.AuthenticationManager.Current;
    am.AddCredential(new ArcGISNetworkCredential
    {
        ServiceUri = new Uri("Insert_Service_URL_Here"),
        Credentials = new NetworkCredential("username", "password"),
    });

    var wfs = "Insert_Service_URL_Here";
    var wfsService = new WfsService(new Uri(wfs));
    await wfsService.LoadAsync();
} ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

 

I protected a local GeoServer service with a username and password. Some OGC services do not challenge the clients to log in. The service needs an `Authentication` header present in the request (for ex. Basic authentication header). This scenario forces the clients to `eagerly` send their login info with the request itself and not wait for the challenge to come back.

This is currently not supported in the Runtime SDK. However, a possible workaround could be to tap into the ArcGISHttpClientHandler.HttpRequestBegin Event, forcing it to add our NetworkCredentials with the outgoing requests (like in the code above).

I hope this works for you. Let me know if you face any problems.

Reply
0 Kudos
Highlighted
New Contributor III

Hello Aditya,

Thank you for your useful answer. It seens to work for the network credential.

But i get an other error when opening layer : "Invalid XML.: Parser was expecting WFS_Capabilities."

Could you help me again ?

This is my code (with some confidential information masked) :

 

private async void Initialize()
{
ArcGISHttpClientHandler.HttpRequestBegin += EagerlyAddNetworkCredentials;

// Create the map with topographic basemap.
MyMapView.Map = new Map(Basemap.CreateTopographic());

try
{
var am = Esri.ArcGISRuntime.Security.AuthenticationManager.Current;
am.AddCredential(new ArcGISNetworkCredential
{
ServiceUri = new Uri("http://x.y.z.1/cgi-bin/mapservRLV.exe?map=D:/GFI/Cartes/client1/Carte4_IA.map"),
Credentials = new NetworkCredential("toto", "titi"),
});

var wfs = "http://x.y.z.1/cgi-bin/mapservRLV.exe?map=D:/GFI/Cartes/client1/Carte4_IA.map&service=WFS&request=GetCapabilities&version=1.1.0";
var wfsService = new Esri.ArcGISRuntime.Ogc.WfsService(new Uri(wfs));
await wfsService.LoadAsync();

...


}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "Couldn't load sample.");
Debug.WriteLine(e);
}

 

 

I forget to say that the request with GetCapabilities works in the browser.

Thanks

 

 

Reply
0 Kudos
Highlighted
Esri Contributor

Hello Jean-Christophe,

My assumption is that the credential is not getting applied to the GetCapabilities url. Maybe try adding another Credential and let the serviceUri be the GetCapabilities url.

I hope this works.

Thanks,

Aditya

Reply
0 Kudos