WMS Service with UserName and Password

2444
7
04-17-2020 03:57 PM
KiroAndreev1
New Contributor II

Dear,

I have next code:

Uri uri = new Uri(currentServiceUrl);

WmsService service = new WmsService(uri);

await service.LoadAsync();

When put wms service with username and password control await service.LoadAsync(); show next error:

System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Full authentication is required to access this resource).

How to solved this problem?

Best Regard

0 Kudos
7 Replies
MichaelBranscomb
Esri Frequent Contributor

Hi,

It sounds like you need to add a handler for the authentication challenge event then respond appropriately. For some examples showing working with different authentication protocols see arcgis-runtime-samples-dotnet/src/WPF/ArcGISRuntime.WPF.Viewer/Samples/Security at master · Esri/arc... 

Regards

Mike 

KiroAndreev1
New Contributor II

Dear Michael,

I tested TokenSecuredChallenge example because i think this is close for my service.I use WMS service from Geo Server which is protected with user name and password and can not view data on map.I would like to ask, examples which you send me is for service created with ArcgGis server or for service created whoever Server?

Also, i would like to give me example or explanation explicitly for wms service which is protected. 

Best Regard

0 Kudos
AdityaTogani
Esri Contributor

Hello,

I tried reproducing the problem you were noticing. I protected a local GeoServer service with a username and password. After using the ChallengeHandler in the Runtime SDK, I still got the `401 (Full authentication is required to access this resource)` response status code. After investigating a little, I found that some GeoServer 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. 

        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 WMSNetworkCred()
        {
            ArcGISHttpClientHandler.HttpRequestBegin += EagerlyAddNetworkCredentials;

            MyView.Map = new Map(Basemap.CreateImagery());
            var am = Esri.ArcGISRuntime.Security.AuthenticationManager.Current;
            am.AddCredential(new ArcGISNetworkCredential
            {
                ServiceUri = new Uri("http://localhost:8080/geoserver/ows?service=wms&version=1.3.0&request=GetCapabilities"),
                Credentials = new NetworkCredential("admin", "geoserver"),
            });

            var wms = "http://localhost:8080/geoserver/ows?service=wms&version=1.3.0&request=GetCapabilities";
            var wmsService = new WmsService(new Uri(wms));
            await wmsService.LoadAsync();
        } ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

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

0 Kudos
KiroAndreev1
New Contributor II

Dear Aditya Togani,

i write all your code in my project (with my serviceUrl, username and password)  but on  await wmsService.LoadAsync(); my applicateion have error:

Esri.ArcGISRuntime.ArcGISRuntimeException: Invalid XML.: Parser was expecting WMS_Capabilities.

I will expect after 

am.AddCredential(new ArcGISNetworkCredential
{
ServiceUri = new Uri("MyURI"),
Credentials = new NetworkCredential("MyUser", "MyPassword"),
});

WmsService to get another uri string or something similar 

var wms = "ANOTHER STRING" OR SOMETHING SIMILAR;

WmsService wmsService = new WmsService(new uri(wms));
await wmsService .LoadAsync();

Best Regard

0 Kudos
AdityaTogani
Esri Contributor

Hello Kiro Andreev,

The service URI has to be a GetCapabilities request and the service should be WMS. Is the version of your service 1.3.0?

0 Kudos
KiroAndreev1
New Contributor II

Dear Aditya Togani,

The service is:

  • GetCapabilities 
  • WMS
  • version 1.3.0

Best Regard.

0 Kudos
AdityaTogani
Esri Contributor

Hey Kiro,

Can you share your WMS service URL with us? You can email me at atogani@esri.com. We need the URL to investigate this properly by reproducing it.

0 Kudos