{"id":2466,"date":"2013-10-14T00:42:11","date_gmt":"2013-10-14T07:42:11","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=2466"},"modified":"2013-10-14T00:47:14","modified_gmt":"2013-10-14T07:47:14","slug":"adal-windows-azure-ad-and-multi-resource-refresh-tokens","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2013\/10\/14\/adal-windows-azure-ad-and-multi-resource-refresh-tokens\/","title":{"rendered":"ADAL, Windows Azure AD and Multi-Resource Refresh Tokens"},"content":{"rendered":"<p>After a ~<a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/10\/01\/getting-acquainted-with-adals-token-cache\/\" target=\"_blank\">one-week hiatus<\/a>, I am back to cover the new features you can find in <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/09\/12\/active-directory-authentication-library-adal-v1-for-net-general-availability\/\" target=\"_blank\">ADAL .NET<\/a>. <br \/>Today I am going to write about Multi-Resource Refresh Tokens. As I am not a great typist, I am going to abbreviate that in \u201cMRRT\u201d; that does not mean that it\u2019s the official acronym, what I write here is just my personal opinion and does not constitute official guidance, the usual yadda yadda yadda <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/wlEmoticon-smile2.png\"><\/p>\n<h3>What is a MRRT?<\/h3>\n<p>Simply put: <em>a MRRT is a refresh token that can be used to obtain an access token for a resource that can be different from the resource for which the MRRT was obtained in the first place<\/em>.<\/p>\n<p>Let\u2019s unpack that concept with one example. Say that I have two Web API projects, resource1 and resource2, both provisioned in the same Windows Azure AD tenant. Say that I have a native client, also provisioned in the same tenant, with the right entries in the permissions table which allow it to call both Web APIs. <\/p>\n<p>If I ask for a token for resource1, I\u2019ll go through whatever authentication flow the operation requires, for example getting prompted via browser dialog, if there\u2019s no existing session. After a successful flow I\u2019ll get back an access token AT1 and a refresh token RT1.<\/p>\n<p>Say that now I want to access resource2. If RT1 is a MRRT, I can simply use RT1 just like I\u2019d use it in the classic refresh flow, but ask for resource2 instead. That will result in getting back an access token AT2 for resource2 (and a RT2 as well) without having to prompt the end user!<\/p>\n<p><strong><em>This is exceptionally useful<\/em><\/strong>. To put things in perspective: a MRRT can play for all the resources in a tenant a role similar to the one played by a TGT in Kerberos. Prompts are reduced to their bare minimum, and you can start to think about sessions it terms that are closer to the ones we are used to on-premises, while at the same time maintaining the flexibility and boundaries-crossing capabilities that OAuth2 affords. Is your mind blown yet? <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/wlEmoticon-smile2.png\"><\/p>\n<h3>Let\u2019 See Some Code<\/h3>\n<p>This is not just some theoretical mumbo jumbo: you can experience this in your code today (though the endpoint used in the process is still in preview).<\/p>\n<p>Here there\u2019s some code that defines in ADAL terms the scenario described earlier:<\/p>\n<pre class=\"csharpcode\"> <span class=\"rem\">\/\/ the tenant<\/span>\r\n <span class=\"kwrd\">string<\/span> authority = <span class=\"str\">\"https:\/\/login.windows.net\/cloudidentity.net\"<\/span>;\r\n\r\n<span class=\"rem\">\/\/ the client coordinates<\/span>\r\n <span class=\"kwrd\">string<\/span> clientId = <span class=\"str\">\"a4836f83-0f69-48ed-aa2b-88d0aed69652\"<\/span>;\r\n <span class=\"kwrd\">string<\/span> redirectURI = <span class=\"str\">\"https:\/\/cloudidentity.net\/myWebAPItestclient\"<\/span>;\r\n\r\n<span class=\"rem\">\/\/ the IDs of the Web APIs<\/span>\r\n <span class=\"kwrd\">string<\/span> resource1 = <span class=\"str\">\"https:\/\/cloudidentity.net\/WindowsAzureADWebAPITest\"<\/span>;\r\n <span class=\"kwrd\">string<\/span> resource2 = <span class=\"str\">\"https:\/\/cloudidentity.net\/cisNAPAoidc1\"<\/span>;\r\n\r\n <span class=\"rem\">\/\/ the AuthenticationContext representing the tenant in your code<\/span>\r\n AuthenticationContext ac = <span class=\"kwrd\">new<\/span> AuthenticationContext(authority);\r\n<\/pre>\n<style type=\"text\/css\">.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>Let\u2019s use ADAL to get a token for accessing resource1:<\/p>\n<pre class=\"csharpcode\">AuthenticationResult arOriginal =\r\n    ac.AcquireToken(resource1, clientId, <span class=\"kwrd\">new<\/span> Uri(redirectURI));\r\n<\/pre>\n<style type=\"text\/css\">.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>Assuming that we started from a clean state (empty cache, no cookies for Windows Azure AD) that line of code will cause ADAL to show the browser dialog and the authentication experience. Go through it to completion.<\/p>\n<p>Since I was at it, I took a Fiddler trace to show what happens while AcquireToken runs. Let\u2019s take a look.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/image15.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; border-left: 0px; display: inline; padding-right: 0px\" border=\"0\" alt=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/image_thumb15.png\" width=\"640\" height=\"352\"><\/a><\/p>\n<p>That\u2019s quite a lot of stuff for a little line of code! <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/wlEmoticon-smile2.png\"><\/p>\n<p>All the part marked (1) is about getting to render the initial authentication experience in the browser dialog.<\/p>\n<p>The GET in (2) takes place after I type in my username and hit TAB, the page tries to establish whether it should also gather my password or if my tenant has SSO configured and I should be redirected to another endpoint (a local ADFS). My tenant is cloud-only, so I don\u2019t get redirected.<\/p>\n<p>The part in (3) finalizes the user authentication part and results in an authorization code. At this point the ADAL dialog closes down and everything else is handled directly at the HTTP request level.<\/p>\n<p>The part in (4) represents the call to the Windows Azure AD\u2019s Token endpoint, to exchange the code for an access token and associated data(refresh token, expirations, etc).<br \/>In fact, I think it\u2019s interesting to take a look at the content of the request to the Token endpoint. Here it is:<\/p>\n<p><font size=\"1\" face=\"Courier New\">POST <\/font><a href=\"https:\/\/login.windows.net\/cloudidentity.net\/oauth2\/token\"><font size=\"1\" face=\"Courier New\">https:\/\/login.windows.net\/cloudidentity.net\/oauth2\/token<\/font><\/a><font size=\"1\" face=\"Courier New\"> HTTP\/1.1<br \/>Content-Type: application\/x-www-form-urlencoded<br \/>Host: login.windows.net<br \/>Content-Length: 654<br \/>Expect: 100-continue<br \/>Connection: Keep-Alive<\/font><\/p>\n<p><font size=\"1\" face=\"Courier New\"><strong>grant_type<\/strong>=<strong>authorization_code<\/strong>&amp;<br \/>code=AwABAAA[SNIP]v-YgAA&amp;<br \/>client_id=a4836f83-0f69-48ed-aa2b-88d0aed69652&amp;<br \/>redirect_uri=https%3A%2F%2Fcloudidentity.net%2FmyWebAPItestclient&amp;<br \/><strong>resource<\/strong>=<strong>https%3A%2F%2Fcloudidentity.net%2FWindowsAzureADWebAPITest<\/strong><\/font><\/p>\n<p>I edited it a bit for readability. As you can see, that\u2019s a pretty standard code grant request. I have formatted in <font face=\"Courier New\"><strong>bold <\/strong><\/font>the parts I want you to notice: the fact that we are performing a code grant request, and the fact that we are referring to the resource URI that in our example corresponds to resource1. Those details will become relevant in a moment.<\/p>\n<p>Now let\u2019s take a look at the <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/09\/16\/getting-acquainted-with-authenticationresult\/\" target=\"_blank\">AuthenticationResult<\/a> we got back:<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/image16.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; border-left: 0px; display: inline; padding-right: 0px\" border=\"0\" alt=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/image_thumb16.png\" width=\"640\" height=\"155\"><\/a><\/p>\n<p>We have both an access token and a refresh token, which is great (does not always happen, ADFS will send refresh tokens only under special conditions and ACS never does).<br \/>Actually, our refresh token is not a normal one: it\u2019s special! As signaled by the property IsMultipleResourceRefreshToken, what we got back is a MRRT.<\/p>\n<p>The good news is that ADAL is fully aware of how MRRTs work, and can take advantage of those automatically if it has one in <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/10\/01\/getting-acquainted-with-adals-token-cache\/\" target=\"_blank\">its cache<\/a>. <br \/>To see that in action, let\u2019s append a line of code which asks for a token for resource2:<\/p>\n<pre class=\"csharpcode\"><span class=\"rem\">\/\/ ...<\/span>\r\n\r\nAuthenticationContext ac = <span class=\"kwrd\">new<\/span> AuthenticationContext(authority);\r\n\r\nAuthenticationResult arOriginal =\r\n    ac.AcquireToken(resource1, clientId, <span class=\"kwrd\">new<\/span> Uri(redirectURI));\r\n\r\n<span class=\"rem\">\/\/ get a token for resource2 right after having gotten one for resource1<\/span>\r\nAuthenticationResult arViaMultiResourceRefreshToken = \r\n    ac.AcquireToken(resource2, clientId, <span class=\"kwrd\">new<\/span> Uri(redirectURI));\r\n<\/pre>\n<style type=\"text\/css\">.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>Let\u2019s run the code again. You will notice that you get prompted on the first AcquireToken, but not on the second. But that doesn\u2019t prove anything, does it: this behavior might be caused by any number of causes, including the presence of a session cookie (not true, but until I don\u2019t write that post on session I\u2019ve promised I can\u2019t explain more <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/wlEmoticon-smile2.png\">).<br \/>To verify that this was really made possible by the use of a MRRT, let\u2019s get back to Fiddler:<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/image17.png\"><img loading=\"lazy\" decoding=\"async\" title=\"image\" style=\"border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; border-left: 0px; display: inline; padding-right: 0px\" border=\"0\" alt=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/image_thumb17.png\" width=\"640\" height=\"367\"><\/a><\/p>\n<p>This is the same flow as before, but this time you can see the effect of the second AcquireToken call for resource2: a single request to the Token endpoint. Let\u2019s take a look at its content:<\/p>\n<p><font face=\"Courier New\">POST <\/font><a href=\"https:\/\/login.windows.net\/cloudidentity.net\/oauth2\/token\"><font face=\"Courier New\">https:\/\/login.windows.net\/cloudidentity.net\/oauth2\/token<\/font><\/a><font face=\"Courier New\"> HTTP\/1.1<br \/>Content-Type: application\/x-www-form-urlencoded<br \/>Host: login.windows.net<br \/>Content-Length: 537<br \/>Expect: 100-continue<\/font><\/p>\n<p><font face=\"Courier New\"><strong>grant_type<\/strong>=<strong>refresh_token<\/strong>&amp;<br \/><strong>resource<\/strong>=<strong>https%3A%2F%2Fcloudidentity.net%2FcisNAPAoidc1<\/strong>&amp;<br \/>refresh_token=AwABAA[SNIP]1IAA&amp;<br \/>client_id=a4836f83-0f69-48ed-aa2b-88d0aed69652<\/font><\/p>\n<p>This time we are using the refresh token, as shown by the grant_type; we are using RT1 (I shortened it for readability but you can see it matches the screenshot of AuthenticationResult) and we are requesting the resource that we mapped to resource2.<\/p>\n<p>If you want to get tokens for other resources provisioned in the same tenant\u2026 rinse and repeat! <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/wlEmoticon-smile2.png\">&nbsp;<\/p>\n<h3>Applicability<\/h3>\n<p>As you have seen, if there is a suitable MRRT in its cache ADAL .NET will take advantage of it automatically. If for some reason you do NOT want this behavior, you can opt out by passing to AcquireToken PromptBehavior.Always (which will force the authentication prompt to show up no matter what) or opt out from using the cache (by passing null at AuthenticationContext construction time). Note that if you opted out from the cache but you still want to take advantage of this feature, you can do so by using AcquireTokenByRefreshToken and passing the target resource.<\/p>\n<p>A refresh token is a MRRT only if IsMultiResourceRefreshToken in the authentication result is set to true.<\/p>\n<p>As of today, only Windows Azure AD can issue MTTR; ADFS in Windows Server 2012 R2 (I really need to find if I can use a shorter name for it <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/wlEmoticon-smile2.png\">) does not support this, and neither does ACS (which does not support any form of refresh tokens anyway).<\/p>\n<p>&nbsp;<\/p>\n<p>Well, there you have it: the MRRT is a super-useful construct, which you are very likely to take advantage of without even knowing it\u2019s there. It will substantially reduce the times in which you need to prompt the end user, shrink traffic and make sessions more manageable. And on that topic, I still want to write a longer post\u2026 stay tuned!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After a ~one-week hiatus, I am back to cover the new features you can find in ADAL .NET. Today I am going to write about Multi-Resource Refresh Tokens. As I am not a great typist, I am going to abbreviate that in \u201cMRRT\u201d; that does not mean that it\u2019s the official acronym, what&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2464,"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-2466","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\/2466","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=2466"}],"version-history":[{"count":1,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2466\/revisions"}],"predecessor-version":[{"id":2467,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2466\/revisions\/2467"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/2464"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=2466"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=2466"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=2466"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}