{"id":2763,"date":"2014-04-16T00:34:02","date_gmt":"2014-04-16T07:34:02","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=2763"},"modified":"2014-04-22T07:53:20","modified_gmt":"2014-04-22T14:53:20","slug":"calling-office365-api-from-a-windows-phone-8-1-app","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2014\/04\/16\/calling-office365-api-from-a-windows-phone-8-1-app\/","title":{"rendered":"Calling Office365 API from a Windows Phone 8.1 App"},"content":{"rendered":"<p>Did you install the preview of Windows Phone 8.1? I sure did, and it\u2019s awesome!<\/p>\n<p>Windows Phone 8.1 introduces a great new feature, which was until recently only available on Windows 8.x: the <strong>WebAuthenticationBroker<\/strong> (WAB for short from now on). <a href=\"https:\/\/www.cloudidentity.com\/blog\/2014\/02\/26\/a-developer-preview-of-the-active-directory-authentication-library-adal-v2\/\">ADAL for Windows Store<\/a> leverages the WAB for all of its authentication UI rendering needs, and that saved us a tremendous amount of work in respect to other platforms (such as <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/09\/12\/active-directory-authentication-library-adal-v1-for-net-general-availability\/\">classic .NET<\/a>) on which we had to handle the UX (dialog, HTML rendering, navigation, etc) on our own.<\/p>\n<p>To give you a practical example of that, and to amuse myself during this 9.5 hours Seattle-Paris flight I am sitting on, I am going to show you how to use the WAB on Windows Phone 8.1 to obtain a token from Azure Active Directory: you\u2019ll see that the savings in respect to <a href=\"https:\/\/www.cloudidentity.com\/blog\/2014\/02\/16\/a-sample-windows-phone-8-app-getting-tokens-from-windows-azure-ad-and-adfs\/\">the older Windows Phone sample<\/a> (where I did have to handle the UX myself) are significant. If you prefer to watch a video, rather than putting up with my logorrhea, check out <a href=\"http:\/\/channel9.msdn.com\/Events\/Build\/2014\/3-598\">the recording of the session on native clients I delivered at \/\/BUILD<\/a> just 10 days ago: the very first demo I show is precisely the same app, though I cleaned up the code a bit since then.<\/p>\n<h2>The WebAuthenticationBroker and the Continuation Pattern<\/h2>\n<p>The WAB on Windows Phone 8.1 differs from its older Windows 8.x sibling in more than the size of its rendering surface. The one difference you can\u2019t ignore (and the reason for which you can\u2019t just reuse ADAL for Windows Store on the phone) lies in the programming model it exposes. Note: the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windowsphone\/develop\/dn596094.aspx\">WAB coverage on MSDN is excellent<\/a>, and I recommend you refer to it rather than relying on what I write here (usual disclaimers apply). Here I\u2019ll just give a barebone explanation covering the essential for getting the WAB to work with AAD.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/04\/image.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-width: 0px;\" title=\"image\" alt=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/04\/image_thumb.png\" width=\"800\" height=\"348\" border=\"0\" \/><\/a><\/p>\n<p>Referring to the diagram above. The idea is that (1) whenever you call the phone WAB from your code, your app gets suspended and the WAB \u201capp\u201d takes over the foreground spot. The user goes through (2) whatever experience the identity provider serves; once the authentication flow comes to an end, (3) the WAB returns control to your app and disappears.<br \/>\nHere that\u2019s where things get interesting. For your app, this is just another activation: you need to add some logic to detect that this activation was caused by the WAB returning from an authentication, and ensure that the values returned by the WAB are routed to the code that needs to resume the authentication logic and process them.<br \/>\nThe idea is that you need in your app an object which implements a well-known interface (IWebAuthenticationContinuable), which includes a method (ContinueWebAuthentication) meant to be used as the re-entry point at reactivation time. In the diagram above it is the page itself that implements IWebAuthenticationContinuable; the OnActivated handler (4) calls the method directly, passing the activation event arguments which will be materialized in ContinueWebAuthentication as WebAuthenticationBrokenContinuationArgs. Those arguments will contain the values you typically expect from the WAB, such as the authorization code produced by an OAuth code grant flow.<\/p>\n<p>This is a common pattern in Windows Phone 8.1: it goes under the name \u201cAndContinue\u201d, from the structure of the primitives used. It is applied whenever a \u201csystem\u201d operation (such as the WAB, but also file picking) might end up requiring a lot of resources, making it hard for an app on a low power device to keep active in memory both the app and the process handling the requested task. Once again, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windowsphone\/develop\/dn631755.aspx\">MSDN provides great coverage for this<\/a>.<\/p>\n<h2>The Sample<\/h2>\n<p>Too abstract for your taste? Presto, let\u2019s look at some code. Here I will skip all of the client app provisioning in AAD, as we\u2019ve covered that task many times. If you want a refresher, just head to one of the samples on GitHub and refer to the instructions there. &lt;LINK&gt;<\/p>\n<p>As mentioned in the title, we want an app that will invoke an Office365 API. We won\u2019t do anything fancy with the results, as I just want to show you how to obtain and use a suitable token. If you want to get a trial of Office 365, check out this link &lt;LINK&gt;. Also, if you don\u2019t want to set up a subscription you can easily repurpose this sample to call any other API (such as the Graph or your own).<\/p>\n<p>Ready? Go! Create a new blank Windows Phone 8.1 app. Make sure to pick up the store flavor. Add a button for triggering the API call.<\/p>\n<p>In your main page, add the declaration for your IWebAuthenticationContinuable. Note that you can decide to return a value, if you so choose.<\/p>\n<pre class=\"csharpcode\"> <span class=\"kwrd\">interface<\/span> IWebAuthenticationContinuable\r\n{\r\n   <span class=\"kwrd\">void<\/span> ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args);\r\n}<\/pre>\n<style type=\"text\/css\"><!--\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }\n--><\/style>\n<p>&nbsp;<\/p>\n<p>That done, add it to the page declaration as an implemented interface, and add the logic for requesting tokens and using them via the continuation model. We\u2019ll flesh those stubs out in a moment.<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">public<\/span> <span class=\"kwrd\">sealed<\/span> <span class=\"kwrd\">partial<\/span> <span class=\"kwrd\">class<\/span> MainPage : Page, IWebAuthenticationContinuable\r\n{\r\n\r\n<span class=\"rem\">  \/\/...<\/span>\r\n\r\n<span class=\"kwrd\">   private<\/span> <span class=\"kwrd\">void<\/span> btnInvoke_Click(<span class=\"kwrd\">object<\/span> sender, RoutedEventArgs e)\r\n   {\r\n       RequestCode();          \r\n   }\r\n\r\n<span class=\"kwrd\">   public<\/span> async <span class=\"kwrd\">void<\/span> ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args)\r\n   {\r\n       <span class=\"kwrd\">string<\/span> access_token = await RequestToken(args.WebAuthenticationResult);\r\n       HttpClient httpClient = <span class=\"kwrd\">new<\/span> HttpClient();\r\n       httpClient.DefaultRequestHeaders.Authorization = <span class=\"kwrd\">new<\/span> AuthenticationHeaderValue(<span class=\"str\">\"Bearer\"<\/span>, access_token);\r\n       HttpResponseMessage response = httpClient.GetAsync(<span class=\"str\">\"https:\/\/outlook.office365.com\/EWS\/OData\/Me\/Inbox\/Messages?$filter=HasAttachments eq true&amp;$select=Subject,Sender,DateTimeReceived\"<\/span>).Result\r\n       <span class=\"kwrd\">if<\/span> (response.IsSuccessStatusCode)\r\n       {\r\n         ShowMessage(response.Content.ReadAsStringAsync().Result);\r\n       }\r\n   }\r\n<span class=\"rem\">\/\/...<\/span><\/pre>\n<style type=\"text\/css\"><!--\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }\n--><\/style>\n<p>&nbsp;<\/p>\n<p>The btnInvoke_Click triggers the request for a token, via the call to the yet-to-be-defined method RequestCode(). We know that requesting a code will require user interaction, hence we can expect that the call to AuthenticateAndContinue (hence the app deactivation &amp; switch to the WAB) will take place in there. That explains why there\u2019s nothing else after the call to RequestCode.<\/p>\n<p>The ContinueWebAuthentication method implements the logic we want to run once the execution comes back from the WAB. The first line, calling the yet-to-be-defined RequestToken, takes the results from the WAB and presumably uses it to hit the Token endpoint of the AAD\u2019s authorization server.<\/p>\n<p>The rest of the method is the usual boilerplate logic for calling a REST API protected by the OAuth2 bearer token flow \u2013 still, I cannot help but marvel at the amazing simplicity with which you can now access Office resources. With that simple (and perfectly readable!) string I can obtain a list of al the messages with attachments from my inbox, and even narrow down to which fields I care about <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/04\/wlEmoticon-smile.png\" \/><\/p>\n<p>Let\u2019s take a look at the code of RequestCode and RequestToken.<\/p>\n<pre class=\"csharpcode\"> <span class=\"kwrd\">string<\/span> Authority = <span class=\"str\">\"https:\/\/login.windows.net\/developertenant.onmicrosoft.com\"<\/span>;\r\n <span class=\"kwrd\">string<\/span> Resource = <span class=\"str\">\"https:\/\/outlook.office365.com\/\"<\/span>;\r\n <span class=\"kwrd\">string<\/span> ClientID = <span class=\"str\">\"43ba3c74-34e2-4dde-9a6a-2671b53c181c\"<\/span>;\r\n <span class=\"kwrd\">string<\/span> RedirectUri = <span class=\"str\">\"http:\/\/l\"<\/span>;\r\n\r\n  <span class=\"kwrd\">private<\/span> <span class=\"kwrd\">void<\/span> RequestCode()\r\n     {            \r\n         <span class=\"kwrd\">string<\/span> authURL = <span class=\"kwrd\">string<\/span>.Format(\r\n             <span class=\"str\">\"{0}\/oauth2\/authorize?response_type=code&amp;resource={1}&amp;client_id={2}&amp;redirect_uri={3}\"<\/span>,\r\n             Authority,\r\n             Resource,\r\n             ClientID,\r\n             RedirectUri);            \r\n         WebAuthenticationBroker.AuthenticateAndContinue(<span class=\"kwrd\">new<\/span> Uri(authURL), <span class=\"kwrd\">new<\/span> Uri(RedirectUri), <span class=\"kwrd\">null<\/span>, WebAuthenticationOptions.None);\r\n     }\r\n\r\n     <span class=\"kwrd\">private<\/span> async Task&lt;<span class=\"kwrd\">string<\/span>&gt; RequestToken(WebAuthenticationResult rez)\r\n     {\r\n         <span class=\"kwrd\">if<\/span> (rez.ResponseStatus == WebAuthenticationStatus.Success)\r\n         {\r\n             <span class=\"kwrd\">string<\/span> code = ParseCode(rez.ResponseData);\r\n             HttpClient client = <span class=\"kwrd\">new<\/span> HttpClient();\r\n             HttpRequestMessage request = <span class=\"kwrd\">new<\/span> HttpRequestMessage(HttpMethod.Post, <span class=\"kwrd\">string<\/span>.Format(<span class=\"str\">\"{0}\/oauth2\/token\"<\/span>, Authority));\r\n             <span class=\"kwrd\">string<\/span> tokenreq = <span class=\"kwrd\">string<\/span>.Format(\r\n                     <span class=\"str\">\"grant_type=authorization_code&amp;code={0}&amp;client_id={1}&amp;redirect_uri={2}\"<\/span>,\r\n                     code,ClientID,Uri.EscapeDataString(RedirectUri));\r\n             request.Content = <span class=\"kwrd\">new<\/span> StringContent(tokenreq, Encoding.UTF8, <span class=\"str\">\"application\/x-www-form-urlencoded\"<\/span>);\r\n\r\n             HttpResponseMessage response = await client.SendAsync(request);\r\n             <span class=\"kwrd\">string<\/span> responseString = await response.Content.ReadAsStringAsync();\r\n\r\n             var jResult = JObject.Parse(responseString);\r\n             <span class=\"kwrd\">return<\/span> (<span class=\"kwrd\">string<\/span>)jResult[<span class=\"str\">\"access_token\"<\/span>];\r\n         }\r\n         <span class=\"kwrd\">else<\/span>\r\n         {   \r\n             <span class=\"kwrd\">throw<\/span> <span class=\"kwrd\">new<\/span> Exception(String.Format(<span class=\"str\">\"Something went wrong: {0}\"<\/span>,rez.ResponseErrorDetail.ToString()));\r\n         }            \r\n     }\r\n\r\n     <span class=\"kwrd\">private<\/span> <span class=\"kwrd\">string<\/span> ParseCode(<span class=\"kwrd\">string<\/span> result)\r\n     {\r\n         <span class=\"kwrd\">int<\/span> codeIndex = result.IndexOf(<span class=\"str\">\"code=\"<\/span>, 0) + 5;\r\n         <span class=\"kwrd\">int<\/span> endCodeIndex = result.IndexOf(<span class=\"str\">\"&amp;\"<\/span>, codeIndex);\r\n         <span class=\"rem\">\/\/ Return the access code as a string<\/span>\r\n         <span class=\"kwrd\">return<\/span> result.Substring(codeIndex, endCodeIndex - codeIndex);\r\n     }<\/pre>\n<style type=\"text\/css\"><!--\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }\n--><\/style>\n<p>&nbsp;<\/p>\n<p>This is mostly protocol mechanics, not unlike the equivalent logic in the older Windows Phone samples I discussed on these pages.<\/p>\n<p>RequestCode crafts the request URL for the Authorization endpoint and passes it to the WAB, calling AuthenticateAndContinue. By now you know what will happen; the app will go to sleep, and the WAB will show up \u2013 initialized with the data passed here. MUCH simpler than having to create an in-app auth page and handling navigation by yourself.<\/p>\n<p>RequestToken and its associated utility function ParseCode retrieve the authorization code from the response data returned by the WAB, construct the request for the Token endpoint, hits it, and parses (via JSON.NET, finally available for Windows Phone 8.1! <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/04\/wlEmoticon-smile.png\" \/> for my \/\/BUILD demo I had to use the data contract serializer, bleah) the access token out from AAD\u2019s response.<\/p>\n<p>If you paid attention to the explanation to how the WAB continuation pattern works, you know that there\u2019s still something missing: the dispatching logic that upon (re)activation routes the WAB results to ContinueWebAuthentication. Open the App.xaml.cs file, locate the OnActivated handler and add the following.<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">protected<\/span> async <span class=\"kwrd\">override<\/span> <span class=\"kwrd\">void<\/span> OnActivated(IActivatedEventArgs e)\r\n{\r\n    var rootFrame = Window.Current.Content <span class=\"kwrd\">as<\/span> Frame;\r\n\r\n    var wabPage = rootFrame.Content <span class=\"kwrd\">as<\/span> IWebAuthenticationContinuable;\r\n    <span class=\"kwrd\">if<\/span> (wabPage != <span class=\"kwrd\">null<\/span>)\r\n    {\r\n         wabPage.ContinueWebAuthentication(e <span class=\"kwrd\">as<\/span> WebAuthenticationBrokerContinuationEventArgs);\r\n    }\r\n\r\n    Window.Current.Activate();\r\n}<\/pre>\n<style type=\"text\/css\"><!--\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }\n--><\/style>\n<p>Now, I know that my friends in the Windows Phone 8.1 team will frown super-hard at the above. For starters: to do things properly, you should be prepared to be reactivated by multiple *AndContinue. In general, the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windowsphone\/develop\/dn631755.aspx\">documentation<\/a> provides nice classes (like the ContinuationManager) you can use to handle those flows with more maintainable code than the hack I have put together here. My goal here (and during the \/\/BUILD session) was to clarify the new WAB behavior with the least amount of code. Once that is clear to you, I encourage you to revisit the above and re-implement it using the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windowsphone\/develop\/dn631755.aspx\">proper continuation practices.<\/a><\/p>\n<p>Aaanyway, just to put a bow on this: here there\u2019s what you see when running the app. I landed in Paris and I can finally connect to the cloud <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/04\/wlEmoticon-smile.png\" \/><\/p>\n<p>The first page:<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/04\/1.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"1\" alt=\"1\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/04\/1_thumb.png\" width=\"288\" height=\"480\" border=\"0\" \/><\/a><\/p>\n<p>Pressing the button triggers RequestCode, which in turns calls WebAuthenticationBroker.AuthenticateAndContinue and causes the switch to the WAB:<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/04\/2.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"2\" alt=\"2\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/04\/2_thumb.png\" width=\"288\" height=\"480\" border=\"0\" \/><\/a><\/p>\n<p>Upon successful auth, we get back a token and we successfully call Exchange online:<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/04\/3.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"3\" alt=\"3\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/04\/3_thumb.png\" width=\"288\" height=\"480\" border=\"0\" \/><\/a><\/p>\n<p>Ta-dah! <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-note\" alt=\"Note\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/04\/wlEmoticon-note.png\" \/><\/p>\n<h2>Wrap<\/h2>\n<p>Windows Phone 8.1 is a great platform, and WAB is a wonderful addition that will make us identity people very happy. The continuation model will indeed impose a rearranging of the app flow. We are looking at ways in which we can abstract away some of the details for you, so that you can keep operating with the high level primitives you enjoy in ADAL without (too much) abstraction leakage. Stay tuned!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Did you install the preview of Windows Phone 8.1? I sure did, and it\u2019s awesome! Windows Phone 8.1 introduces a great new feature, which was until recently only available on Windows 8.x: the WebAuthenticationBroker (WAB for short from now on). ADAL for Windows Store leverages the WAB for all of its authentication UI&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2758,"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-2763","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\/2763","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=2763"}],"version-history":[{"count":2,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2763\/revisions"}],"predecessor-version":[{"id":2777,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2763\/revisions\/2777"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/2758"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=2763"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=2763"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=2763"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}