{"id":2412,"date":"2013-09-16T07:32:51","date_gmt":"2013-09-16T14:32:51","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=2412"},"modified":"2013-09-16T07:33:40","modified_gmt":"2013-09-16T14:33:40","slug":"getting-acquainted-with-authenticationresult","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2013\/09\/16\/getting-acquainted-with-authenticationresult\/","title":{"rendered":"Getting Acquainted with AuthenticationResult"},"content":{"rendered":"<p>Now that the cat\u2019s out of the bag, we can finally play with it <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/09\/wlEmoticon-smile2.png\" \/> time &amp; energy permitting, in the next days (weeks?) I\u2019ll be covering some aspects of using ADAL .NET to help you to get the most from AD in your applications.<\/p>\n<p>In the announcement post I introduced AcquireToken, the key primitive exposed by ADAL for obtaining access tokens to be used with the protected resources you want to access. Today I\u2019ll go a bit deeper on how to use the results of that operation.<\/p>\n<p>Let\u2019s consider a common case, in which you have a desktop app accessing a Web API protected by Windows Azure AD, associated to the domain CloudIdentity.net (could have been just as well whatever.onmicrosoft.com, I just like to use the other one because it\u2019s shorter). The client is regularly registered in the tenant, hence we have its ID; same for the Web API, for which we have the resource ID.<\/p>\n<p>Here there\u2019s the code you\u2019d write for acquiring the token:<\/p>\n<pre class=\"csharpcode\">AuthenticationContext ac = \r\n    <span class=\"kwrd\">new<\/span> AuthenticationContext(<span class=\"str\">\"https:\/\/login.windows.net\/cloudidentity.net\"<\/span>);\r\nAuthenticationResult ar = \r\n    ac.AcquireToken(<span class=\"str\">\"https:\/\/cloudidentity.net\/WindowsAzureADWebAPITest\"<\/span>,\r\n                    <span class=\"str\">\"a4836f83-0f69-48ed-aa2b-88d0aed69652\"<\/span>,\r\n                    <span class=\"kwrd\">new<\/span> Uri(<span class=\"str\">\"https:\/\/cloudidentity.net\/myWebAPItestclient\"<\/span>));<\/pre>\n<style type=\"text\/css\"><!--\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }\n--><\/style>\n<p>The first couple of lines initialize the instance of AuthenticationContext which we can use for interacting with the associated AD instance.<\/p>\n<p>The next line asks to the Windows Azure AD tenant for a token scoped for the resource <a href=\"https:\/\/cloudidentity.net\/WindowsAzureADWebAPITest\">https:\/\/cloudidentity.net\/WindowsAzureADWebAPITest<\/a>, advertises that the request is coming from the client a4836f83-0f69-48ed-aa2b-88d0aed69652, and indicates <a href=\"https:\/\/cloudidentity.net\/myWebAPItestclient\">https:\/\/cloudidentity.net\/myWebAPItestclient<\/a> as reply url (technicalities of the OAuth2 code grant; let\u2019s just say that ehre you have to pass the same value that is stored in the client registration in Windows Azure AD).<\/p>\n<p>If that\u2019s the first time that you call AcquireToken with those parameters, ADAL will take care of popping out a dialog containing a browser, which will in turn present the user with whatever authentication experience Windows Azure AD decides to use in this case.<\/p>\n<p>If the user successfully authenticates, AcquireToken returns to you a nice AuthenticationResult instance. There you will find the access token (in the AccessToken property) you need to call the web API, and let me be clear: if performing the call as is is all you want to do, you don\u2019t need to know anything else.<br \/>\nThat said, you\u2019ll discover that there\u2019s way more stuff in AuthenticationResult: if you know what it\u2019s for, you can use the extra info for interesting tweaks. Let\u2019s take a look!<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/09\/image11.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" alt=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/09\/image_thumb11.png\" width=\"565\" height=\"189\" border=\"0\" \/><\/a><\/p>\n<p>Here there\u2019s a view courtesy of the VS2013 debugger. Let me give you a brief description for all of those properties:<\/p>\n<p><strong>AccessToken &#8211; <\/strong>Those are the bits of the access token themselves. In most cases it will be a JWT, but you\u2019re not supposed to know that! <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/09\/wlEmoticon-smile2.png\" \/> Or, to clarify: the token is meant for the resource, and for the client the token itself is supposed to be an opaque blob to be used but not inspected. Should you peek in it and take a dependency on any of its aspects in the client code, you\u2019d end up with extremely brittle software: the characteristics of the token are the result of a negotiation between the resource and its issuer, which can change things at any time without having to inform the client. You\u2019ve been warned <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-winkingsmile\" alt=\"Winking smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/09\/wlEmoticon-winkingsmile.png\" \/><\/p>\n<p><strong>AccessTokenType <\/strong>\u2013 givens indications on the intended usage. More details are beyond the scope of this post, but not not leaving completely dry: in this case \u201cbearer\u201d indicates that this token should be simply attached to requests.<\/p>\n<p><strong>ExpiresOn <\/strong>\u2013 this is the expiration of the access token. If you repeat the AccessToken call with the exact same parameters before the expiration occurs, you are going to get the exact same token as cached by ADAL. If you repeat the call after the expiration, if there is an associated refresh token (see below) and it is not expired itself ADAL is going to automatically (and silently, no UI) use it to get a new access token and return it to you. Bottom line; in general <em>always<\/em> use AcquireToken instead of storing the access token in your own code!<br \/>\nNote: ADAL does not offer any clock skew functionality. That expiration value is final. If there is clock skew between the issuer and the resource, you might need to do something to get things renewed sooner. More detials in a future post.<\/p>\n<p><strong>IsMultipleResourceRefreshToken \u2013 <\/strong>this flag indicates whether the refresh token (if present in the AuthenticationResult, it won\u2019t always be the case) is one of those magic refresh tokens that can be used for silently obtaining an access token even for resources that are different from the one for which the refresh token\/access token couple was obtained in the first place. Of all the flavors of AD ADAL can talk to, this can only happen with Windows Azure AD. This is another candidate for its own blog post.<\/p>\n<p><strong>RefreshToken<\/strong> \u2013 This contains the bits of the refresh token. It won\u2019t always be present: ACS never issues it, ADFS will do so only in special cases and even Windows Azure AD will do so only when the underlying OAuth flow is right (e.g. code grant).<br \/>\n<strong><span style=\"text-decoration: underline;\">Important<\/span><\/strong>: <strong><\/strong><strong><span>in the general case, you don\u2019t need to use this field at all<\/span><\/strong><strong><\/strong>. ADAL caches the refresh token and uses it transparently, taking full advantage of all of its capabilities, every single time you call AcquireToken. We return the refresh token because there are some cases where you might want to have full control about some other aspects, but those are only advanced scenarios that should be fairly rare.<\/p>\n<p><strong>TenantId <\/strong>\u2013 this is the identifier of the tenant that was used for authenticating the user. You might not have known that information in advance, given that you can create a generic AuthenticationContext tied to the Common endpoint: in that case, the true tenant is established only when the end user enters his\/her credentials which by necessity must belong to a specific tenant. This value makes a lot of sense for Windows Azure AD, but less for other AD flavors.<\/p>\n<p><strong>UserInfo<\/strong> \u2013 This is a bit of a \u201ccontamination\u201d from OpenId Connect. I won\u2019t go in any details, I\u2019ll just say that when ADAL triggers a user authentication with Windows Azure AD, as in the case described here, besides the expected bits (access token, refresh token\u2026) you also get back an Id_token describing the user. Some info might be useful to you as generic properties (FirstName, LastName). Other properties can instead play an important role in the mechanics of how you handle authentication and manage state. More details below.<\/p>\n<p>One property of UserInfo, <strong>UserId<\/strong>, deserves to be explored in more details. In the Windows Azure AD case, UserId will contain the UPN of the user who authenticated to obtain the tokens back. There are variations I don\u2019t want to talk about yet, but they\u2019ll work like in the UPN case hence for our explanation that makes no difference. Now, although this is a less-than-perfect identifier (it can be reassigned) it is still a pretty good moniker for tying the obtained tokens to the user they are associated to. As such, it is used as one of the component of the cache key under which ADAL stores the current result. And as such, this can play a role to gain more control in subsequent calls to AcquireToken. Let\u2019s make an example.<\/p>\n<p>Suppose that your client application is designed to allow the user to use multiple accounts at once. A classic example would be the People app in Windows 8, where you can <em>connect <\/em>multiple accounts from different providers. Say that you want to make sure that you will perform a certain API call using a specific user, for example the same one that was used in the earlier call. You have a reference to that user, the string you found in UserInfo.UserId from the AuthenticationResult of the first call: all you need to do is specifying it as a parameter in AcquireToken.<\/p>\n<pre class=\"csharpcode\">AuthenticationResult ar =\r\n     ac.AcquireToken(<span class=\"str\">\"https:\/\/cloudidentity.net\/AnotherResource\"<\/span>, \r\n                                 <span class=\"str\">\"a4836f83-0f69-48ed-aa2b-88d0aed69652\"<\/span>, \r\n                                 <span class=\"kwrd\">new<\/span> Uri(<span class=\"str\">\"https:\/\/cloudidentity.net\/whatevs\"<\/span>),\r\n                                 <span class=\"str\">\"vibro@cloudidentity.net\"<\/span>);<\/pre>\n<style type=\"text\/css\"><!--\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }\n--><\/style>\n<p>Adding the UserId as parameter will have the following effect:<\/p>\n<ul>\n<li>ADAL will search the cache for an entry that not only satisfies the resource and clientid constraint, but also\u00a0 that it was obtained with the same userid<\/li>\n<li>If the cache does not contain a suitable entry, ADAL will pop out the browser dialog with the user textbox pre-populated with the indicated userid<\/li>\n<\/ul>\n<p>That\u2019s pretty neat, as it gives you the necessary control for handling tokens in multi-users scenarios that can notoriously get very complicated. I\u2019ll get back to this in the post where I\u2019ll discuss the cache model. So much to write!<\/p>\n<p>Now, technically there\u2019s nothing preventing your application from gathering the UPN of the intended user and feeding it directly in AcquireToken: that can work, but there are limitations:<\/p>\n<ul>\n<li>the username textbox will be pre-populated with the right values, but the end user can always delete its content and type another username. ADAL will always use what\u2019s returned in the UserInfo.UserId as cache key, hence you can catch this situation with a simple check on the AuthenticationResult<\/li>\n<li>different flavors of AD work differently<\/li>\n<\/ul>\n<p>Neither ADFS or ACS will return id_tokens, hence the UserInfo properties will not carry values when you work with those authority types. Well, mostly. We did do some extra steps for giving you at least <em>some <\/em>info.<\/p>\n<p>For results from those authorities ADAL itself generates an identifier and stores it in the UserId field. That won\u2019t tell you an <em>absolute<\/em> identifier for the user, but it does offer you a mechanism for enforcing that subsequent calls to AcquireToken can search the cache for the <em>same<\/em> user that came into play here. I know, it\u2019s complicated: let me make you an example. Say that you call AcquireToken against ADFS, and you get back the usual tokens and a UserId value of 1234567. Now, from that userid value you cannot know that the user is in fact <a href=\"mailto:mario@contoso.com\">mario@contoso.com<\/a>; but by using that userid value later on you can enforce that the token you are getting from the cache is associated to the same user that authenticated earlier, even if you are not certain about the actual identity of the user. It\u2019s a bit like when you leave your jacket a the coat check. They give you a ticket with a number, and as long as you show up later with the same number you get your jacket back: at no point in that transaction your name need to come up.<br \/>\nIf that\u2019s not crystal clear don\u2019t worry too much, I\u2019ll be getting back on this multiple times in the next posts.<\/p>\n<p>That\u2019s pretty much it! However, before closing I just want to make sure I stress that for the basic case you don\u2019t need to know anything, and I mean anything at all, about the structure of AuthenticationResult. There is a little utility method which crafts a header for your web API flow, and that\u2019s all you need to know to be able to call your OAuth-protected API. Just make sure you always call AcquireToken so that ADAL has the chance of handling token lifecycle &amp; refreshing for you, and that\u2019s all you need! Code below:<\/p>\n<pre class=\"csharpcode\"> <span class=\"kwrd\">string<\/span> authHeader = ar.CreateAuthorizationHeader();\r\n HttpClient client = <span class=\"kwrd\">new<\/span> HttpClient();\r\n HttpRequestMessage request = \r\n     <span class=\"kwrd\">new<\/span> HttpRequestMessage(HttpMethod.Get, <span class=\"str\">\"https:\/\/localhost:44353\/api\/Values\"<\/span>);\r\n request.Headers.TryAddWithoutValidation(<span class=\"str\">\"Authorization\"<\/span>, authHeader);\r\n HttpResponseMessage response = await client.SendAsync(request);\r\n <span class=\"kwrd\">string<\/span> responseString = await response.Content.ReadAsStringAsync();\r\n MessageBox.Show(responseString);<\/pre>\n<style type=\"text\/css\"><!--\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }\n--><\/style>\n<p>&nbsp;<\/p>\n<p>All so standard that I\u2019ll deem it self-explanatory and call it a post.<\/p>\n<p>Next, I\u2019ll be talking about cache. Stay tuned! <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-winkingsmile\" alt=\"Winking smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/09\/wlEmoticon-winkingsmile.png\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Now that the cat\u2019s out of the bag, we can finally play with it time &amp; energy permitting, in the next days (weeks?) I\u2019ll be covering some aspects of using ADAL .NET to help you to get the most from AD in your applications. In the announcement post I introduced AcquireToken, the key&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2410,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2412","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2412","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/comments?post=2412"}],"version-history":[{"count":2,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2412\/revisions"}],"predecessor-version":[{"id":2414,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2412\/revisions\/2414"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/2410"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=2412"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=2412"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=2412"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}