{"id":1163,"date":"2010-08-19T11:07:58","date_gmt":"2010-08-19T11:07:58","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/odatateam\/2010\/08\/19\/odata-and-authentication-part-8-oauth-wrap\/"},"modified":"2010-08-19T11:07:58","modified_gmt":"2010-08-19T11:07:58","slug":"odata-and-authentication-part-8-oauth-wrap","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/odata\/odata-and-authentication-part-8-oauth-wrap\/","title":{"rendered":"OData and Authentication \u2013 Part 8 \u2013 OAuth WRAP"},"content":{"rendered":"<p>OAuth WRAP is a claims based authentication protocol supported by the <a href=\"http:\/\/www.microsoft.com\/windowsazure\/appfabric\/\">AppFabric<\/a> Access Control (ACS) which is part of <a href=\"http:\/\/www.microsoft.com\/windowsazure\/\">Windows Azure<\/a>.<\/p>\n<p>But most importantly it is REST (and thus OData) friendly too.<\/p>\n<p>The idea is that you authenticate against an ACS server and acquire a Simple Web Token or SWT \u2013 which contains signed claims about identity \/ roles \/ rights etc \u2013 and then embed the SWT in requests to a resource server that trusts the ACS server.<\/p>\n<p>The resource server then looks for and verifies the SWT by checking it is correctly signed, before allowing access based on the claims made in the SWT.<\/p>\n<p>If you want to learn more about OAuth WRAP itself here\u2019s the <a href=\"http:\/\/tools.ietf.org\/html\/draft-hardt-oauth-01\">spec<\/a>.<\/p>\n<h3>Goal<\/h3>\n<p>Now we know the principles behind OAuth WRAP it\u2019s time to map those into the OData world.<\/p>\n<p>Our goal is simple. We want an OData service that uses OAuth WRAP for authorization and a client to test it end to end.<\/p>\n<h3>Why OAuth WRAP?<\/h3>\n<p>You might be wondering why this post covers OAuth WRAP and not <a href=\"https:\/\/en.wikipedia.org\/wiki\/OAuth\">OAuth 2.0<\/a>. <\/p>\n<p>OAuth 2.0 essentially combines the best features of OAuth 1.0 and OAuth WRAP.<\/p>\n<p>Unfortunately OAuth 2.0 is not yet a ratified standard, so ACS doesn\u2019t support it yet. On the other hand OAuth 1.0 is cumbersome for RESTful protocols like OData. So that leaves OAuth WRAP.<\/p>\n<p>However once it is ratified OAuth 2.0 will essentially depreciate OAuth WRAP and ACS will rev to support it. When that happens you can expect to see a new post in this Authentication Series.<\/p>\n<h3>Strategy<\/h3>\n<p>First we\u2019ll provision an ACS server to act as our identity server.<\/p>\n<p>Next we\u2019ll configure our identity server with appropriate roles, scopes and claim transformation rules etc.<\/p>\n<p>Then we\u2019ll create a HttpModule (see <a href=\"http:\/\/blogs.msdn.com\/b\/astoriateam\/archive\/2010\/07\/19\/odata-and-authentication-part-5-custom-httpmodules.aspx\">part 5<\/a>) to intercept all requests to the server, which will crack open the SWT, convert it into an IPrincipal and store it in HttpContext.Current.Request.User. This way it can be accessed later for authorization purposes inside the Data Service.<\/p>\n<p>Then we\u2019ll create a simple OData service using WCF Data Services and protect it with a custom HttpModule.<\/p>\n<p>Finally we\u2019ll write client code to authenticate against the ACS server and acquire a SWT token. We\u2019ll use the techniques you saw in <a href=\"http:\/\/blogs.msdn.com\/b\/astoriateam\/archive\/2010\/05\/24\/odata-and-authentication-part-3-clientside-hooks.aspx\">part 3<\/a> to send the SWT as part of every request to our OData services.<\/p>\n<h3>Step 1 \u2013 Provisioning an ACS server<\/h3>\n<p>First you\u2019ll need an <a href=\"http:\/\/www.microsoft.com\/windowsazure\/offers\/\">Windows Azure account<\/a> and a running AppFabric namespace.<\/p>\n<p>Once your namespace is running you also have a running ACS server.<\/p>\n<h3>Step 2 \u2013 Configuring the ACS server<\/h3>\n<p>To correctly configure the ACS server you\u2019ll need to Install the Windows Azure Platform AppFabric SDK which you can find <a href=\"http:\/\/www.microsoft.com\/windowsazure\/appfabric\/\">here<\/a>.<\/p>\n<p>ACM.exe is a command line tool that ships as part of the AppFabric SDK, and that allows you to create Issuers, TokenPolicies, Scopes and Rules.<\/p>\n<p>For an introduction to ACM.exe and ACS look no further than this <a href=\"http:\/\/download.microsoft.com\/download\/E\/5\/8\/E5870ED0-2A57-4970-B140-14815AD45CF6\/A%20Developer%27s%20Guide%20to%20Access%20Control%20in%20Windows%20Azure%20platform%20AppFabric.docx\">excellent guide<\/a> by <a href=\"http:\/\/www.pluralsight-training.net\/community\/blogs\/keith\/\">Keith Brown<\/a>.<\/p>\n<p>To simplify our acm commands you should edit your ACM.exe.config file to include information about your ACS like this:<\/p>\n<p><font face=\"Courier New\">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;      <br \/>&lt;configuration&gt;       <br \/>&#160; &lt;appSettings&gt;       <br \/>&#160;&#160;&#160; &lt;add key=&quot;host&quot; value=&quot;accesscontrol.windows.net&quot;\/&gt;       <br \/>&#160;&#160;&#160; &lt;add key=&quot;service&quot; value=&quot;{<strong>Your service namespace goes here}<\/strong>&quot;\/&gt;       <br \/>&#160;&#160;&#160; &lt;add key=&quot;mgmtkey&quot; value=&quot;{<strong>Your Windows Azure Management Key goes here}<\/strong>&quot;\/&gt;       <br \/>&#160; &lt;\/appSettings&gt;       <br \/>&lt;\/configuration&gt;<\/font><\/p>\n<p>Doing this saves you from having to re-enter this information every time you run ACM. <\/p>\n<p>Very handy.<\/p>\n<h4>Claims Transformation<\/h4>\n<p>Before we start configuring our ACS we need to know a few principles\u2026<\/p>\n<p>Generally claims authentication is used to translate a set of input claims into a signed set of output claims.    <\/p>\n<p>Sometimes this extends to Federation, which allows trust relationships to be established between identity providers, such that a user on one system can gain access to resources on another system.<\/p>\n<p>However in this blog post we are going to keep it simple and skip federation.&#160; <\/p>\n<p>Don\u2019t worry though we\u2019ll add federation in the next post.<\/p>\n<h4>Issuers<\/h4>\n<p>In ACS terms an Issuer represents a security principal. And whether we want federation or not our first step is to create a new issuer like this:<\/p>\n<p><font size=\"2\"><font face=\"Lucida Console\"><strong>&gt; acm create issuer          <br \/>&#160;&#160;&#160; -name: partner           <br \/><\/strong><\/font><\/font><font size=\"2\"><font face=\"Lucida Console\"><strong>&#160;&#160;&#160; -issuername: partner          <br \/>&#160;&#160;&#160; -autogeneratekey<\/strong><\/font><\/font>&#160;<\/p>\n<p>This will generate a key which you can retrieve by issuing this command:<\/p>\n<p><font size=\"2\" face=\"Lucida Console\"><strong>&gt; acm getall issuer        <br \/>&#160;&#160;&#160;&#160;&#160; <\/strong><\/font><font size=\"2\" face=\"Lucida Console\"><strong>Count: 1 <\/strong><\/font><\/p>\n<p><font size=\"2\" face=\"Lucida Console\"><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; id: iss_89f12a7ed023c3b7b0a85f32dff96fed2014ad0a        <br \/>&#160;&#160;&#160;&#160;&#160;&#160; name: odata-issuer         <br \/>issuername: odata-issuer         <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; key: 9QKoZgtxxU4ABv8uiuvaR+k0cOmUxfEOE0qfPK2lCJY=         <br \/>previouskey: 9QKoZgtxxU4ABv8uiuvaR+k0cOmUxfEOE0qfPK2lCJY=         <br \/>&#160; algorithm: Symmetric256BitKey<\/strong><\/font> <\/p>\n<p>Our clients are going to need to know this key, so make a note of it for later.<\/p>\n<h4>Token Policy <\/h4>\n<p>Next we need a token policy. Token Policies specify a timeout indicating how long a new Simple Web Token (or SWT) should be valid, or put another way, how long before the SWT expires.<\/p>\n<p>When creating a token policy you need to balance security versus ease of use and convenience. The shorter the timeout the more likely it is to be based on up to date Identity and Role information, but that comes at the cost of frequent refreshes, which have performance and convenience implications.<\/p>\n<p>For our purposes a timeout of 1 hour is probably about right. So we create a new policy like this:<\/p>\n<p><font size=\"2\" face=\"Lucida Console\"><strong>&gt; acm create tokenpolicy        <br \/>&#160;&#160;&#160; -name: odata-service-policy         <br \/>&#160;&#160;&#160; -timeout: 3600         <br \/>&#160;&#160;&#160; -autogeneratekey<\/strong><\/font><\/p>\n<p>Where 3600 is the number of seconds in an hour. To see what you created issue this command:<\/p>\n<p><font size=\"2\" face=\"Lucida Console\"><strong>&gt; acm getall tokenpolicy        <br \/><\/strong><\/font><font size=\"2\" face=\"Lucida Console\"><strong>&#160; Count: 1 <\/strong><\/font><\/p>\n<p><font size=\"2\" face=\"Lucida Console\"><strong>&#160;&#160;&#160;&#160; id: tp_aaf3fd9ca64d4471a5c7b5c572c087fb        <br \/>&#160;&#160; name: odata-service-policy         <br \/>timeout: 3600         <br \/>&#160;&#160;&#160; key: WRwJkQ9PgbhnIUgKuuovw\/6yVAo\/Dh0qrb7rqQWnsBk=<\/strong><\/font><\/p>\n<\/p>\n<p>We\u2019ll need both the id and key later. <\/p>\n<p>This key is what we share with our resource servers, so that they can check SWTs are correctly signed. We\u2019ll come back to that later.<\/p>\n<h4>Scope<\/h4>\n<p>A service may have multiple \u2018scopes\u2019 each with a different set of access rules and rights.<\/p>\n<p>Scopes are linked to a token policy, telling ACS how long SWTs should remain valid, how to sign the SWT, and scopes contain a set of rules which tell ACS how to translate incoming claims into claims embedded in the SWT.<\/p>\n<p>When requesting a SWT a client must include an \u2018applies_to\u2019 parameter, which tells ACS for which scope they need a SWT, and consequently which token policy and rules should apply when constructing the SWT.<\/p>\n<p>Here are just some of the reasons you might need multiple scopes:<\/p>\n<ul>\n<li>A multi-tenant resource server would probably need different rules per tenant. <\/li>\n<li>A single-tenant resource server with distinct sets of independently protected resources. <\/li>\n<\/ul>\n<p>But for our purposes one scope is enough.<\/p>\n<p><font size=\"2\" face=\"Lucida Console\"><strong>&gt; acm create scope        <br \/>&#160;&#160;&#160; -name: odata-service-scope         <br \/>&#160;&#160;&#160; -appliesto:http:\/\/odata.mydomain.com         <br \/>&#160;&#160;&#160; -tokenpolicyid:tp_aaf3fd9ca64d4471a5c7b5c572c087fb<\/strong><\/font><\/p>\n<p>For \u2018appliesto\u2019 I chose the url for our planned OData service. Notice too that we bind the scope to the token policy we just created via it\u2019s id. <\/p>\n<p>You can retrieve this scope by executing this:<\/p>\n<p><font size=\"2\" face=\"Lucida Console\"><strong>&gt; acm getall scope        <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Count: 1 <\/strong><\/font><\/p>\n<p><font size=\"2\" face=\"Lucida Console\"><strong>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; id: scp_c028015be790fb5d3ead59307bb3e537d586eac0        <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; name: odata-service         <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; appliesto: <\/strong><\/font><font size=\"2\" face=\"Lucida Console\"><strong>http:\/\/odata.mydomain.com<\/strong><\/font>     <br \/><font size=\"2\" face=\"Lucida Console\"><strong>&#160;&#160;&#160;&#160; tokenpolicyid: tp_d8c65f770fb14a90bc707e958a722df9<\/strong><\/font><\/p>\n<p>You\u2019ll need to know the scopeid to add Rules to the scope.<\/p>\n<h3>Rules<\/h3>\n<p>ACS has one real job, which you could sum up with these four words: \u201cClaims in, claims out\u201d. Essentially ACS is just a claims transformation engine, and the transformation is achieved by applying a series of rules. <\/p>\n<p>The rules are associated with a scope, and tell ACS how to transform input claims for the target scope (via applies_to) into signed output claims.<\/p>\n<p>In our simple example, all we really want to do is this: \u2018If you know the key of my issuer, we\u2019ll sign a claim that you are a \u2018User\u2019.<\/p>\n<p>To do that we need this rule:<\/p>\n<p><font size=\"2\" face=\"Lucida Console\"><strong>&gt; acm create rule        <br \/>-name:partner-is-user         <br \/>-scopeid:scp_c028015be790fb5d3ead59307bb3e537d586eac0         <br \/>-inclaimissuerid:iss_89f12a7ed023c3b7b0a85f32dff96fed2014ad0a         <br \/>-inclaimtype:Issuer         <br \/>-inclaimvalue:partner         <br \/>-outclaimtype:Roles         <br \/>-outclaimvalue:User         <br \/><\/strong><\/font>    <br \/>&quot;Issuer&quot; is a special type of input claim type (normally input claim type is just a string that needs to be found in an incoming SWT) that says anyone who demonstrates direct knowledge of the issuer key will receive a SWT that includes that output claim specified in the rule*. <\/p>\n<p>So this particular rule means anyone who issues an OAuth WRAP request with the Issuer name as the <u>wrap_name<\/u> and the Issuer key as the <u>wrap_password<\/u> will receive a signed SWT that claims their &quot;Roles=User&quot;.<\/p>\n<p><font color=\"#404040\"><strong>*NOTE:<\/strong> there are other ways that this rule particular can match, but they are outside the scope of this blog post, check out this <\/font><a href=\"http:\/\/download.microsoft.com\/download\/E\/5\/8\/E5870ED0-2A57-4970-B140-14815AD45CF6\/A%20Developer%27s%20Guide%20to%20Access%20Control%20in%20Windows%20Azure%20platform%20AppFabric.docx\"><font color=\"#404040\">excellent guide<\/font><\/a><font color=\"#404040\"> by <\/font><a href=\"http:\/\/www.pluralsight-training.net\/community\/blogs\/keith\/\"><font color=\"#404040\">Keith Brown<\/font><\/a><font color=\"#404040\"> for more.<\/font><\/p>\n<p>To test that our rule is working try this:<\/p>\n<p><font face=\"Courier New\">WebClient client = new WebClient();      <br \/>client.BaseAddress = &quot;<\/font><font face=\"Courier New\">https:\/\/{your-namespace-goes-here}.accesscontrol.windows.net&quot;;<\/font>     <br \/><font face=\"Courier New\">     <br \/>NameValueCollection values = new NameValueCollection();       <br \/>values.Add(&quot;wrap_name&quot;, &quot;partner&quot;);       <br \/>values.Add(&quot;wrap_password&quot;, &quot;9QKoZgtxxU4ABv8uiuvaR+k0cOmUxfEOE0qfPK2lCJY=&quot;);       <br \/>values.Add(&quot;wrap_scope&quot;, &quot;<\/font><font face=\"Courier New\">http:\/\/odata.mydomain.com&quot;);<\/font>     <br \/><font face=\"Courier New\">     <br \/>byte[] responseBytes = client.UploadValues(&quot;WRAPv0.9&quot;, &quot;POST&quot;, values);       <\/p>\n<p>string response = Encoding.UTF8.GetString(responseBytes);       <br \/>string token = response.Split(&#8216;&amp;&#8217;)       <br \/>&#160;&#160;&#160; .Single(value =&gt; value.StartsWith(&quot;wrap_access_token=&quot;))       <br \/>&#160;&#160;&#160; .Split(&#8216;=&#8217;)[1]; <\/font><\/p>\n<p><font face=\"Courier New\">Console.WriteLine(token);<\/font><\/p>\n<p>When I run that code get this:<\/p>\n<p><font size=\"2\" face=\"Lucida Console\"><strong>Roles%3dUser%26Issuer%3dhttps%253a%252f%252ffabrikamjets.accesscontrol.windows.net%252f%26Audience%3dhttp%253a%252f%252fodata.mydomain.com%26ExpiresOn%3d1282071821%26HMACSHA256%3d%252bc2ZiBpm74Etw%252bAkXY1jNwme8acHfIYd9AAtGMckoss%253d<\/strong><\/font><\/p>\n<p>As you can see the Roles%#dUser is simply a UrlEncoded version of Roles=User, so assuming this is a correctly signed SWT (more on that in Step 3) our rule appears to be working.<\/p>\n<h3>Step 3 \u2013 Creating the OAuth WRAP HttpModule<\/h3>\n<p>Now we have our ACS server correctly configured the next step is to create a HttpModule to crack open SWTs and map them into principles for use inside Data services.<\/p>\n<p>Lets just take the code we wrote in parts <a href=\"http:\/\/blogs.msdn.com\/b\/astoriateam\/archive\/2010\/07\/19\/odata-and-authentication-part-4-server-side-hooks.aspx\">4<\/a> &amp; <a href=\"http:\/\/blogs.msdn.com\/b\/astoriateam\/archive\/2010\/07\/19\/odata-and-authentication-part-5-custom-httpmodules.aspx\">5<\/a> and rework it for OAuth WRAP, firstly by creating a OAuthWrapHttpModule that looks like this:<\/p>\n<p><font face=\"Courier New\">public class OAuthWrapAuthenticationModule : IHttpModule      <br \/>{       <br \/>&#160;&#160;&#160; public void Init(HttpApplication context)       <br \/>&#160;&#160;&#160; {       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; context.AuthenticateRequest +=       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; new EventHandler(context_AuthenticateRequest);       <br \/>&#160;&#160;&#160; }       <br \/>&#160;&#160;&#160; void context_AuthenticateRequest(object sender, EventArgs e)       <br \/>&#160;&#160;&#160; {       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; HttpApplication application = (HttpApplication)sender;       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (!OAuthWrapAuthenticationProvider.Authenticate(application.Context))       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Unauthenticated(application);       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; } <\/font><\/p>\n<p><font face=\"Courier New\">&#160;&#160;&#160; }      <br \/>&#160;&#160;&#160; void Unauthenticated(HttpApplication application)       <br \/>&#160;&#160;&#160; {       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; \/\/ you could ignore this and rely on authorization logic to       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; \/\/ intercept requests etc. But in this example we fail early.       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; application.Context.Response.Status = &quot;401 Unauthorized&quot;;       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; application.Context.Response.StatusCode = 401;       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; application.Context.Response.AddHeader(&quot;WWW-Authenticate&quot;, &quot;WRAP&quot;);       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; application.CompleteRequest();       <br \/>&#160;&#160;&#160; }       <br \/>&#160;&#160;&#160; public void Dispose() { }       <br \/>}<\/font><\/p>\n<p>As you can see this relies on an OAuthWrapAuthenticationProvider which looks like this:<\/p>\n<p><font face=\"Courier New\">public class OAuthWrapAuthenticationProvider      <br \/>{       <br \/>&#160;&#160;&#160; static TokenValidator _validator = CreateValidator();       <\/p>\n<p>&#160;&#160;&#160; static TokenValidator CreateValidator()       <br \/>&#160;&#160;&#160; {       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; string acsHostname =       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ConfigurationManager.AppSettings[&quot;acsHostname&quot;];       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; string serviceNamespace =       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ConfigurationManager.AppSettings[&quot;serviceNamespace&quot;];       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; string trustedAudience =       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ConfigurationManager.AppSettings[&quot;trustedAudience&quot;];       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; string trustedSigningKey =&#160; <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ConfigurationManager.AppSettings[&quot;trustedSigningKey&quot;];       <\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160; return new TokenValidator(       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; acsHostname,       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; serviceNamespace,       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; trustedAudience,       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; trustedSigningKey       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; );       <br \/>&#160;&#160;&#160; }       <br \/>&#160;&#160;&#160; public static TokenValidator Validator       <br \/>&#160;&#160;&#160; {       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; get { return _validator; }       <br \/>&#160;&#160;&#160; }<\/font><\/p>\n<p><font face=\"Courier New\">&#160;&#160;&#160; public static bool Authenticate(HttpContext context)      <br \/>&#160;&#160;&#160; {       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (!HttpContext.Current.Request.IsSecureConnection)&#160; <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return false; <\/font><\/p>\n<p><font face=\"Courier New\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (!HttpContext.Current.Request.Headers.AllKeys.Contains(&quot;Authorization&quot;))      <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return false; <\/font><\/p>\n<p><font face=\"Courier New\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; string authHeader = HttpContext.Current.Request.Headers[&quot;Authorization&quot;]; <\/font><\/p>\n<p><font face=\"Courier New\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; \/\/ check that it starts with &#8216;WRAP&#8217;      <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (!authHeader.StartsWith(&quot;WRAP &quot;))       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return false;       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; }       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; \/\/ the header should be in the form &#8216;WRAP access_token=&quot;{token}&quot;&#8217;       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; \/\/ so lets get the {token}       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; string[] nameValuePair = authHeader       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; .Substring(&quot;WRAP &quot;.Length)       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; .Split(new char[] { &#8216;=&#8217; }, 2); <\/font><\/p>\n<p><font face=\"Courier New\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (nameValuePair.Length != 2 ||      <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; nameValuePair[0] != &quot;access_token&quot; ||       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; !nameValuePair[1].StartsWith(&quot;\\&quot;&quot;) ||       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; !nameValuePair[1].EndsWith(&quot;\\&quot;&quot;))       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; {       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return false;       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; } <\/font><\/p>\n<p><font face=\"Courier New\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; \/\/ trim off the leading and trailing double-quotes      <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; string token = nameValuePair[1].Substring(1, nameValuePair[1].Length &#8211; 2); <\/font><\/p>\n<p><font face=\"Courier New\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (!Validator.Validate(token))      <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return false; <\/font><\/p>\n<p><font face=\"Courier New\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; var roles = GetRoles(Validator.GetNameValues(token)); <\/font><\/p>\n<p><font face=\"Courier New\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; HttpContext.Current.User = new GenericPrincipal(      <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; new GenericIdentity(&quot;partner&quot;),       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; roles       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; );&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; return true;       <br \/>&#160;&#160;&#160; }       <br \/>&#160;&#160;&#160; static string[] GetRoles(Dictionary&lt;string, string&gt; nameValues)       <br \/>&#160;&#160;&#160; {       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (!nameValues.ContainsKey(&quot;Roles&quot;))       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return new string[] { };       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; else       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return nameValues[&quot;Roles&quot;].Split(&#8216;,&#8217;);       <br \/>&#160;&#160;&#160; }       <br \/>}<\/font><\/p>\n<p>As you can see the Authenticate method does a number of things:<\/p>\n<ul>\n<li>Verifies we are using HTTPS because it would be insecure to pass SWT tokens around over straight HTTP. <\/li>\n<li>Verifies that the authorization header exists and it is a WRAP header. <\/li>\n<li>Extracts the SWT token from the authorization header. <\/li>\n<li>Asks a TokenValidator to validate the token. More on this in a second. <\/li>\n<li>Then extracts the Roles claims from the token (it assumes there is a Roles claim that contains a &#8216;,&#8217; delimited list of roles). <\/li>\n<li>Finally if every check passes it constructs a GenericPrincipal, with a hard coded identity set to \u2018partner\u2019, and the list of roles found in the SWT and assigns it to HttpContext.Current.User. <\/li>\n<\/ul>\n<p>In our example the identity itself is hard coded because currently our ACS rules don\u2019t make any claims about the username, it just has role claims. Clearly though if we added more ACS rules you could include a username claim too.<\/p>\n<p>The TokenValidator used in the code above is lifted from Windows Azure AppFabric v1.0 C# samples, which you can find <a href=\"https:\/\/www.microsoft.com\/downloads\/details.aspx?FamilyID=39856a03-1490-4283-908f-c8bf0bfad8a5&amp;displaylang=en\">here<\/a>. If you download and unzip these samples you\u2019ll find the TokenValidator here:<\/p>\n<p><font size=\"2\" face=\"Lucida Console\"><strong>~\\AccessControl\\GettingStarted\\ASPNETStringReverser\\CS35\\Service\\App_Code\\TokenValidator.cs<\/strong><\/font><\/p>\n<p> <font size=\"2\" face=\"Lucida Console\"><\/font>  <\/p>\n<p>Our create CreateValidator() method creates a shared instance of the TokenValidator, and as you can see we are pulling these settings from web.config:<\/p>\n<p><font face=\"Courier New\">&lt;configuration&gt;      <br \/>&#160; \u2026       <br \/>&#160; &lt;appSettings&gt;       <br \/>&#160;&#160;&#160;&#160; &lt;add key=&quot;acsHostName&quot; value=&quot;accesscontrol.windows.net&quot;\/&gt;       <br \/>&#160;&#160;&#160;&#160; &lt;add key=&quot;serviceNamespace&quot; value=&quot;{your namespace goes here}&quot;\/&gt;       <br \/>&#160;&#160;&#160;&#160; &lt;add key=&quot;trustedAudience&quot; value=&quot;<\/font><a href=\"http:\/\/odata.mydomain.com&quot;\/\"><font face=\"Courier New\">http:\/\/odata.mydomain.com&quot;\/<\/font><\/a><font face=\"Courier New\">&gt;      <br \/>&#160;&#160;&#160;&#160; &lt;add key=&quot;trustedSigningKey&quot; value=&quot;{your token policy key goes here}&gt;       <br \/>&#160;&#160; &lt;\/appSettings&gt;       <br \/>&#160;&#160; \u2026       <br \/>&lt;\/configuration&gt;<\/font><\/p>\n<p>The most interesting one is the trustedSigningKey.&#160; <\/p>\n<p>This is a key shared between ACS and the resource server (in our case our HttpModule). It is the key from the token policy we created in step 2.<\/p>\n<p>The ACS server uses the token policy key to create a hash of the claims (or HMACSHA256) which gets appended to the claims to complete the SWT. Then to verify that the SWT and its claims are valid the resource server simply re-computes the hash and compares.<\/p>\n<p>Now that we\u2019ve got our module we simply need to register it with IIS via the web.config like this:<\/p>\n<p><font face=\"Courier New\">&lt;configuration&gt;      <br \/>&#160; \u2026       <br \/>&#160; &lt;system.webServer&gt;       <br \/>&#160;&#160;&#160;&#160; &lt;modules&gt;       <br \/>&#160;&#160;&#160;&#160;&#160;&#160; &lt;add name=&quot;OAuthWrapAuthenticationModule&quot;       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; type=&quot;SimpleService.OAuthWrapAuthenticationModule&quot;\/&gt;       <br \/>&#160;&#160;&#160;&#160; &lt;\/modules&gt;       <br \/>&#160;&#160; &lt;\/system.webServer&gt;       <br \/>\u2026       <br \/>&lt;\/configuration&gt;<\/font><\/p>\n<\/p>\n<h3>Step 4 \u2013 Creating an OData Service<\/h3>\n<p>Next we need to add (if you haven\u2019t already) an OData Service.<\/p>\n<p>There are <a href=\"http:\/\/blogs.msdn.com\/b\/alexj\/archive\/2010\/01\/07\/data-service-providers-getting-started.aspx\">lots of ways<\/a> to create an OData Service using WCF Data Services. But by far the easiest way to create a read\/write service is using the <a href=\"http:\/\/blogs.msdn.com\/b\/astoriateam\/archive\/2009\/12\/17\/getting-started-with-the-data-services-update-for-net-3-5-sp1-part-1.aspx\">Entity Framework like this<\/a>. <\/p>\n<p>Now because we\u2019ve converted the OAuth WRAP SWT into a GenericPrincipal by the time requests hit our Data Service all the authorization techniques we already know using QueryInterceptors and ChangeIntercepts are still applicable. <\/p>\n<p>So you could easily write code like this:<\/p>\n<p><font face=\"Courier New\">[QueryInterceptor(&quot;Orders&quot;)]      <br \/>public Expression&lt;Func&lt;Order, bool&gt;&gt; OrdersFilter()       <br \/>{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br \/>&#160;&#160;&#160; if (!HttpContext.Current.Request.IsAuthenticated)       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; return (Order o) =&gt; false;       <br \/>&#160;&#160;&#160; <\/font><font face=\"Courier New\">var user = HttpContext.Current.User;      <br \/>&#160;&#160;&#160; if (user.IsInRole(&quot;User&quot;))       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; return (Order o) =&gt; true;       <br \/>&#160;&#160;&#160; else       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; return (Order o) =&gt; false;&#160; <br \/><\/font><font face=\"Courier New\">}<\/font><\/p>\n<p>And of course you can rework the HttpModule and interceptors as needed if your claims get more involved.<\/p>\n<h3>Step 5 \u2013 Acquiring and using a SWT Token<\/h3>\n<p>The final step is to write a client that will send a valid SWT with each OData request.<\/p>\n<p>In <a href=\"http:\/\/blogs.msdn.com\/b\/astoriateam\/archive\/2010\/05\/24\/odata-and-authentication-part-3-clientside-hooks.aspx\">part 3<\/a> we explored the available client-side hooks. So we know that we can hook up to the DataServiceContext.SendingRequest like this:<\/p>\n<p><font face=\"Courier New\">ctx.SendingRequest +=new EventHandler&lt;SendingRequestEventArgs&gt;(OnSendingRequest);<\/font><\/p>\n<p>And in our event hander we can add headers to the outgoing request. For OAuth WRAP we need to add a authorization header in the form:<\/p>\n<p><font size=\"2\" face=\"Lucida Console\"><strong>Authorization:WRAP access_token=&quot;{YOUR SWT GOES HERE}&quot;<\/strong><\/font><\/p>\n<p><font color=\"#808080\"><strong>NOTE:<\/strong> the double quotes (&quot;) are actually part of the format, but the curly bracked ({) are not. See the string.Format call below if you have any doubts.<\/font><\/p>\n<p>So our OnSendingRequest event handler looks like this:<\/p>\n<p><font face=\"Courier New\">static void OnSendingRequest(object sender, SendingRequestEventArgs e)      <br \/>{       <br \/>&#160;&#160;&#160; e.RequestHeaders.Add(       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; &quot;Authorization&quot;,       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; string.Format(&quot;WRAP access_token=\\&quot;{0}\\&quot;&quot;, GetToken())       <br \/>&#160;&#160;&#160; );       <br \/>}<\/font><\/p>\n<p>As you can see this uses GetToken() to acquire the actual SWT:<\/p>\n<p><font face=\"Courier New\">static string GetToken()      <br \/>{       <br \/>&#160;&#160;&#160; if (_token == null){       <br \/>&#160;&#160;&#160;&#160;&#160;&#160; WebClient client = new WebClient();       <br \/>&#160;&#160;&#160;&#160;&#160;&#160; client.BaseAddress =       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &quot;<\/font><font face=\"Courier New\">https:\/\/{your-namespace-goes-here}.accesscontrol.windows.net&quot;;<\/font>     <br \/><font face=\"Courier New\">&#160;&#160;&#160;&#160;&#160;&#160; NameValueCollection values = new NameValueCollection();      <br \/>&#160;&#160;&#160;&#160;&#160;&#160; values.Add(&quot;wrap_name&quot;, &quot;partner&quot;);       <br \/>&#160;&#160;&#160;&#160;&#160;&#160; values.Add(&quot;wrap_password&quot;, &quot;{Issuer Key goes here}&quot;);       <br \/>&#160;&#160;&#160;&#160;&#160;&#160; values.Add(&quot;wrap_scope&quot;, &quot;<\/font><font face=\"Courier New\">http:\/\/odata.mydomain.com&quot;);<\/font>     <br \/><font face=\"Courier New\">&#160;&#160;&#160;&#160;&#160;&#160; byte[] responseBytes = client.UploadValues(&quot;WRAPv0.9&quot;, &quot;POST&quot;, values);      <br \/>&#160;&#160;&#160;&#160;&#160;&#160; string response = Encoding.UTF8.GetString(responseBytes);       <br \/>&#160;&#160;&#160;&#160;&#160;&#160; string token = response.Split(&#8216;&amp;&#8217;)       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; .Single(value =&gt; value.StartsWith(&quot;wrap_access_token=&quot;))       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; .Split(&#8216;=&#8217;)[1]; <\/font><\/p>\n<p><font face=\"Courier New\">&#160;&#160;&#160;&#160;&#160; _token = HttpUtility.UrlDecode(token);&#160; <br \/>&#160;&#160; }       <br \/>&#160;&#160; return _token;       <br \/>}       <br \/>static string _token = null; <\/font><\/p>\n<p>As you can see we acquire the SWT once (by demonstrating knowledge of the Issuer key)and assuming that is successful we cache it for later reuse. <\/p>\n<p>Finally if we issue queries like say this:<\/p>\n<p><font face=\"Courier New\">try      <br \/>{       <br \/>&#160;&#160;&#160; foreach (Order order in ctx.Orders)       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; Console.WriteLine(order.Number);       <br \/>}       <br \/>catch (DataServiceQueryException ex)       <br \/>{       <br \/>&#160;&#160;&#160; \/\/var scheme = ex.Response.Headers[&quot;WWW-Authenticate&quot;];       <br \/>&#160;&#160;&#160; var code = ex.Response.StatusCode;       <br \/>&#160;&#160;&#160; if (code == 401)       <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160; _token = null;       <br \/>}<\/font><\/p>\n<p>And our token has expired, as it will after 60 minutes, an exception will occur and we can just null out the cached SWT and any retries will force our code to acquire a new SWT.&#160; <\/p>\n<h3>Summary<\/h3>\n<p>In this post we\u2019ve come a long way. We\u2019ve now got a simple OData and OAuth WRAP authentication scenario working end to end. <\/p>\n<p>It is a good foundation to build upon. But there are a few things we can do to make it better.<\/p>\n<p>We could:<\/p>\n<ul>\n<li>Configure our ACS to federate identities across domains, and configure our client code to do SWT exchange to go from one domain to another. <\/li>\n<li>Create an expiring cache of Principals so that we don\u2019t need to re-validate everytime a new request is received. <\/li>\n<li>Upgrade our Principal object so it can handle more general claims rather than just User\/Roles. <\/li>\n<\/ul>\n<p>We\u2019ll address these issues in Part 9.<\/p>\n<p><strong><a href=\"https:\/\/twitter.com\/adjames\">Alex James<\/a>       <br \/><\/strong>Program Manager     <br \/>Microsoft<\/p>\n","protected":false},"excerpt":{"rendered":"<p>OAuth WRAP is a claims based authentication protocol supported by the AppFabric Access Control (ACS) which is part of Windows Azure. But most importantly it is REST (and thus OData) friendly too. The idea is that you authenticate against an ACS server and acquire a Simple Web Token or SWT \u2013 which contains signed claims [&hellip;]<\/p>\n","protected":false},"author":512,"featured_media":3253,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[15,33,39,47,48],"class_list":["post-1163","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-odata","tag-authentication","tag-federation","tag-httpmodule","tag-oauth-wrap","tag-odata"],"acf":[],"blog_post_summary":"<p>OAuth WRAP is a claims based authentication protocol supported by the AppFabric Access Control (ACS) which is part of Windows Azure. But most importantly it is REST (and thus OData) friendly too. The idea is that you authenticate against an ACS server and acquire a Simple Web Token or SWT \u2013 which contains signed claims [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/1163","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/users\/512"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/comments?post=1163"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/1163\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media\/3253"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media?parent=1163"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/categories?post=1163"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/tags?post=1163"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}