@@ -46,12 +46,12 @@ namespace TodoListClient
4646 /// </summary>
4747 public partial class MainWindow : Window
4848 {
49- //
49+
5050 // The Client ID is used by the application to uniquely identify itself to the v2.0 endpoint
5151 // The AAD Instance is the instance of the v2.0 endpoint
5252 // The Redirect URI is the URI where the v2.0 endpoint will return OAuth responses.
5353 // The Authority is the sign-in URL.
54- //
54+
5555 private static string aadInstance = ConfigurationManager . AppSettings [ "ida:AADInstance" ] ;
5656 private static string clientId = ConfigurationManager . AppSettings [ "ida:ClientId" ] ;
5757 Uri redirectUri = new Uri ( ConfigurationManager . AppSettings [ "ida:RedirectUri" ] ) ;
@@ -65,29 +65,36 @@ protected override async void OnInitialized(EventArgs e)
6565 {
6666 base . OnInitialized ( e ) ;
6767
68- //
69- // As the application starts, try to get an access token without prompting the user. If one exists, populate the To Do list. If not, continue.
70- //
7168 authContext = new AuthenticationContext ( authority , new FileCache ( ) ) ;
7269 AuthenticationResult result = null ;
7370
71+ // As the app starts, we want to check to see if the user is already signed in.
72+ // You can do so by trying to get a token from ADAL, passing in the parameter
73+ // PromptBehavior.Never. This forces ADAL to throw an exception if it cannot
74+ // get a token for the user without showing a UI.
75+
7476 try
7577 {
7678 result = await authContext . AcquireTokenAsync ( new string [ ] { clientId } , null , clientId , redirectUri , new PlatformParameters ( PromptBehavior . Never , null ) ) ;
7779
78- // A valid token is in the cache - get the To Do list.
80+ // If we got here, a valid token is in the cache. Proceed to
81+ // fetch the user's tasks from the TodoListService via the
82+ // GetTodoList() method.
83+
7984 SignInButton . Content = "Clear Cache" ;
8085 GetTodoList ( ) ;
8186 }
8287 catch ( AdalException ex )
8388 {
8489 if ( ex . ErrorCode == "user_interaction_required" )
8590 {
86- // There are no tokens in the cache. Proceed without calling the To Do list service.
91+ // If user interaction is required, the app should take no action,
92+ // and simply show the user the sign in button.
8793 }
8894 else
8995 {
90- // An unexpected error occurred.
96+ // Here, we catch all other AdalExceptions
97+
9198 string message = ex . Message ;
9299 if ( ex . InnerException != null )
93100 {
@@ -106,25 +113,29 @@ public MainWindow()
106113
107114 private async void GetTodoList ( )
108115 {
109- //
110- // Get an access token to call the To Do service.
111- //
112116 AuthenticationResult result = null ;
113117 try
114118 {
119+ // Here, we try to get an access token to call the TodoListService
120+ // without invoking any UI prompt. PromptBehavior.Never forces
121+ // ADAL to throw an exception if it cannot get a token silently.
122+
115123 result = await authContext . AcquireTokenAsync ( new string [ ] { clientId } , null , clientId , redirectUri , new PlatformParameters ( PromptBehavior . Never , null ) ) ;
116124 }
117125 catch ( AdalException ex )
118126 {
119- // There is no access token in the cache, so prompt the user to sign-in.
127+ // ADAL couldn't get a token silently, so show the user a message
128+ // and let them click the Sign-In button.
129+
120130 if ( ex . ErrorCode == "user_interaction_required" )
121131 {
122132 MessageBox . Show ( "Please sign in first" ) ;
123133 SignInButton . Content = "Sign In" ;
124134 }
125135 else
126136 {
127- // An unexpected error occurred.
137+ // In any other case, an unexpected error occurred.
138+
128139 string message = ex . Message ;
129140 if ( ex . InnerException != null )
130141 {
@@ -136,20 +147,21 @@ private async void GetTodoList()
136147 return ;
137148 }
138149
139- // Once the token has been returned by ADAL, add it to the http authorization header, before making the call to access the To Do list service.
150+ // Once the token has been returned by ADAL,
151+ // add it to the http authorization header,
152+ // before making the call to access the To Do list service.
153+
140154 httpClient . DefaultRequestHeaders . Authorization = new AuthenticationHeaderValue ( "Bearer" , result . Token ) ;
141155
156+
142157 // Call the To Do list service.
143158 HttpResponseMessage response = await httpClient . GetAsync ( todoListBaseAddress + "/api/todolist" ) ;
144159
145160 if ( response . IsSuccessStatusCode )
146161 {
147-
148- // Read the response and databind to the GridView to display To Do items.
149162 string s = await response . Content . ReadAsStringAsync ( ) ;
150163 JavaScriptSerializer serializer = new JavaScriptSerializer ( ) ;
151164 List < TodoItem > toDoArray = serializer . Deserialize < List < TodoItem > > ( s ) ;
152-
153165 TodoList . ItemsSource = toDoArray . Select ( t => new { t . Title } ) ;
154166 }
155167 else
@@ -162,31 +174,28 @@ private async void GetTodoList()
162174
163175 private async void AddTodoItem ( object sender , RoutedEventArgs e )
164176 {
177+ // This method follows the same pattern as GetTodoList()
178+
165179 if ( string . IsNullOrEmpty ( TodoText . Text ) )
166180 {
167181 MessageBox . Show ( "Please enter a value for the To Do item name" ) ;
168182 return ;
169183 }
170184
171- //
172- // Get an access token to call the To Do service.
173- //
174185 AuthenticationResult result = null ;
175186 try
176187 {
177188 result = await authContext . AcquireTokenAsync ( new string [ ] { clientId } , null , clientId , redirectUri , new PlatformParameters ( PromptBehavior . Never , null ) ) ;
178189 }
179190 catch ( AdalException ex )
180191 {
181- // There is no access token in the cache, so prompt the user to sign-in.
182192 if ( ex . ErrorCode == "user_interaction_required" )
183193 {
184194 MessageBox . Show ( "Please sign in first" ) ;
185195 SignInButton . Content = "Sign In" ;
186196 }
187197 else
188198 {
189- // An unexpected error occurred.
190199 string message = ex . Message ;
191200 if ( ex . InnerException != null )
192201 {
@@ -199,17 +208,9 @@ private async void AddTodoItem(object sender, RoutedEventArgs e)
199208 return ;
200209 }
201210
202- //
203- // Call the To Do service.
204- //
205-
206- // Once the token has been returned by ADAL, add it to the http authorization header, before making the call to access the To Do service.
207211 httpClient . DefaultRequestHeaders . Authorization = new AuthenticationHeaderValue ( "Bearer" , result . Token ) ;
208212
209- // Forms encode Todo item, to POST to the todo list web api.
210213 HttpContent content = new FormUrlEncodedContent ( new [ ] { new KeyValuePair < string , string > ( "Title" , TodoText . Text ) } ) ;
211-
212- // Call the To Do list service.
213214 HttpResponseMessage response = await httpClient . PostAsync ( todoListBaseAddress + "/api/todolist" , content ) ;
214215
215216 if ( response . IsSuccessStatusCode )
@@ -225,20 +226,25 @@ private async void AddTodoItem(object sender, RoutedEventArgs e)
225226
226227 private async void SignIn ( object sender = null , RoutedEventArgs args = null )
227228 {
228- // If there is already a token in the cache, clear the cache and update the label on the button.
229+ // If the user clicked the 'clear cache' button,
230+ // clear the ADAL token cache and show the user as signed out.
231+ // It's also necessary to clear the cookies from the browser
232+ // control so the next user has a chance to sign in.
233+
229234 if ( SignInButton . Content . ToString ( ) == "Clear Cache" )
230235 {
231236 TodoList . ItemsSource = string . Empty ;
232237 authContext . TokenCache . Clear ( ) ;
233- // Also clear cookies from the browser control.
234238 ClearCookies ( ) ;
235239 SignInButton . Content = "Sign In" ;
236240 return ;
237241 }
238242
239- //
240- // Get an access token to call the To Do list service.
241- //
243+ // If the user clicked the 'Sign-In' button, force
244+ // ADAL to prompt the user for credentials by specifying
245+ // PromptBehavior.Always. ADAL will get a token for the
246+ // TodoListService and cache it for you.
247+
242248 AuthenticationResult result = null ;
243249 try
244250 {
@@ -248,6 +254,10 @@ private async void SignIn(object sender = null, RoutedEventArgs args = null)
248254 }
249255 catch ( AdalException ex )
250256 {
257+ // If ADAL cannot get a token, it will throw an exception.
258+ // If the user canceled the login, it will result in the
259+ // error code 'authentication_canceled'.
260+
251261 if ( ex . ErrorCode == "authentication_canceled" )
252262 {
253263 MessageBox . Show ( "Sign in was canceled by the user" ) ;
0 commit comments