{"id":2531,"date":"2013-10-29T00:27:16","date_gmt":"2013-10-29T07:27:16","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=2531"},"modified":"2013-10-29T00:28:26","modified_gmt":"2013-10-29T07:28:26","slug":"using-adals-acquiretokenby-authorizationcode-to-call-a-web-api-from-a-web-app","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2013\/10\/29\/using-adals-acquiretokenby-authorizationcode-to-call-a-web-api-from-a-web-app\/","title":{"rendered":"Using ADAL&rsquo;s AcquireTokenBy AuthorizationCode to Call a Web API From a Web App"},"content":{"rendered":"<p>We are going to publish a sample doing justice to this scenario soon, but in the meanwhile I am getting questions about this multiple times per day hence I think it\u2019s time to whip up a super-quick post and unblock some of you guys.<\/p>\n<p>Wait, what am I talking about? Perhaps I rushed a bit into it <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-bottom-style: none; border-right-style: none; border-left-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/wlEmoticon-smile6.png\"> let\u2019s take a step back:<\/p>\n<p><em>Say that you have a Web application. Say that as part of the functions it perform, your app needs to call a Web API. Say that such Web API is protected by a Windows Azure AD tenant. How do you obtain a token for it?<\/em><\/p>\n<p>The answer is \u2013 via OAuth2, of course; and via ADAL, if you don\u2019t want to write too much code.<\/p>\n<p>You might have already seen how to use ADAL for obtaining tokens from native applications: the flow for Web applications is a little different. <br \/>Web apps are characterized in the OAuth2 spec as \u201cconfidential clients\u201d, that is to say clients that can keep a secret: the idea is that what you save on your web server is not accessible to anybody else, hence you can safely save keys there. As such, during the token acquisition flow your app is required to use such a secret to identify itself. In practical terms, this means that when you create your app in the directory tenant you need to have a credential of some sort (a secret, a certificate, etc) assigned to it and later use it from your code. The good news? When you create one Web app with the new VS2013 ASP.NET templates, and you assign read or write directory access rights to it, the creation process itself will provision a secret for your app and will even make you the courtesy of saving it in your web.config, ready for you to use! That secret is put there so that your app can call the Graph API (through another flow, the client credential grant, but that\u2019s a story for another day) but it will just as well for our scenario.<\/p>\n<p>If you want to follow along, this would be a good time to drop in VS2013 and create a new Single Organization \u2013 cloud MVC app. Make sure you choose read or write in the bottom dropdown.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/image38.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_thumb38.png\" width=\"640\" height=\"452\"><\/a><\/p>\n<p>If the differences with the native client case would end here, things would be pretty easy; we\u2019d just add to AcquireToken a parameter for passing the client secret and we\u2019d be done. However differences do run a bit a deeper here.<br \/>In a native client the main app UI activity is well separated from the token acquisition flow, which takes place in a dedicated browser dialog; but for a Web app all the action takes place entirely in the browser! That means that if the user needs to interact with some external UI in order to grant to the Web app access to the Web API, he\/she needs to be shipped out to the authority that renders the consent UI and come back with some artifact showing that consent has indeed been granted. Now, the example I am showing is super special and no UI needs to be actually shown \u2013 for 2 reasons:<\/p>\n<ul>\n<li>Currently the consent for accessing resources in Windows Azure AD is admin based \u2013 that means that if the tenant admin consented for one given app\/resource to be provisioned in the tenant, direct user consent is not necessary (though user authentication is, given that the token will be issued on per-user basis)<\/li>\n<li>In this sample I am using the same AAD tenant for both web sign on and for protecting the target API \u2013 which means that when being redirected the user will land on the Authorization endpoint already authenticated, hence no UI will be shown.<br \/>I am doing this simplified scenario because it\u2019s already 11:40PM and I can\u2019t write this post all night, but in fact it\u2019s perfectly possible for you to use a different tenant or even implement web sign on in completely different fashion, without even using Windows Azure AD. There would simply be more provisioning steps involved.<\/li>\n<\/ul>\n<p>Despite the simplifications afforded by the above, the OAuth2 code grant still requires us to ship the user offsite to obtain an authorization code, retrieve that code once it comes back and use it to call AAD and obtain the necessary token(s).<\/p>\n<p>That flow is heavily dependent on the stack you are using for developing your web app, hence it was not possible for us to wrap it in its entirety in a single call as we\u2019ve done for the native clients. Rather, in ADAL this flow is split in two phases:<\/p>\n<ol>\n<li>You, the Web app developer, are responsible to initiate the process by redirecting the user to the Windows Azure AD tenant\u2019s Authorization endpoint. It\u2019s pretty straightforward, the parameters are pretty much the same you\u2019d pass to the usual ADAL calls.<br \/>You are also responsible to set up a handler\/page\/action at the configured return URL to retrieve the authorization code<\/li>\n<li>Once you have the code, you can pass it to ADAL along with the client id &amp; secret to obtain an access token, refresh token etc etc as usual.<\/li>\n<\/ol>\n<p>#1 is the part that is dependent on the development stack, hence it\u2019s up to you to implement it in whatever way is appropriate for the tech you used. #2 is all automated goodness.<\/p>\n<p>So let\u2019s make that happen, shall we? <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-bottom-style: none; border-right-style: none; border-left-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/wlEmoticon-smile6.png\"><br \/>Navigate to your Windows Azure portal, select the app you create via VS, and click Configure. You\u2019ll get to the screen below.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/image39.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; border-left: 0px; display: inline; padding-right: 0px\" border=\"0\" alt=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/image_thumb39.png\" width=\"634\" height=\"1052\"><\/a><\/p>\n<p>At the very bottom you\u2019ll see a drop down listing all the Web API provisioned in your tenant (I\u2019ll assume you have at least one; if you don\u2019t, see any of the posts I\u2019ve been publishing ion the last month and you\u2019ll find instructions to create one). Pick the one you like best, then hit Save on the command bar below.<\/p>\n<p>That done, move your attention to the Reply URL section just few lines above.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/image40.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; border-left: 0px; display: inline; padding-right: 0px\" border=\"0\" alt=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/image_thumb40.png\" width=\"487\" height=\"363\"><\/a><\/p>\n<p>Go ahead and add a new URL, corresponding to the address on which you\u2019ll want to add logic for handling the return flow carrying the code. Hit save again, then move back to VS2013.<\/p>\n<p>Head to the HomeController, and spend a second to take a look to the list of constants placed there by the template. As mentioned, those are mostly for the benefit of the boilerplate Graph code included in the UserProfile action; but they\u2019ll come in handy for us as well.<\/p>\n<p>The first thing to add is the logic for triggering the token acquisition flow. Here I\u2019ll just pick one of the default actions to host it. Here\u2019s the code, formatted for your screens:<\/p>\n<div class=\"csharpcode\">\n<pre><span class=\"lnum\">   1:  <\/span><span class=\"kwrd\">public<\/span> ActionResult About()<\/pre>\n<pre><span class=\"lnum\">   2:  <\/span>{<\/pre>\n<pre><span class=\"lnum\">   3:  <\/span>  <span class=\"kwrd\">string<\/span> authorizationUrl = <span class=\"kwrd\">string<\/span>.Format(<\/pre>\n<pre><span class=\"lnum\">   4:  <\/span>    <span class=\"str\">\"https:\/\/login.windows.net\/{0}\/oauth2\/authorize?<\/span><\/pre>\n<pre><span class=\"str\">            api-version=1.0&amp;<\/span><\/pre>\n<pre><span class=\"str\"><\/span><span class=\"str\">            response_type=code&amp;<\/span><\/pre>\n<pre><span class=\"str\">            client_id={1}&amp;<\/span><\/pre>\n<pre><span class=\"str\">            resource={2}&amp;<\/span><\/pre>\n<pre><span class=\"str\">            redirect_uri={3}\"<\/span>,<\/pre>\n<pre><span class=\"lnum\">   5:  <\/span>    ClaimsPrincipal.Current.FindFirst(TenantIdClaimType).Value,<\/pre>\n<pre><span class=\"lnum\">   6:  <\/span>    AppPrincipalId,<\/pre>\n<pre><span class=\"lnum\">   7:  <\/span>    <span class=\"str\">\"http:\/\/myadfsvagaries\/webapi\"<\/span>,<\/pre>\n<pre><span class=\"lnum\">   8:  <\/span>    <span class=\"str\">\"https:\/\/localhost:44304\/Home\/CatchCode\"<\/span><\/pre>\n<pre><span class=\"lnum\">   9:  <\/span>  );<\/pre>\n<pre><span class=\"lnum\">  10:  <\/span>&nbsp;<\/pre>\n<pre><span class=\"lnum\">  11:  <\/span>    <span class=\"kwrd\">return<\/span> <span class=\"kwrd\">new<\/span> RedirectResult(authorizationUrl);<\/pre>\n<pre><span class=\"lnum\">  12:  <\/span>}<\/pre>\n<\/div>\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>The URL is just the standard URL you\u2019ll see for any Authorization endpoint (apart for the resource parameters) but just for excess of clarity<\/p>\n<ul>\n<li>the base URL is the Windows Azure AD URL + the current tenant identifier (taken from the web sign on claim in line 5, but I could have kept it in config just as well) and the Authorize sub-url<\/li>\n<li>Line 6 carries the client id of the web app<\/li>\n<li>line 7 specifies the ID of the Web API we want to call<\/li>\n<li>line 8 contains the return URL from where we want to retrieve the code \u2013 this is the same URL we added in the portal<\/li>\n<\/ul>\n<p>That done, we just need the code to retrieve the code and use it to get the token(s).<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">public<\/span> ActionResult CatchCode(<span class=\"kwrd\">string<\/span> code)\r\n{\r\n    AuthenticationContext ac = \r\n        <span class=\"kwrd\">new<\/span> AuthenticationContext(<span class=\"kwrd\">string<\/span>.Format(<span class=\"str\">\"https:\/\/login.windows.net\/{0}\"<\/span>, \r\n                                  ClaimsPrincipal.Current.FindFirst(TenantIdClaimType).Value));\r\n    ClientCredential clcred = \r\n        <span class=\"kwrd\">new<\/span> ClientCredential(AppPrincipalId, AppKey);\r\n    var ar= \r\n        ac.AcquireTokenByAuthorizationCode(code, \r\n                   <span class=\"kwrd\">new<\/span> Uri(<span class=\"str\">\"https:\/\/localhost:44304\/Home\/CatchCode\"<\/span>), clcred);\r\n    <span class=\"kwrd\">return<\/span> View();\r\n}\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>If you followed the other posts on ADAL, you should recognize the generic structure. First we create an AuthenticationContext for the current tenant; then we create a ClientCredential with the id and the secret of the Web app (same thing we\u2019d do for calling the Graph).<\/p>\n<p>The news here is the call not to AcquireToken, but to AcquireTokenByAuthorizationCode \u2013 passing the ClientCredential and a return URL (IMPORTANT \u2013 it must be the same return URL value used in the code request!).<\/p>\n<p>The reason for the different name is to make it explicit that this is not exactly operating in the same way as the other primitives \u2013 apart from the calling pattern, for example, AcquireTokenByAuthorizationCode won\u2019t save tokens in the cache.<\/p>\n<p>Want to give it a spin? Try it! Put a breakpoint on the last line of CatchCode and hit F5. Go through the authentication, then click About. If everything goes well, you should get a nice AuthenticationResult. Let\u2019s take a look at what the debugger tells us:<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/image41.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_thumb41.png\" width=\"640\" height=\"254\"><\/a><\/p>\n<p>The main thing I wanted to show you is that the token you get contains claims describing the user, which is one of the main differentiators in respect to other server side flows like the client credentials flow provided OOB for Graph access in the template.<\/p>\n<p>&nbsp;<\/p>\n<p>There you have it! This is a very messy and incomplete walkthrough \u2013 for example, I didn\u2019t mention at all where you are going to save the tokens you just got \u2013 but as I mentioned a good &amp; comprehensive sample is on its way. Hopefully this will help unblock you, feel free to get in touch if you need clarifications! <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-bottom-style: none; border-right-style: none; border-left-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/10\/wlEmoticon-smile6.png\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We are going to publish a sample doing justice to this scenario soon, but in the meanwhile I am getting questions about this multiple times per day hence I think it\u2019s time to whip up a super-quick post and unblock some of you guys. Wait, what am I talking about? Perhaps I rushed&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2526,"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-2531","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\/2531","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=2531"}],"version-history":[{"count":1,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2531\/revisions"}],"predecessor-version":[{"id":2532,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2531\/revisions\/2532"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/2526"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=2531"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=2531"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=2531"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}