Visual Basic (Declaration) | |
---|---|
Public Property ClientCertificate As X509Certificate |
C# | |
---|---|
public X509Certificate ClientCertificate {get; set;} |
A client certificate is an electronic document which uses a digital signature to bind a public key with an identity. A client certificate is used to verify that a public key belongs to an individual or an organization. When a client certificate is valid, access to secured content over the https:// is enabled. Client certificates fall under the technology umbrella known as a Public-Key Infrastructure (PKI). PKI is a large complex body of standards, policies, protocols, and practices that are beyond the scope this documentation. The following Microsoft document should give the developer a starting point to understand PKI: Public Key Infrastructure.
ArcGIS Server version 10.1 and higher has the ability to leverage PKI solutions in 'Commercial Off the Shelf' (COTS) Web servers such as: Microsoft Internet Information Server (IIS), Oracle WebLogic, IBM WebSphere, etc. through the use of the ArcGIS Web Adaptor. The requirements for using PKI in ArcGIS Server include:
- The ArcGIS Web Adaptor must be setup as the gateway to ArcGIS Server.
- The Web Server hosting the ArcGIS Web Adaptor must be configured to require client certificates for user authentication.
- ArcGIS Server Site must be configured to: (a) Delegate user authentication to the Web Tier and (b) Use an identity store (LDAP, Windows Active Directory, etc.) supported by the Web Server.
When a request is made for a resource on ArcGIS Server, the Web Server will authenticate the user by validating the client certificate provided. The request (along with the user name) is then forwarded to ArcGIS Server via the Web Adaptor. ArcGIS Server will verify that the specified user has access to the requested resource before sending back the appropriate response. For more information on using PKI techniques to set up and use client certificates, see the ArcGIS Server documentation.
The ArcGIS Runtime for WPF requires supplying a valid Microsoft System.Security.Cryptography.X509Certificates.X509Certificate object as the .ClientCertificate Property in order to gain access to a secured (https://) ArcGIS Server web service based upon PKI. The Microsoft System.Security.Cryptography.X509Certificates Namespace API documentation provides a starting point for developers to learn how to programmatically access X509Certificate objects. If no client certificates have been set up on a client machine and a user tries to access using an X509Certificate from your custom ArcGIS WPF application, a Windows Security dialog stating "No certificate available. No certificates meet the application. Click OK to continue" will appear:
Whenever an ArcGIS Runtime for WPF based application uses PKI to secure web services, it is important that error checking be added to the application to ensure that the correct X509Certificate is used to access those secured web services. If a user of your ArcGIS WPF client application provides/uses an X509Certificate that is not accepted by the PKI security set up on the ArcGIS Server machine, then an error will be thrown. The following are a couple of different error messages that could occur:
"Error initializing layer: The remote server returned an error: (403) Forbidden.":
"Error initializing layer: The remote server returned an error: (401) Unauthorized.":
Depending on the particular ArcGIS Runtime for WPF object that is used, the developer will need to write code in the appropriate error handling event. For example: an ArcGISDynmaicMapServiceLayer should have error trapping code in the InitializationFailed Event; a QueryTask should have error trapping code in the Failed Event, a PrintTask should have error trapping code in the ExecuteCompleted Event (via the PrintEventArgs), etc.
The .ClientCertificate Property has been added to numerous ArcGIS Runtime for WPF objects. Accessing and using an X509Certificate is basically the same for each of the ArcGIS Runtime for WPF objects with a .ClientCertificate Property. There are code examples of using the X509Certificate in the DynamicMapServiceLayer.ClientCertificate Property, ArcGISTiledMapServiceLayer.ClientCertificate Property, Printing.PrintTask.ClientCertificate Property (code-behind only options) and FeatureLayer.ClientCertificate Property (Model-View-View-Model (MVVM) pattern using XAML and code-behind). Remember the key to accessing a PKI based secured ArcGIS Server web service is to first provide the appropriate .ClientCertificate Property credentials during construction of the object and prior to using (i.e Set/Write) any of the other properties/methods of the ArcGIS Runtime for WPF object, otherwise an error accessing that object will result.
Property Value
The client certificate used for authentication.How to use:
Click the 'Load Certificate' button to choose a Public Key Infrasturcture (PKI) certificate from the dialog. Then click the 'Add Secured ArcGISDynamicMapServiceLayer' button to add a secured layer to the Map. It is required to edit the code-behind and specify your https:// Url for the secured ArcGISDynamicMapServiceLayer.
NOTE: It is assumed that your organization already has an ArcGIS Server set up using PKI security protocols. Additionally, a crediential certificate has been set up for the user login that will be testing this example code.
The XAML code in this example is used in conjunction with the code-behind (C# or VB.NET) to demonstrate the functionality.
The following screen shot corresponds to the code example in this page.
XAML | Copy Code |
---|---|
<Grid> <!-- Add a Map control. --> <esri:Map x:Name="MyMap" Margin="0,124,0,0"/> <!-- Add a Button to choose certificate. --> <Label Content="Step1:" Height="28" HorizontalAlignment="Left" Name="Label1" VerticalAlignment="Top" Margin="0,81,0,0" /> <Button Content="Load Certificate" Height="23" HorizontalAlignment="Right" Margin="0,84,320,0" Name="Button_LoadCertificate" VerticalAlignment="Top" Width="134" Click="Button_LoadCertificate_Click"/> <!-- Add a Button to add an ArcGISDynamicMapServiceLayer. The button is disabled by default until a certificate is chosen. --> <Label Content="Step2:" Height="28" HorizontalAlignment="Left" Margin="0,110,0,0" Name="Label2" VerticalAlignment="Top" /> <Button Content="Add Secured ArcGISDynamicMapServiceLayer" Height="23" HorizontalAlignment="Left" Margin="49,110,0,0" Name="Button_Add_Secured_ArcGISDynamicMapServiceLayer" VerticalAlignment="Top" Width="297" Click="Button_Add_Secured_ArcGISDynamicMapServiceLayer_Click"/> <!-- Provide the instructions on how to use the sample code. --> <TextBlock Height="75" HorizontalAlignment="Left" Name="TextBlock1" VerticalAlignment="Top" Width="503" TextWrapping="Wrap" Text="Click the 'Load Certificate' button to choose a Public Key Infrasturcture (PKI) certificate from the dialog. Then click the 'Add Secured ArcGISDynamicMapServiceLayer' button to add a secured layer to the Map. It is required to edit the code-behind and specify your https:// Url for the secured ArcGISDynamicMapServiceLayer." /> </Grid> |
C# | Copy Code |
---|---|
private void MainWindow_Loaded(object sender, System.Windows.RoutedEventArgs e) { // Do not enable the ability to load the secured layer until after the certificate is obtained. Button_Add_Secured_ArcGISDynamicMapServiceLayer.IsEnabled = false; } // Global (i.e. Member) variable for the certificate. public System.Security.Cryptography.X509Certificates.X509Certificate _TheClientCertificate = new System.Security.Cryptography.X509Certificates.X509Certificate(); private void Button_LoadCertificate_Click(object sender, System.Windows.RoutedEventArgs e) { // Create a new instance of a X509Store object (which is a physical store where certificates are persisted and managed). // The X509Store object uses a StoreName based upon a 'personal certificate' and a StoreLocation for the user that // is currently logged in. The X509Store is accessed as ReadOnly to obtain the certificate. // NOTE: Don't forget to add a Reference to the System.Security Assembly. System.Security.Cryptography.X509Certificates.X509Store theX509Store = null; System.Security.Cryptography.X509Certificates.StoreName theStoreName = System.Security.Cryptography.X509Certificates.StoreName.My; System.Security.Cryptography.X509Certificates.StoreLocation theStoreLocation = System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser; theX509Store = new System.Security.Cryptography.X509Certificates.X509Store(theStoreName, theStoreLocation); theX509Store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.ReadOnly); // Obtain the collection of certificates in the X509Store. Note: depending on your organization there may multiple certificates! System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates = theX509Store.Certificates; // Display a dialog that prompts the user to select the correct certificate from the list of certificates available in the X509Store. // If the correct certificate is chosen and the user clicks the button to load the secured ArcGISDynamicMapServiceLayer it should // display in the Map control. If a wrong certificate is chosen and then user then clicks the button to load the secured // ArcGISDynamicMapServiceLayer, the InitializationFailed event will fire and display an error message with text similar to: // "Error initializing layer: The remote server returned an error: (403) Forbidden." // or: // "Error Initializing layer: The remote server returned and error: (401) Unauthorized." string theTitle = "Select a certificate"; string theMessage = "Select the certificate to use for authentication to access the secured ArcGISSynamicMapServiceLayer."; System.Security.Cryptography.X509Certificates.X509SelectionFlag theSelectionFlag = System.Security.Cryptography.X509Certificates.X509SelectionFlag.SingleSelection; certificates = System.Security.Cryptography.X509Certificates.X509Certificate2UI.SelectFromCollection(certificates, theTitle, theMessage, theSelectionFlag); // Only continue if at least one certificate is chosen. if (certificates.Count > 0) { // Set the X509Certificate global variable. This will be used in constructing the ArcGISDynamicMapServiceLayer. _TheClientCertificate = certificates[0]; // Enable the ability for the user to draw the secured ArcGISDynamicMapServiceLayer. Button_Add_Secured_ArcGISDynamicMapServiceLayer.IsEnabled = true; } } private void Button_Add_Secured_ArcGISDynamicMapServiceLayer_Click(object sender, System.Windows.RoutedEventArgs e) { // Create a new instance of an ArcGISDynamicMapServiceLayer. ESRI.ArcGIS.Client.ArcGISDynamicMapServiceLayer theArcGISDynamicMapServiceLayer = new ESRI.ArcGIS.Client.ArcGISDynamicMapServiceLayer(); // Set its ID value. That way you can access it by name in other parts of the application if desired. theArcGISDynamicMapServiceLayer.ID = "MyArcGISDynamicMapServiceLayer"; // TODO: Provide the URL to the ArcGISDynamicMapSerciceLayer. Typically the URL will begin with https:// (denoting a // secured service) rather than http:// (which usually denotes a public service). theArcGISDynamicMapServiceLayer.Url = "https://www.yoursite.com/arcgis/rest/services/test/us_counties/MapServer"; // Set the ArcGISDynamicMapServiceLayer.ClientCertficate property to the X509Certificate global variable that was chosen by the user. theArcGISDynamicMapServiceLayer.ClientCertificate = _TheClientCertificate; // Wire up an event handler for the ArcGISDynamicMapServiceLayer.InitializationFailed event in case there is a problem loading // the layer. theArcGISDynamicMapServiceLayer.InitializationFailed += ArcGISDynamicMapServiceLayer_InitializationFailed; // Add the secured ArcGISDynamicMapServiceLayer to the Map. MyMap.Layers.Add(theArcGISDynamicMapServiceLayer); } private void ArcGISDynamicMapServiceLayer_InitializationFailed(object sender, EventArgs e) { // Display a MessageBox with Error information if there is a problem loading the ArcGISDynamicMapServiceLayer. ESRI.ArcGIS.Client.Layer theLayer = (ESRI.ArcGIS.Client.Layer)sender; MessageBox.Show("Error initializing layer: " + theLayer.InitializationFailure.Message); } |
VB.NET | Copy Code |
---|---|
Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded ' Do not enable the ability to load the secured layer until after the certificate is obtained. Button_Add_Secured_ArcGISDynamicMapServiceLayer.IsEnabled = False End Sub ' Global (i.e. Member) variable for the certificate. Public _TheClientCertificate As New System.Security.Cryptography.X509Certificates.X509Certificate Private Sub Button_LoadCertificate_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button_LoadCertificate.Click ' Create a new instance of a X509Store object (which is a physical store where certificates are persisted and managed). ' The X509Store object uses a StoreName based upon a 'personal certificate' and a StoreLocation for the user that ' is currently logged in. The X509Store is accessed as ReadOnly to obtain the certificate. ' NOTE: Don't forget to add a Reference to the System.Security Assembly. Dim theX509Store As Security.Cryptography.X509Certificates.X509Store Dim theStoreName As Security.Cryptography.X509Certificates.StoreName = Security.Cryptography.X509Certificates.StoreName.My Dim theStoreLocation As Security.Cryptography.X509Certificates.StoreLocation = Security.Cryptography.X509Certificates.StoreLocation.CurrentUser theX509Store = New Security.Cryptography.X509Certificates.X509Store(theStoreName, theStoreLocation) theX509Store.Open(Security.Cryptography.X509Certificates.OpenFlags.ReadOnly) ' Obtain the collection of certificates in the X509Store. Note: depending on your organization there may multiple certificates! Dim certificates As Security.Cryptography.X509Certificates.X509Certificate2Collection = theX509Store.Certificates ' Display a dialog that prompts the user to select the correct certificate from the list of certificates available in the X509Store. ' If the correct certificate is chosen and the user clicks the button to load the secured ArcGISDynamicMapServiceLayer it should ' display in the Map control. If a wrong certificate is chosen and then user then clicks the button to load the secured ' ArcGISTiledMapServiceLayer, the InitializationFailed event will fire and display an error message with text similar to: ' "Error initializing layer: The remote server returned an error: (403) Forbidden." ' or: ' "Error Initializing layer: The remote server returned and error: (401) Unauthorized." Dim theTitle As String = "Select a certificate" Dim theMessage As String = "Select the certificate to use for authentication to access the secured ArcGISSynamicMapServiceLayer." Dim theSelectionFlag As Security.Cryptography.X509Certificates.X509SelectionFlag = Security.Cryptography.X509Certificates.X509SelectionFlag.SingleSelection certificates = Security.Cryptography.X509Certificates.X509Certificate2UI.SelectFromCollection(certificates, theTitle, theMessage, theSelectionFlag) ' Only continue if at least one certificate is chosen. If certificates.Count > 0 Then ' Set the X509Certificate global variable. This will be used in constructing the ArcGISDynamicMapServiceLayer. _TheClientCertificate = certificates(0) ' Enable the ability for the user to draw the secured ArcGISDynamicMapServiceLayer. Button_Add_Secured_ArcGISDynamicMapServiceLayer.IsEnabled = True End If End Sub Private Sub Button_Add_Secured_ArcGISDynamicMapServiceLayer_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button_Add_Secured_ArcGISDynamicMapServiceLayer.Click ' Create a new instance of an ArcGISDynamicMapServiceLayer. Dim theArcGISDynamicMapServiceLayer As New ESRI.ArcGIS.Client.ArcGISDynamicMapServiceLayer ' Set its ID value. That way you can access it by name in other parts of the application if desired. theArcGISDynamicMapServiceLayer.ID = "MyArcGISDynamicMapServiceLayer" ' TODO: Provide the URL to the ArcGISDynamicMapSerciceLayer. Typically the URL will begin with https:// (denoting a ' secured service) rather than http:// (which usually denotes a public service). theArcGISDynamicMapServiceLayer.Url = "https://www.yoursite.com/arcgis/rest/services/test/us_counties/MapServer" ' Set the ArcGISDynamicMapServiceLayer.ClientCertficate property to the X509Certificate global variable that was chosen by the user. theArcGISDynamicMapServiceLayer.ClientCertificate = _TheClientCertificate ' Wire up an event handler for the ArcGISDynamicMapServiceLayer.InitializationFailed event in case there is a problem loading ' the layer. AddHandler theArcGISDynamicMapServiceLayer.InitializationFailed, AddressOf ArcGISDynamicMapServiceLayer_InitializationFailed ' Add the secured ArcGISDynamicMapServiceLayer to the Map. MyMap.Layers.Add(theArcGISDynamicMapServiceLayer) End Sub Private Sub ArcGISDynamicMapServiceLayer_InitializationFailed(sender As Object, e As EventArgs) ' Display a MessageBox with Error information if there is a problem loading the ArcGISDynamicMapServiceLayer. Dim theLayer As ESRI.ArcGIS.Client.Layer = CType(sender, ESRI.ArcGIS.Client.Layer) MessageBox.Show("Error initializing layer: " + theLayer.InitializationFailure.Message) End Sub |
Target Platforms: Windows XP Professional, Windows Server 2003 family, Windows Vista, Windows Server 2008 family, Windows 7, Windows 8