View in WPF WinUI MAUI UWP View on GitHub
Sample viewer app
This sample demonstrates how to prompt the user for a username and password to authenticate with ArcGIS Server to access an ArcGIS token-secured service. Accessing secured services requires a login that's been defined on the server.
Use case
Your app may need to access services that are restricted to authorized users. For example, your organization may host ArcGIS services that are only accessible by verified users.
How to use the sample
When you run the sample, the app will load a map that contains a layer from a secured service. Then, you will be challenged for a user name and password to view that layer. Enter the correct user name (user1) and password (user1). If you authenticate successfully, the secured layer will display, otherwise the map will contain only the public layers.
How it works
A custom ChallengeHandler
is set for AuthenticationManager
that displays a login dialog for entering a username and password.
In response to the attempt to access secured content, the AuthenticationManager
calls the challenge handler.
A TokenCredential
is created from the entered username and password, and an attempt is made to load the layer.
Relevant API
AuthenticationManager
TokenCredential
Please note: the username and password are case sensitive for token-based authentication. If the user doesn't have permission to access all the content within the portal item, partial or no content will be returned.
authentication, cloud, portal, remember, security
Sample CodeTokenSecuredChallenge.xaml TokenSecuredChallenge.xaml TokenSecuredChallenge.xaml.cs
Use dark colors for code blocks Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
< UserControl x:Class = "ArcGIS.WPF.Samples.TokenSecuredChallenge.TokenSecuredChallenge"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:esri = "http://schemas.esri.com/arcgis/runtime/2013"
xmlns:mapping = "clr-namespace:Esri.ArcGISRuntime.Mapping;assembly=Esri.ArcGISRuntime" >
< Grid x:Name = "layoutGrid" >
< esri:MapView x:Name = "MyMapView" >
< mapping:Map >
< mapping:Map.OperationalLayers >
<!-- This layer is public and does not require credentials -->
< mapping:ArcGISTiledLayer Name = "World Street Map - Public" Source = "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
<!-- This layer is secured with ArcGIS tokens and requires a login -->
<!-- username: user1 | password: user1 -->
< mapping:ArcGISMapImageLayer Name = "USA - Secure" Source = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA_secure_user1/MapServer" />
</ mapping:Map.OperationalLayers >
</ mapping:Map >
</ esri:MapView >
<!-- Layer listing with status -->
< Border Style = "{StaticResource BorderStyle}" >
< StackPanel >
< TextBlock Margin = "4"
FontSize = "14"
FontWeight = "Bold"
Text = "Map layers (with status)" />
< ListView x:Name = "listLayerStatus"
Padding = "6"
ItemsSource = "{Binding ElementName=MyMapView, Path=Map.AllLayers}" >
< ListView.ItemTemplate >
< DataTemplate >
< StackPanel >
< TextBlock HorizontalAlignment = "Left" Text = "{Binding Name}" />
< StackPanel Orientation = "Horizontal" >
< TextBlock Margin = "20,0,0,5" FontWeight = "Bold" >
< TextBlock.Style >
< Style TargetType = "{x:Type TextBlock}" >
< Style.Triggers >
< DataTrigger Binding = "{Binding LoadStatus}" Value = "2" >
< Setter Property = "Foreground" Value = "Red" />
< Setter Property = "Text" Value = "Access Denied" />
</ DataTrigger >
< DataTrigger Binding = "{Binding LoadStatus}" Value = "0" >
< Setter Property = "Foreground" Value = "Green" />
< Setter Property = "Text" Value = "Access Granted" />
</ DataTrigger >
</ Style.Triggers >
< Style.Setters >
< Setter Property = "Foreground" Value = "Black" />
< Setter Property = "Text" Value = "Initializing" />
</ Style.Setters >
</ Style >
</ TextBlock.Style >
</ TextBlock >
</ StackPanel >
</ StackPanel >
</ DataTemplate >
</ ListView.ItemTemplate >
</ ListView >
</ StackPanel >
</ Border >
<!-- Login UI -->
< Border x:Name = "loginPanel"
HorizontalAlignment = "Left"
Style = "{StaticResource BorderStyle}"
Visibility = "Collapsed" >
< Grid >
< Grid.ColumnDefinitions >
< ColumnDefinition Width = "Auto" />
< ColumnDefinition Width = "*" />
</ Grid.ColumnDefinitions >
< Grid.RowDefinitions >
< RowDefinition Height = "*" />
< RowDefinition Height = "Auto" />
< RowDefinition Height = "Auto" />
< RowDefinition Height = "Auto" />
< RowDefinition Height = "Auto" />
< RowDefinition Height = "*" />
</ Grid.RowDefinitions >
< TextBlock Grid.Row = "0"
Grid.Column = "0"
Grid.ColumnSpan = "2"
Margin = "0,0,0,8"
Text = "{Binding ServiceUrl, StringFormat='Login to: {0}'}"
TextWrapping = "Wrap" />
< TextBlock Grid.Row = "1"
Grid.Column = "0"
Grid.ColumnSpan = "2"
Margin = "0,0,0,8"
FontWeight = "SemiBold"
Text = "Username and password are user1/user1"
TextWrapping = "Wrap" />
< TextBlock Grid.Row = "2"
Grid.Column = "0"
Margin = "2"
VerticalAlignment = "Center"
Text = "Username" />
< TextBox Grid.Row = "2"
Grid.Column = "1"
Margin = "2"
Text = "{Binding UserName, UpdateSourceTrigger=PropertyChanged}" />
< TextBlock Grid.Row = "3"
Grid.Column = "0"
Margin = "2"
VerticalAlignment = "Center"
Text = "Password" />
<!--
For simplicity, the password is visible in this example. You can use a PasswordBox to mask the password text,
but it complicates data binding. See this discussion for details: http://stackoverflow.com/questions/1483892/how-to-bind-to-a-passwordbox-in-mvvm
-->
< TextBox Grid.Row = "3"
Grid.Column = "1"
Margin = "2"
Text = "{Binding Password, UpdateSourceTrigger=PropertyChanged}" />
< Button Grid.Row = "4"
Grid.Column = "0"
Grid.ColumnSpan = "2"
Margin = "0,12,0,0"
Padding = "5,2.5,5,2.5"
HorizontalAlignment = "Center"
Click = "LoginButtonClick"
Content = "Login and load layer"
IsDefault = "True" />
< TextBlock Grid.Row = "5"
Grid.Column = "0"
Grid.ColumnSpan = "2"
Margin = "8,12,8,0"
Foreground = "Red"
Text = "{Binding ErrorMessage}"
TextWrapping = "Wrap" >
< TextBlock.Style >
< Style TargetType = "{x:Type TextBlock}" >
< Style.Triggers >
< DataTrigger Binding = "{Binding ErrorMessage}" Value = "" >
< Setter Property = "Visibility" Value = "Collapsed" />
</ DataTrigger >
</ Style.Triggers >
</ Style >
</ TextBlock.Style >
</ TextBlock >
</ Grid >
</ Border >
</ Grid >
</ UserControl >