{"id":3179,"date":"2015-01-15T12:14:50","date_gmt":"2015-01-15T20:14:50","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=3179"},"modified":"2015-01-15T12:20:05","modified_gmt":"2015-01-15T20:20:05","slug":"adal-2-x-servicing-release-introduces-support-for-windows-phone-8-1-silverlight-apps","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2015\/01\/15\/adal-2-x-servicing-release-introduces-support-for-windows-phone-8-1-silverlight-apps\/","title":{"rendered":"ADAL 2.X Servicing Release Introduces Support for Windows Phone 8.1 Silverlight Apps"},"content":{"rendered":"<p>If you head to the NuGet gallery you\u2019ll find that <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.IdentityModel.Clients.ActiveDirectory\/2.14.201151115\">we just released an update to our ADAL .NET package<\/a>.<\/p>\n<p>This servicing update (we go from v2.1<strong>3<\/strong>.112191810 to v2.1<strong>4<\/strong>.201151115) fixes various bugs. The one you\u2019re most likely to have stumbled upon is one issue with Windows Store apps publication \u2013 which is solved in the release.<\/p>\n<p>This release also introduces a new feature: the ability to use ADAL in Windows Phone 8.1 Silverlight applications. Until now, <a href=\"https:\/\/www.cloudidentity.com\/blog\/2014\/06\/16\/adal-for-windows-phone-8-1-deep-dive\/\">ADAL only worked with Windows Phone 8.1 Store applications<\/a>.<\/p>\n<p>SL apps support was a feature you have been very vocal about: for example, see the twitter exchange I had with <a href=\"https:\/\/twitter.com\/gcaughey\">Ginny<\/a> back in June.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/01\/image.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/01\/image_thumb.png\" alt=\"image\" width=\"632\" height=\"830\" border=\"0\" \/><\/a><\/p>\n<p>In the last few months we heard more and more of that feedback \u2013 from internal and external customers. Although there are ways of getting tokens from those kind of apps (the code delta is non zero but pretty small, it\u2019s more of a matter of creating an assembly for it rather than a winmd), we found ourselves spending cycles to help people understand their options \u2013 and we realized that it would have been more efficient for everybody if we would simply bite the bullet and include Windows Phone\u00a0 8.1 Silverlight apps as a new target platform in our official NuGet. So, that\u2019s exactly what we did <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/01\/wlEmoticon-smile.png\" alt=\"Smile\" \/> and given that the programming surface did not change, we were able to do this in a servicing release.<\/p>\n<h2>Using ADAL in a Windows Phone 8.1 Silverlight app<\/h2>\n<p>Using ADAL in a winphone 8.1 SL app is not very different from doing so in a <a href=\"https:\/\/github.com\/AzureADSamples\/NativeClient-WindowsPhone8.1\">winphone Windows Store one<\/a>, which is why we are not releasing a new sample for it at this time. If you think you need one please let us know, though!<\/p>\n<p>The main difference lies in the way in which SL apps deal with the continuation model (behind the scenes we use the WebAuthenticationBroker, which is why this only works with 8.1 and we still need to handle continuation).<br \/>\nThe application events cycle is slightly different, which influences where you need to inject the continuation handling code.<\/p>\n<p>Here there\u2019s a quick walkthrough to show how to see ADAL in action in your Windows Phone 8.1 SL app.<\/p>\n<ul>\n<li>Start from a blank Windows Phone 8.1 Silverlight app.<\/li>\n<li>Add a reference to the latest ADAL: at this time you can do so via the following line in the package manager console.<\/li>\n<\/ul>\n<p><strong><span style=\"font-family: Consolas;\">Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory -Version 2.14.201151115<\/span><\/strong><\/p>\n<ul>\n<li>Add some basic ADAL code: here I am using as is the same code I used for the <a href=\"https:\/\/www.cloudidentity.com\/blog\/2014\/08\/28\/use-adal-to-connect-your-universal-apps-to-azure-ad-or-adfs\/\">Universal Apps post<\/a>, where I make a simple Directory Graph call from a lone button on the default page. Note that you can use the exact same code, as the client is multitenant and will work with any directory tenant.<\/li>\n<\/ul>\n<pre class=\"csharpcode\"><span class=\"kwrd\">using<\/span> System;\r\n<span class=\"kwrd\">using<\/span> System.Windows;\r\n<span class=\"kwrd\">using<\/span> System.Windows.Navigation;\r\n<span class=\"kwrd\">using<\/span> Microsoft.Phone.Controls;\r\n<span class=\"kwrd\">using<\/span> Microsoft.IdentityModel.Clients.ActiveDirectory;\r\n<span class=\"kwrd\">using<\/span> Windows.ApplicationModel.Activation;\r\n\r\n<span class=\"kwrd\">namespace<\/span> WPSL_App1\r\n{\r\n    <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">partial<\/span> <span class=\"kwrd\">class<\/span> MainPage : PhoneApplicationPage, IWebAuthenticationContinuable\r\n    {\r\n        AuthenticationContext ac = <span class=\"kwrd\">null<\/span>;\r\n        <span class=\"rem\">\/\/ Constructor<\/span>\r\n        <span class=\"kwrd\">public<\/span> MainPage()\r\n        {\r\n            InitializeComponent();            \r\n        }\r\n\r\n        <span class=\"kwrd\">protected<\/span> <span class=\"kwrd\">override<\/span> async <span class=\"kwrd\">void<\/span> OnNavigatedTo(NavigationEventArgs e)\r\n        {\r\n            <span class=\"kwrd\">base<\/span>.OnNavigatedTo(e);\r\n            ac = await AuthenticationContext.CreateAsync(<span class=\"str\">\"https:\/\/login.windows.net\/common\"<\/span>);        \r\n        }\r\n\r\n        <span class=\"kwrd\">private<\/span> async <span class=\"kwrd\">void<\/span> btnCallGraph_Click(<span class=\"kwrd\">object<\/span> sender, RoutedEventArgs e)\r\n        {\r\n            AuthenticationResult result =\r\n                 await ac.AcquireTokenSilentAsync(<span class=\"str\">\"https:\/\/graph.windows.net\"<\/span>,\r\n                                                  <span class=\"str\">\"e11a0451-ac9d-4c89-afd8-d2fa3322ef68\"<\/span>);\r\n            <span class=\"kwrd\">if<\/span> (result != <span class=\"kwrd\">null<\/span> &amp;&amp; result.Status == AuthenticationStatus.Success)\r\n            {\r\n                ShowGreeting(result);\r\n            }\r\n            <span class=\"kwrd\">else<\/span>\r\n            {\r\n                ac.AcquireTokenAndContinue(<span class=\"str\">\"https:\/\/graph.windows.net\"<\/span>,\r\n                                           <span class=\"str\">\"e11a0451-ac9d-4c89-afd8-d2fa3322ef68\"<\/span>,\r\n                                           <span class=\"kwrd\">new<\/span> Uri(<span class=\"str\">\"http:\/\/li\"<\/span>), ShowGreeting);\r\n            } \r\n        }\r\n        <span class=\"kwrd\">public<\/span> async <span class=\"kwrd\">void<\/span> ShowGreeting(AuthenticationResult ar)\r\n        {            \r\n            MessageBox.Show(<span class=\"str\">\"hello, Mr\/Ms \"<\/span> + ar.UserInfo.FamilyName);            \r\n        }\r\n        <span class=\"kwrd\">public<\/span> async <span class=\"kwrd\">void<\/span> ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args)\r\n        {\r\n            await ac.ContinueAcquireTokenAsync(args);\r\n        } \r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>Same old, same old. Quick comments:<\/p>\n<ul>\n<li>The page implements the usual IWebAuthenticationContinuable interface to handle continuation, via the ContinueWebAuthentication method toward the end of the class declaration<\/li>\n<li>The init happens in OnNavigated given that we want an async method.<\/li>\n<li>btn_CallGraph_CLick follows the usual pattern: if we have a token in our belly we get it silently and use it, otherwise we start the interactive token acquisition process and book the work to do (the ShowGreeting method) after that\u2019s done<\/li>\n<\/ul>\n<p>The slightly different part is in App.xaml.cs. Here there are the relevant parts:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">namespace<\/span> WPSL_App1\r\n{\r\n    <span class=\"kwrd\">interface<\/span> IWebAuthenticationContinuable\r\n    {\r\n        <span class=\"rem\">\/\/\/ &lt;summary&gt;<\/span>\r\n        <span class=\"rem\">\/\/\/ This method is invoked when the web authentication broker returns<\/span>\r\n        <span class=\"rem\">\/\/\/ with the authentication result<\/span>\r\n        <span class=\"rem\">\/\/\/ &lt;\/summary&gt;<\/span>\r\n        <span class=\"rem\">\/\/\/ &lt;param name=\"args\"&gt;Activated event args object that contains returned authentication token&lt;\/param&gt;<\/span>\r\n        <span class=\"kwrd\">void<\/span> ContinueWebAuthentication(WebAuthenticationBrokerContinuationEventArgs args);\r\n    }\r\n    <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">partial<\/span> <span class=\"kwrd\">class<\/span> App : Application\r\n    {\r\n        <span class=\"rem\">\/\/\/ ... stuff ...<\/span>\r\n        <span class=\"kwrd\">private<\/span> <span class=\"kwrd\">void<\/span> Application_ContractActivated(<span class=\"kwrd\">object<\/span> sender, Windows.ApplicationModel.Activation.IActivatedEventArgs e)\r\n        {\r\n            var webAuthenticationBrokerContinuationEventArgs = e <span class=\"kwrd\">as<\/span> WebAuthenticationBrokerContinuationEventArgs;\r\n            <span class=\"kwrd\">if<\/span> (webAuthenticationBrokerContinuationEventArgs != <span class=\"kwrd\">null<\/span>)\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(webAuthenticationBrokerContinuationEventArgs);\r\n                }\r\n            }\r\n        }\r\n    \/\/\/ ... more stuff<\/pre>\n<p>&nbsp;<\/p>\n<ul>\n<li>At the top I declare the IWebAuthenticationContinuable interface. It can go anywhere, really. I just added it here \u2018cause I am lazy and sloppy.<\/li>\n<li>The method Application_ContractActivated is the functional equivalent of OnActivated in the Windows Store version of the app (see <a href=\"https:\/\/github.com\/AzureADSamples\/NativeClient-WindowsPhone8.1\/blob\/master\/TodoListClient\/App.xaml.cs\">here<\/a>) hence that\u2019s where we handle continuation<\/li>\n<\/ul>\n<p>That\u2019s really all you need! Let\u2019s give it a spin: hit F5.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/01\/image1.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/01\/image_thumb1.png\" alt=\"image\" width=\"556\" height=\"995\" border=\"0\" \/><\/a><\/p>\n<p>Click on the big button. You\u2019ll see the familiar sign in experience from AAD.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/01\/image2.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/01\/image_thumb2.png\" alt=\"image\" width=\"555\" height=\"1002\" border=\"0\" \/><\/a><\/p>\n<p>Sign in.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/01\/image3.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/01\/image_thumb3.png\" alt=\"image\" width=\"557\" height=\"1000\" border=\"0\" \/><\/a><\/p>\n<p>You\u2019ll get the usual consent page. Accept, and\u2026<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/01\/image4.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/01\/image_thumb4.png\" alt=\"image\" width=\"566\" height=\"1014\" border=\"0\" \/><\/a><\/p>\n<p>\u2026voila\u2019! I securely accessed my previous corporate data from my Windows Phone 8.1 Silverlight app, with just few lines of code.<\/p>\n<h2><\/h2>\n<h2>Giving Feedback Works!!!<\/h2>\n<p>As this new feature demonstrates, we do try to listen and act on your feedback to the best of our abilities. Silverlight support was not in the cards, but your relentless requests helped us to better understand the impact of not supporting it.<\/p>\n<p>I hope this will inspire to be vocal about our libraries and services, because well\u2026 it works! <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/01\/wlEmoticon-smile.png\" alt=\"Smile\" \/><br \/>\nIn fact, if you want to be even more directly involved, I\u2019ll take this opportunity to remind you that <a href=\"https:\/\/www.cloudidentity.com\/blog\/2014\/07\/07\/adal-for-netwindows-storewindows-phone-is-now-open-source\/\">ADAL is open source<\/a> and with it <a href=\"https:\/\/github.com\/AzureAD\">all of our libraries<\/a>. Feel free to file issues, give us feedback and contribute\u2026 we *love* it when you do.<\/p>\n<p>Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you head to the NuGet gallery you\u2019ll find that we just released an update to our ADAL .NET package. This servicing update (we go from v2.13.112191810 to v2.14.201151115) fixes various bugs. The one you\u2019re most likely to have stumbled upon is one issue with Windows Store apps publication \u2013 which is solved&#8230;<\/p>\n","protected":false},"author":1,"featured_media":3174,"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-3179","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\/3179","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=3179"}],"version-history":[{"count":2,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/3179\/revisions"}],"predecessor-version":[{"id":3182,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/3179\/revisions\/3182"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/3174"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=3179"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=3179"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=3179"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}