{"id":2541,"date":"2013-11-04T09:35:59","date_gmt":"2013-11-04T16:35:59","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=2541"},"modified":"2013-11-04T09:38:42","modified_gmt":"2013-11-04T16:38:42","slug":"call-a-web-api-without-knowing-in-advance-its-resource-uri-or-what-authority-it-trusts","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2013\/11\/04\/call-a-web-api-without-knowing-in-advance-its-resource-uri-or-what-authority-it-trusts\/","title":{"rendered":"Call a Web API Without Knowing in Advance Its Resource URI or What Authority It Trusts"},"content":{"rendered":"<p>Courtesy of the daylight saving switch, which made the weekend just a tad longer, here there\u2019s a quick post to show a relatively small but powerful feature of ADAL, the AuthenticationParameters class.<br \/>In a nutshell: I\u2019ll show you how you can write a client to consume a Web API secured by AD &#8211; knowing nothing at development time about the Web API\u2019s security requirement.<\/p>\n<h2>Resource-Driven Authority Discovery<\/h2>\n<p>Most of the ADAL code samples you have seen here follow the same (hopefully easy) pattern:<\/p>\n<ol>\n<li>Create an AuthenticationContext instance to represent in your code the authority (Windows Azure AD tenant\/ADFS instance) trusted by your target resource<\/li>\n<li>Use the AuthenticationContext instance to obtain a token (via any of the AcquireToken overloads) for the target resource<\/li>\n<li>Use the token to call the service<\/li>\n<\/ol>\n<p>That pattern assumes that you already know #1 the authority you want to work with, and 2# the identifier by which the target resource is known by that authority. That is often a sound assumption (after all, as of today you do have to explicitly configure permissions between a client and a resource, at least in AAD) but it does not always hold. You might have created a generic client, meant to be downloaded from some central store and used by multiple tenants that are unknown at development and publication time. <br \/>Sometimes, all you know are the coordinates of your client app itself (id, returnURI) and the physical URL (not the URI) of the resource you want to access.<\/p>\n<p>Well, good news everyone! The <a href=\"http:\/\/tools.ietf.org\/html\/rfc6750\">Bearer Token Usage P.S.<\/a> from the Oauth2.0 Authorization Framework defines a mechanism through which a protected resource can &#8211; upon receiving a request without adequate authentication credentials \u2013 challenge the caller by passing back information that the client could use to obtain the necessary credentials. Trivializing things a bit: you could say that if you call a Web API without including the token it expects, the Web API will reply back with the necessary data (usually the authority it trusts and the Web API\u2019s identifier) for you to obtain the right token and retry. This handily takes care of the aforementioned case: who cares if you don\u2019t know the authority and the id of the Web API in advance, when the Web API itself can tell you the first time you call it!<\/p>\n<p>The challenge format is super simple and you could easily parse it manually, however we decided to make things absolutely frictionless for you and baked support for it directly in the library\u2019s object model.<\/p>\n<p>The responsibility of generating the challenge is on the resource developer: that means that if besides the client app you also own writing the Web API, it\u2019s up to you to inject the necessary logic. <br \/>The <a href=\"http:\/\/code.msdn.microsoft.com\/AAL-Native-Application-to-fd648dcf\">main ADAL sample on code gallery<\/a> does demonstrate this approach. However we wrote that sample in the pre-OWIN era, when you had to handle all the resource side code (JWT interception, validation, ClaimsPrincipal creation, etc) by hand. I wanted to make sure you know how to take advantage of this feature also when you are creating your Web API with the VS2013 templates (AAD tutorial <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/09\/09\/whats-new-for-organizational-accounts-in-visual-studio-2013-rc\/\">here<\/a>, ADFS tutorial <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/10\/25\/securing-a-web-api-with-adfs-on-ws2012-r2-got-even-easier\/\">here<\/a>) and OWIN middleware. As of today that entails customizations that might not immediately clear, or at least weren\u2019t for me: luckily I had the help of <a href=\"https:\/\/www.codeplex.com\/site\/users\/view\/davidmatson\">David Matson<\/a>, a developer on the ASP.NET team that knows this stuff inside out and also happens to be the fastest typist I\u2019ve ever seen working in the VS IDE <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\/11\/wlEmoticon-smile.png\"> Thanks David!<\/p>\n<p>Here there\u2019s how I am going to break this down: first I\u2019ll walk you though the code you need to add to the Web API project to generate the challenge, then I\u2019ll show you what parts of ADAL you can use on the client to make sure your app understands the challenge. That done, we\u2019ll give it a spin and then we\u2019ll make some larger scope considerations.<\/p>\n<h2>Emitting a Challenge From Your Web API<\/h2>\n<p>Let\u2019s start by creating a Web API project configured to work with organizational accounts, as described <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/09\/09\/whats-new-for-organizational-accounts-in-visual-studio-2013-rc\/\">here<\/a>.<br \/>That will provide us with the perfect starting point, a Web API project already provisioned in Windows Azure AD and already configured with the necessary OWIN middleware to validate JWTs from the Windows Azure AD tenant we used for creating the project.<\/p>\n<p>The goal is to modify the behavior of the authentication OWIN middleware to produce a suitable Challenge message whenever a 401 response is warranted.<\/p>\n<p>To do that, we will need to play a bit with the lower level components that ASP.NET uses for working with OWIN in Web API projects. Go to the Solution Explorer, right click on the Web API project and choose Manage NuGet Packages. Search for Microsoft.AspNet.WebApi.Owin and once you find it install it.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/11\/image.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\/11\/image_thumb.png\" width=\"640\" height=\"426\"><\/a><\/p>\n<p>Excellent. That done, go to the Controllers folder and open the ValuesController.cs. We are going to use the default code generated by the template. Take a look at the controller declaration:<\/p>\n<pre class=\"csharpcode\">[Authorize]\r\n<span class=\"kwrd\">public<\/span> <span class=\"kwrd\">class<\/span> ValuesController : ApiController\r\n{\r\n    <span class=\"rem\">\/\/ GET api\/values<\/span>\r\n    <span class=\"kwrd\">public<\/span> IEnumerable&lt;<span class=\"kwrd\">string<\/span>&gt; Get()\r\n    {\r\n        <span class=\"kwrd\">return<\/span> <span class=\"kwrd\">new<\/span> <span class=\"kwrd\">string<\/span>[] { <span class=\"str\">\"value1\"<\/span>, <span class=\"str\">\"value2\"<\/span> };\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>The template decorates the controller with [Authorize] to enforce that the caller will be granted access only upon presentation of the correct credentials \u2013 in this case, a JWT from the right AAD tenant.<\/p>\n<p>Now, the Owin middleware already has its own challenge generation logic \u2013 but it does not generate the kind of message we want. David tells me that as of today the strategy that yields the best code economy consists in<\/p>\n<ol>\n<li>creating a filter that will turn off the default challenge behavior<\/li>\n<li>creating a filter that will pick up that functionality and produce the message we want<\/li>\n<\/ol>\n<p>In practice, this means that the code above will change to look like the following:<\/p>\n<pre class=\"csharpcode\">[HostAuthenticationNoChallenge(<span class=\"str\">\"Bearer\"<\/span>)]\r\n[WindowsAzureADChallenge]\r\n[Authorize]\r\n<span class=\"kwrd\">public<\/span> <span class=\"kwrd\">class<\/span> ValuesController : ApiController\r\n{\r\n    <span class=\"rem\">\/\/ GET api\/values<\/span>\r\n    <span class=\"kwrd\">public<\/span> IEnumerable&lt;<span class=\"kwrd\">string<\/span>&gt; Get()\r\n    {\r\n        <span class=\"kwrd\">return<\/span> <span class=\"kwrd\">new<\/span> <span class=\"kwrd\">string<\/span>[] { <span class=\"str\">\"value1\"<\/span>, <span class=\"str\">\"value2\"<\/span> };\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>The first attribute does #1, the second one does #2. Let\u2019s define those classes, starting with HostAuthenticationNoChallenge. Here there\u2019s the code:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">public<\/span> <span class=\"kwrd\">class<\/span> HostAuthenticationNoChallengeAttribute : Attribute, IAuthenticationFilter\r\n{\r\n    <span class=\"kwrd\">private<\/span> <span class=\"kwrd\">readonly<\/span> IAuthenticationFilter _inner;\r\n\r\n    <span class=\"kwrd\">public<\/span> HostAuthenticationNoChallengeAttribute(<span class=\"kwrd\">string<\/span> authenticationType)\r\n    {\r\n        _inner = <span class=\"kwrd\">new<\/span> HostAuthenticationAttribute(authenticationType);\r\n    }\r\n\r\n    <span class=\"kwrd\">public<\/span> Task AuthenticateAsync(HttpAuthenticationContext context, <\/pre>\n<pre class=\"csharpcode\">                                  CancellationToken cancellationToken)\r\n    {\r\n        <span class=\"kwrd\">return<\/span> _inner.AuthenticateAsync(context, cancellationToken);\r\n    }\r\n\r\n    <span class=\"kwrd\">public<\/span> Task ChallengeAsync(HttpAuthenticationChallengeContext context, <\/pre>\n<pre class=\"csharpcode\">                               CancellationToken cancellationToken)\r\n    {\r\n        <span class=\"kwrd\">return<\/span> Task.FromResult(0);\r\n    }\r\n\r\n    <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">bool<\/span> AllowMultiple\r\n    {\r\n        get { <span class=\"kwrd\">return<\/span> _inner.AllowMultiple; }\r\n    }\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>That does not have a lot going identity-wise, hence I am mostly using this as boilerplate logic for enabling the next class to do its job:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">public<\/span> <span class=\"kwrd\">class<\/span> WindowsAzureADChallengeAttribute : Attribute, IAuthenticationFilter\r\n{\r\n    <span class=\"kwrd\">public<\/span> Task AuthenticateAsync(HttpAuthenticationContext context, <\/pre>\n<pre class=\"csharpcode\">                                  CancellationToken cancellationToken)\r\n    {\r\n        <span class=\"kwrd\">return<\/span> Task.FromResult(0);\r\n    }\r\n\r\n    <span class=\"kwrd\">public<\/span> Task ChallengeAsync(HttpAuthenticationChallengeContext context, <\/pre>\n<pre class=\"csharpcode\">                               CancellationToken cancellationToken)\r\n    {\r\n        context.Result = <span class=\"kwrd\">new<\/span> AADChallengeResult { Inner = context.Result };\r\n        <span class=\"kwrd\">return<\/span> Task.FromResult(0);\r\n    }\r\n\r\n    <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">bool<\/span> AllowMultiple\r\n    {\r\n        get { <span class=\"kwrd\">return<\/span> <span class=\"kwrd\">true<\/span>; }\r\n    }\r\n\r\n    <span class=\"kwrd\">private<\/span> <span class=\"kwrd\">class<\/span> AADChallengeResult : IHttpActionResult\r\n    {\r\n        <span class=\"kwrd\">public<\/span> IHttpActionResult Inner { get; set; }\r\n        <span class=\"kwrd\">public<\/span> async Task&lt;HttpResponseMessage&gt; ExecuteAsync(CancellationToken cancellationToken)\r\n        {\r\n            HttpResponseMessage response = await Inner.ExecuteAsync(cancellationToken);\r\n            <span class=\"kwrd\">if<\/span> (response.StatusCode == HttpStatusCode.Unauthorized)\r\n            {\r\n                <span class=\"kwrd\">string<\/span> challengeMessage = \r\n                    <span class=\"kwrd\">string<\/span>.Format(<span class=\"str\">\"authorization_uri=\\\"https:\/\/login.windows.net\/{0}\\\",resource_id={1}\"<\/span>,\r\n                                    ConfigurationManager.AppSettings[<span class=\"str\">\"ida:Tenant\"<\/span>],\r\n                                    ConfigurationManager.AppSettings[<span class=\"str\">\"ida:Audience\"<\/span>]);\r\n                AuthenticationHeaderValue authenticateHeader = <\/pre>\n<pre class=\"csharpcode\">                     <span class=\"kwrd\">new<\/span> AuthenticationHeaderValue(<span class=\"str\">\"Bearer\"<\/span>, challengeMessage);\r\n                response.Headers.WwwAuthenticate.Add(authenticateHeader);\r\n            }\r\n            <span class=\"kwrd\">return<\/span> response;\r\n        }\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>As you can imagine, the core of the challenge generation logic takes place in AADChallengeResult and specifically in ExecuteAsync. In summary: if the response is carrying a 401, the code inserts in the www-authenticate header a \u201cBearer\u201d followed by a comma separated values list containing authorization_uri (the authority the Web API wants you to use when requesting a token for it) and resource_id (the ID you should sue with that authority when requesting a token for this Web API).<br \/>Both values come straight from the AppSettings entries populated by the template at project creation time. That means that the code you see here is 100% boilerplate: you can paste it in ANY Web API project generated with VS2013 with organizational account authentication, and as long as you didn\u2019t change anything fundamental it will work right away as is with no changes need.<\/p>\n<h2>Using AuthenticationParameters in the Client\u2019s Code<\/h2>\n<p>Moving back to the client. You can use any .NET client type you like; here I\u2019m using a WinForm app given that it\u2019s super fast. Follow the instructions in the section \u201cRegister a Native Client\u201d in <a href=\"http:\/\/msdn.microsoft.com\/en-us\/magazine\/dn463788.aspx\">this article<\/a> to let WIndows Azure AD know about your client and enable the necessary permissions for the client to call your Web API. That done, add the following code in the click handler of a button:<\/p>\n<div class=\"csharpcode\">\n<pre><span class=\"lnum\">   1:  <\/span><span class=\"kwrd\">private<\/span> async <span class=\"kwrd\">void<\/span> button1_Click(<span class=\"kwrd\">object<\/span> sender, EventArgs e)<\/pre>\n<pre><span class=\"lnum\">   2:  <\/span>{<\/pre>\n<pre><span class=\"lnum\">   3:  <\/span>    <span class=\"kwrd\">string<\/span> webApiUrl = <span class=\"str\">\"https:\/\/localhost:44305\/api\/Values\"<\/span>;<\/pre>\n<pre><span class=\"lnum\">   4:  <\/span>    <span class=\"kwrd\">string<\/span> clientID = <span class=\"str\">\"220c8fe6-5f65-405f-bff3-089e88a2b9d4\"<\/span>;<\/pre>\n<pre><span class=\"lnum\">   5:  <\/span>    <span class=\"kwrd\">string<\/span> returnUri = <span class=\"str\">\"http:\/\/challengedclient\"<\/span>;<\/pre>\n<pre><span class=\"lnum\">   6:  <\/span>&nbsp;<\/pre>\n<pre><span class=\"lnum\">   7:  <\/span>    AuthenticationParameters ap = <\/pre>\n<pre><span class=\"lnum\">   8:  <\/span>        AuthenticationParameters.CreateFromResourceUrl(<span class=\"kwrd\">new<\/span> Uri(webApiUrl));<\/pre>\n<pre><span class=\"lnum\">   9:  <\/span>    AuthenticationContext ac = <\/pre>\n<pre><span class=\"lnum\">  10:  <\/span>        <span class=\"kwrd\">new<\/span> AuthenticationContext(ap.Authority);<\/pre>\n<pre><span class=\"lnum\">  11:  <\/span>    AuthenticationResult ar = <\/pre>\n<pre><span class=\"lnum\">  12:  <\/span>        ac.AcquireToken(ap.Resource, <\/pre>\n<pre><span class=\"lnum\">  13:  <\/span>                        clientID, <\/pre>\n<pre><span class=\"lnum\">  14:  <\/span>                        <span class=\"kwrd\">new<\/span> Uri(returnUri));<\/pre>\n<pre><span class=\"lnum\">  15:  <\/span>&nbsp;<\/pre>\n<pre><span class=\"lnum\">  16:  <\/span>    HttpClient client = <span class=\"kwrd\">new<\/span> HttpClient();<\/pre>\n<pre><span class=\"lnum\">  17:  <\/span>    HttpRequestMessage request =<\/pre>\n<pre><span class=\"lnum\">  18:  <\/span>        <span class=\"kwrd\">new<\/span> HttpRequestMessage(HttpMethod.Get, webApiUrl);<\/pre>\n<pre><span class=\"lnum\">  19:  <\/span>    request.Headers.TryAddWithoutValidation(<span class=\"str\">\"Authorization\"<\/span>, <\/pre>\n<pre><span class=\"lnum\">  20:  <\/span>                    ar.CreateAuthorizationHeader());<\/pre>\n<pre><span class=\"lnum\">  21:  <\/span>    HttpResponseMessage response = <\/pre>\n<pre><span class=\"lnum\">  22:  <\/span>        await client.SendAsync(request);<\/pre>\n<pre><span class=\"lnum\">  23:  <\/span>    <span class=\"kwrd\">string<\/span> responseString = <\/pre>\n<pre><span class=\"lnum\">  24:  <\/span>        await response.Content.ReadAsStringAsync();<\/pre>\n<pre><span class=\"lnum\">  25:  <\/span>&nbsp;<\/pre>\n<pre><span class=\"lnum\">  26:  <\/span>    MessageBox.Show(responseString);<\/pre>\n<pre><span class=\"lnum\">  27:  <\/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>Now, this is the part I want to drill in a bit.<\/p>\n<p>Lines 3, 4 and 5 hold the initial values we know of from the client\u2019s perspective: the client coordinates, which will remain the same (usually) no matter which resource we\u2019ll access, and the physical, network-addressable endpoint at which the target resource resides.<\/p>\n<p>Lines 7 is where the magic happens. The class AuthenticationParameters is especially designed to help you to take advantage of resources that can emit challenges: it contains logic for eliciting a challenge and make the results easily accessible to you. What is demonstrated here is the case in which you know for sure that the resource supports challenges and you want to take advantage of that upfront: however this is not the only way to use it, as we\u2019ll see later.What is demonstrated here is the case in which you know for sure that the resource supports challenges and you want to take advantage of that upfront: however this is not the only way to use it, as we\u2019ll see later.<a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/11\/image1.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\/11\/image_thumb1.png\" width=\"640\" height=\"266\"><\/a><br \/>The static method CreateFromResourceUrl simply GETs the resource at the URL provided, and wraps the salient elements of the challenge in the properties of a new AuthenticationParameters instance.<\/p>\n<p>Line 9 demonstrates how to use the information received from the challenge to create your AuthenticationContext against the AAD tenant requested by the resource.<\/p>\n<p>Line 11 shows how to use the resource ID obtained form the challenge to acquire a token correctly scoped.<\/p>\n<p>The rest of the code is just the usual call to a default Web API, which you have seen a million times by now <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\/11\/wlEmoticon-smile.png\"><\/p>\n<blockquote>\n<p><strong><font color=\"#ff0000\">IMPORTANT<\/font><\/strong>: using the challenge information to drive authentication entails a certain amount of risk. For what concerns authenticating the user this is somewhat mitigated by the authority validation in the AAD case, though it remains a risk for the ADFS case (where the automatic validation feature is not available and AuthenticationContext calls must turn that off). You should ensure you perform whatever checks make sense in your scenario before blindly trusting what you receive in the challenge.<br \/>Special consideration should be given to the risk of token forwarding attacks. Imagine that a malicious resource A wants to gain access to resource B. If you use the challenge mechanism for calling A, A might send you a challenge containing the resource ID for B. If you\u2019d just blindly follow what A says, you\u2019d obtain a token scoped for B and present it in your call for A. At that point, A could use that token for calling B and pretending to be you. NOT good.<br \/>How do you defend yourself from this? Mostly by enforcing constraints on the shape of the resource IDs received. For example, you might want to impose that the URI of the resource returned in the challenge uses the same domain\/hostname of the physical address at which the resource is listening from. That is not always applicable, especially at development time or if you didn\u2019t register a vanity domain; but it\u2019s a good example of what you might want to do to prevent issues.<br \/>And of course, all the basic networking hygiene applies here: do this only on HTTPS, ensure that the SSL channels are correctly validated to prevent DNS attacks, and so on.<\/p>\n<\/blockquote>\n<p>&nbsp;<\/p>\n<h2>The Solution in Action<\/h2>\n<p>Let\u2019s give the solution a spin! Start both the Web API and the client project, put a breakpoint on line 9 on the client and hit the button.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/11\/image2.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\/11\/image_thumb2.png\" width=\"640\" height=\"94\"><\/a><\/p>\n<p>The challenge generation logic worked, and AuthenticationParameters contains the right values. If you hit F5 you\u2019ll see that the call performed according to those parameters succeeds. Q.E.D.<\/p>\n<h2>Want More?<\/h2>\n<p>This is a very basic use of the feature. As you have seen in the class diagram excerpt above, AuthenticationParameters offers other methods for populating its properties. Those are meant for more reactive scenarios, in which you receive a 401 during an actual call to the Web API and the response contains a challenge. The two overloads are meant to offer you the convenience of working at whatever level (header or entire response) you are confortable with, or what is dictated by the error management in the client library you are using if the resource you are targeting offers one.<\/p>\n<p>You\u2019d want to modify that logic for Web API working against ADFS (you would not hardcode login.windows net in the authority_uri). The warnings I gave earlier are especially serious when working with an on-premises instance, hence I recommend you do as much due diligence as possible before enabling the feature.<\/p>\n<p>The static logic shown here would not work in case of multi-tenant resources: in that case you\u2019d likely add some route-based logic in your filters to customize the challenge to the AAD tenant meant to secure a given Web API route (which might contains hints of the tenant it is meant for). Remember: for URLs that carry no indication of who the intended tenant might be, there\u2019s always the option using the Common endpoint <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\/11\/wlEmoticon-smile.png\"><\/p>\n<p>Finally: the use of this feature might at times lead to some odd behaviors if the Web API does not do its job properly. Say that the challenge generation logic is buggy and the requirements sent back in the challenge are not the same requirements enforced at request time: if your client is using the challenge to react to access errors, it might end up in a poisoned loop in which it obtains a token which complies to the Web API challenge \u2013 but that it fails when used, generating the same challenge and going back to square 1. There\u2019s no automated logic in ADAL to help you detecting this situation, given that ADAL stays out of your way when you are actually accessing the resource, hence to prevent similar situations you\u2019ll have to make the necessary checks in your own code.<\/p>\n<p>That said, I don\u2019t want the above to scare you!<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\/11\/wlEmoticon-smile.png\"> like everything concerning security this feature requires due diligence, but once that\u2019s done you get clients that can be self-configuring without the need of out of band settings acquisition logic. I believe this will be super important, especially once this capability will be available for the ADAL flavors targeting applications stores <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-winkingsmile\" style=\"border-top-style: none; border-bottom-style: none; border-right-style: none; border-left-style: none\" alt=\"Winking smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/11\/wlEmoticon-winkingsmile.png\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Courtesy of the daylight saving switch, which made the weekend just a tad longer, here there\u2019s a quick post to show a relatively small but powerful feature of ADAL, the AuthenticationParameters class.In a nutshell: I\u2019ll show you how you can write a client to consume a Web API secured by AD &#8211; knowing&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2537,"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-2541","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\/2541","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=2541"}],"version-history":[{"count":1,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2541\/revisions"}],"predecessor-version":[{"id":2542,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2541\/revisions\/2542"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/2537"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=2541"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=2541"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=2541"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}