diff --git a/README.md b/README.md
index cd1e21cf7b..c96d554964 100644
--- a/README.md
+++ b/README.md
@@ -543,6 +543,7 @@ For additional Windows samples, see [Windows on GitHub](http://microsoft.github.
diff --git a/Samples/BluetoothLE/cs/Package.appxmanifest b/Samples/BluetoothLE/cs/Package.appxmanifest
index aaaab7a958..d8836efe0f 100644
--- a/Samples/BluetoothLE/cs/Package.appxmanifest
+++ b/Samples/BluetoothLE/cs/Package.appxmanifest
@@ -20,7 +20,7 @@
-
+
diff --git a/Samples/HotspotAuthentication/README.md b/Samples/HotspotAuthentication/README.md
new file mode 100644
index 0000000000..eaf784ef2e
--- /dev/null
+++ b/Samples/HotspotAuthentication/README.md
@@ -0,0 +1,111 @@
+
+
+# Hotspot authentication sample
+
+Shows how to provision and register a hotspot profile and perform either WISPr or custom authentication.
+
+> **Note:** This sample is part of a large collection of UWP feature samples.
+> If you are unfamiliar with Git and GitHub, you can download the entire collection as a
+> [ZIP file](https://github.com/Microsoft/Windows-universal-samples/archive/master.zip), but be
+> sure to unzip everything to access shared dependencies. For more info on working with the ZIP file,
+> the samples collection, and GitHub, see [Get the UWP samples from GitHub](https://aka.ms/ovu2uq).
+> For more samples, see the [Samples portal](https://aka.ms/winsamples) on the Windows Dev Center.
+
+This sample demonstrates the following operations:
+
+- Provision a hotspot profile and register the corresponding background task.
+- Authenticate as a foreground app with default WISPr authentication or custom authentication.
+- Authenticate in a background task
+
+The background task requires that the profile be provisioned and registered.
+The task is triggered once the Wi-Fi is connected to the hotspot as a part of post Wi-Fi connection.
+When a device initially connects, the hotspot usually has a limited connection,
+and post-connection authentication is done by a background task to enable the full Internet connection.
+
+In order to invoke the hotspot authentication flow (background task),
+the access point being connected to must provide a captive portal response
+with WISPr support claimed in the XML blob being returned to the client.
+
+Authentication can be completed in one of two ways.
+- Issuing WISPr credentials using IssueCredentialsAsync API, which uses the default WISPr implementation.
+- Performing a custom WISPr authentication using the information obtained through HotspotAuthenticationContext.TryGetAuthenticationContext. In this case, you must call HotspotAuthenticationContext.SkipAuthentication API to skip the default WISPr authentication process once the custom authentication is complete.
+
+## Related topics
+
+### Conceptual
+
+[Windows 8 hotspot authentication sample](https://code.msdn.microsoft.com/windowsapps/Wi-Fi-hotspot-authenticatio-943569eb)
+
+### Reference
+
+[Mobile Broadband on the Windows Hardware Dev Center](https://docs.microsoft.com/en-us/windows-hardware/drivers/mobilebroadband/index)
+
+[HotspotAuthenticationContext](https://docs.microsoft.com/en-us/uwp/api/Windows.Networking.NetworkOperators.HotspotAuthenticationContext)
+
+[HotspotAuthenticationEventDetails ](https://docs.microsoft.com/en-us/uwp/api/Windows.Networking.NetworkOperators.HotspotAuthenticationEventDetails)
+
+[IBackgroundTask](https://docs.microsoft.com/en-us/uwp/api/Windows.ApplicationModel.Background.IBackgroundTask)
+
+[IBackgroundTaskInstance](https://docs.microsoft.com/en-us/uwp/api/Windows.ApplicationModel.Background.IBackgroundTaskInstance)
+
+## System requirements
+
+The system must have a Wi-Fi adapter for this sample to be meaningful.
+
+**Client:** Windows 10
+
+**Server:** Windows Server 2016 Technical Preview
+
+**Phone:** Windows 10
+
+## Build the sample
+
+1. If you download the samples ZIP, be sure to unzip the entire archive, not just the folder with the sample you want to build.
+2. Start Microsoft Visual Studio 2017 and select **File** \> **Open** \> **Project/Solution**.
+3. Starting in the folder where you unzipped the samples, go to the Samples subfolder, then the subfolder for this specific sample, then the subfolder for the programming language. Double-click the Visual Studio Solution (.sln) file.
+4. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
+
+## Run the sample
+
+The Wi-Fi hotspot authentication sample has following requirements:
+
+Windows must trigger the application when authenticating with a certain hotspot. This is achieved by provisioning a WLAN profile with a corresponding configuration.
+
+1. The app must declare background task and corresponding entry point must match with the actual background task.
+2. The app must declare networkConnectionManagerProvisioning capability to provision hotspot profile xml. The capability belongs to restrictedcapabilities namespace and needs to be manually added to the Package.appxmanifest file since Visaul Studio UI doesn't support it.
+3. The provisioning XML built into this application must be modified to match the hotspot's SSID.
+
+The steps for completing these requirements and running the sample are described below:
+
+1. Modify the Provisioning Metadata XML file to match your hotspot by opening ProvisioningData.xml and adjusting the following fields:
+
+* CarrierProvisioning\Global\CarrierID: If writing a mobile broadband operator app, use the same GUID that you specified as the Service Number in the metadata authoring wizard.
+If writing a hotspot-only app, generate a new GUID with Visual Studio. On the Tools menu, click Create GUID. Click Copy to transfer the new GUID to the Clipboard.
+
+* CarrierProvisioning\Global\SubscriberID: If writing a mobile broadband operator app, use the International Mobile Subscriber Identity (IMSI) of the mobile broadband SIM.
+If writing a hotspot-only app, use any unique identifier appropriate to your service, such as a username or account number.
+
+* CarrierProvisioning\WLANProfiles\WLANProfile\name: Name of your service or test Access Point (AP).
+
+* CarrierProvisioning\WLANProfiles\WLANProfile\SSIDConfig\SSID\name: Configured SSID of your test hotspot.
+
+* CarrierProvisioning\WLANProfiles\WLANProfile\MSM\security\HotspotProfile\ExtAuth\ExtensionId:
+Package family name of the application. To retrieve this name, open package.appmanifest in Visual Studio. Click on the Packaging tab. Copy the Package Family Name.
+
+2. Provide appropriate credentials for your test AP
+
+* If the test AP uses fixed credentials: Modify HotspotAuthenticationTask\ConfigStore.cs to return a valid username and password for your test AP.
+* If the test AP uses dynamic credentials: In HotspotAuthenticationTask\BackgroundTask.cs, replace the reference to ConfigStore with your own business logic to generate/retrieve appropriate credentials for the network.
+
+The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
+
+**Deploying the sample**
+1. Select **Build** \> **Deploy Solution**.
+
+**Deploying and running the sample**
+1. To debug the sample and then run it, press F5 or select **Debug** \> **Start Debugging**. To run the sample without debugging, press Ctrl+F5 or select **Debug** \> **Start Without Debugging**.
+
+
diff --git a/Samples/HotspotAuthentication/cs/HotspotAuthentication.sln b/Samples/HotspotAuthentication/cs/HotspotAuthentication.sln
new file mode 100644
index 0000000000..cf695990bd
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/HotspotAuthentication.sln
@@ -0,0 +1,57 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27130.2027
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotspotAuthenticationApp", "HotspotAuthenticationApp.csproj", "{8F134D66-D37D-5D95-8312-F9730FB97B1B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotspotAuthenticationTask", "HotspotAuthenticationTask\HotspotAuthenticationTask.csproj", "{39343226-E6E6-5D21-B5B0-F0BEA809ABF2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Debug|ARM.ActiveCfg = Debug|ARM
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Debug|ARM.Build.0 = Debug|ARM
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Debug|ARM.Deploy.0 = Debug|ARM
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Debug|x64.ActiveCfg = Debug|x64
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Debug|x64.Build.0 = Debug|x64
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Debug|x64.Deploy.0 = Debug|x64
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Debug|x86.ActiveCfg = Debug|x86
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Debug|x86.Build.0 = Debug|x86
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Debug|x86.Deploy.0 = Debug|x86
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Release|ARM.ActiveCfg = Release|ARM
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Release|ARM.Build.0 = Release|ARM
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Release|ARM.Deploy.0 = Release|ARM
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Release|x64.ActiveCfg = Release|x64
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Release|x64.Build.0 = Release|x64
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Release|x64.Deploy.0 = Release|x64
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Release|x86.ActiveCfg = Release|x86
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Release|x86.Build.0 = Release|x86
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}.Release|x86.Deploy.0 = Release|x86
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}.Debug|ARM.ActiveCfg = Debug|ARM
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}.Debug|ARM.Build.0 = Debug|ARM
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}.Debug|x64.ActiveCfg = Debug|x64
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}.Debug|x64.Build.0 = Debug|x64
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}.Debug|x86.ActiveCfg = Debug|x86
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}.Debug|x86.Build.0 = Debug|x86
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}.Release|ARM.ActiveCfg = Release|ARM
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}.Release|ARM.Build.0 = Release|ARM
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}.Release|x64.ActiveCfg = Release|x64
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}.Release|x64.Build.0 = Release|x64
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}.Release|x86.ActiveCfg = Release|x86
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {82A66FCD-859A-40F5-A8CC-402F20E50B26}
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/HotspotAuthentication/cs/HotspotAuthenticationApp.csproj b/Samples/HotspotAuthentication/cs/HotspotAuthenticationApp.csproj
new file mode 100644
index 0000000000..da8a5614b3
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/HotspotAuthenticationApp.csproj
@@ -0,0 +1,198 @@
+
+
+
+
+ Debug
+ x86
+ {8F134D66-D37D-5D95-8312-F9730FB97B1B}
+ AppContainerExe
+ Properties
+ SDKTemplate
+ HotspotApp
+ en-US
+ UAP
+ 10.0.15063.0
+ 10.0.15063.0
+ 15
+ true
+ 512
+ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ win10-arm;win10-arm-aot;win10-x86;win10-x86-aot;win10-x64;win10-x64-aot
+
+
+ true
+ bin\ARM\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ bin\ARM\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ x64
+ false
+ prompt
+ true
+
+
+ bin\x64\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ x64
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ bin\x86\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+ true
+
+
+
+ App.xaml.cs
+ App.xaml
+
+
+ MainPage.xaml.cs
+ MainPage.xaml
+
+
+ Properties\AssemblyInfo.cs
+
+
+
+ Scenario1_Initialization.xaml
+
+
+ Scenario2_BackgroundTask.xaml
+
+
+ Scenario3_ForegroundApp.xaml
+
+
+
+
+
+ Designer
+
+
+
+
+ App.xaml
+ MSBuild:Compile
+ Designer
+
+
+ MainPage.xaml
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ Styles\Styles.xaml
+ MSBuild:Compile
+ Designer
+
+
+
+
+ Properties\Default.rd.xml
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smallTile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squareTile-sdk.png
+
+
+ Assets\storeLogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+
+
+ 5.0.0
+
+
+
+
+ {f0f4e04a-1851-45f4-9899-4986677874fa}
+ HotspotAuthenticationTask
+
+
+
+ 15.0
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HotspotAuthentication/cs/HotspotAuthenticationTask/BackgroundTask.cs b/Samples/HotspotAuthentication/cs/HotspotAuthenticationTask/BackgroundTask.cs
new file mode 100644
index 0000000000..0720a95570
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/HotspotAuthenticationTask/BackgroundTask.cs
@@ -0,0 +1,196 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using Windows.ApplicationModel.Background;
+using Windows.Data.Xml.Dom;
+using Windows.Networking.NetworkOperators;
+using Windows.UI.Notifications;
+
+// The namespace for the background tasks.
+namespace HotspotAuthenticationTask
+{
+ // A background task always implements the IBackgroundTask interface.
+ public sealed class AuthenticationTask : IBackgroundTask
+ {
+ private const string _foregroundAppId = "HotspotAuthenticationApp.App";
+ private volatile bool _cancelRequested = false;
+
+ private HotspotAuthenticationEventDetails _details;
+ private HotspotAuthenticationContext _context;
+
+ // The Run method is the entry point of a background task.
+ public async void Run(IBackgroundTaskInstance taskInstance)
+ {
+ Debug.WriteLine("Background " + taskInstance.Task.Name + " starting...");
+
+ // Convert the trigger details to a HotspotAuthenticationEventDetails.
+ _details = taskInstance.TriggerDetails as HotspotAuthenticationEventDetails;
+
+ // Associate a cancelation handler with the background task for handlers
+ // that may take a considerable time to complete.
+ taskInstance.Canceled += OnCanceled;
+
+ // Take a deferral so that we can call asynchronous APIs.
+ BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
+
+ // The real work happens in RunAsync.
+ await RunAsync();
+
+ Debug.WriteLine("Background " + taskInstance.Task.Name + " completed");
+
+ deferral.Complete();
+ }
+
+ private async Task RunAsync()
+ {
+ // Do the background task activity. First, get the authentication context.
+ Debug.WriteLine("Getting event details");
+
+ if (!HotspotAuthenticationContext.TryGetAuthenticationContext(_details.EventToken, out _context))
+ {
+ // The event is not targetting this application. There is no further processing to do.
+ Debug.WriteLine("Failed to get event context");
+ return;
+ }
+
+ byte[] ssid = _context.WirelessNetworkId;
+ Debug.WriteLine("SSID: " + System.Text.UTF8Encoding.UTF8.GetString(ssid, 0, ssid.Length));
+
+ if (ConfigStore.UseNativeWISPr)
+ {
+ // Following code can be used if using native WISPr implementation. Please note that
+ // following HotspotAuthenticationContext properties only work on windows and not on windows phone.
+ // On Windows Phone they return un-useful strings
+ // Developers are expected to implement their own WISPr implementation on Phone
+
+ Debug.WriteLine("AuthenticationUrl: " + _context.AuthenticationUrl.OriginalString);
+ Debug.WriteLine("RedirectMessageUrl: " + _context.RedirectMessageUrl.OriginalString);
+ Debug.WriteLine("RedirectMessageXml: " + _context.RedirectMessageXml.GetXml());
+
+ // In this sample, the AuthenticationUrl is always checked in the background task handler
+ // to avoid launching the foreground app in case the authentication host is not trusted.
+ if (ConfigStore.AuthenticationHost != _context.AuthenticationUrl.Host)
+ {
+ // Hotspot is not using the trusted authentication server.
+ // Abort authentication and disconnect.
+ Debug.WriteLine("Authentication server is untrusted");
+ _context.AbortAuthentication(ConfigStore.MarkAsManualConnect);
+ return;
+ }
+ }
+
+ // Run the appropriate scenario selected by the foreground app.
+ if (ConfigStore.AuthenticateThroughBackgroundTask)
+ {
+ await AuthenticateInBackgroundAsync();
+ }
+ else
+ {
+ ContinueAuthenticationInForeground();
+ }
+ return;
+ }
+
+ private async Task AuthenticateInBackgroundAsync()
+ {
+ // In case this handler performs more complex tasks, it may get canceled at runtime.
+ // Check if task was canceled by now.
+ if (_cancelRequested)
+ {
+ // In case the task handler takes too long to generate credentials and gets canceled,
+ // the handler should terminate the authentication by aborting it
+ Debug.WriteLine("Aborting authentication");
+ _context.AbortAuthentication(ConfigStore.MarkAsManualConnect);
+ return;
+ }
+
+ if (ConfigStore.UseNativeWISPr)
+ {
+ // The most common way of handling an authentication attempt is by providing WISPr credentials
+ // through the IssueCredentialsAsync API.
+ // If the task doesn't take any actions for authentication failures, it can use the
+ // IssueCredentials API to just provide credenstials.
+ // Alternatively, an application could run its own business logic to authentication with the
+ // hotspot. In this case it should call the SkipAuthentication API. Note that it should call
+ // SkipAuthentication after it has authenticated to allow Windows to refresh the network connectivity
+ // state instantly.
+ Debug.WriteLine("Issuing credentials");
+ HotspotCredentialsAuthenticationResult result = await _context.IssueCredentialsAsync(
+ ConfigStore.UserName, ConfigStore.Password, ConfigStore.ExtraParameters, ConfigStore.MarkAsManualConnect);
+ if (result.ResponseCode == HotspotAuthenticationResponseCode.LoginSucceeded)
+ {
+ Debug.WriteLine("Issuing credentials succeeded");
+ Uri logoffUrl = result.LogoffUrl;
+ if (logoffUrl != null)
+ {
+ Debug.WriteLine("The logoff URL is: " + logoffUrl.OriginalString);
+ }
+ }
+ else
+ {
+ Debug.WriteLine("Issuing credentials failed");
+ }
+ }
+ else
+ {
+ //TODO: Please perform any authentication that is required by your particular scenario.
+ // Check _cancelRequested periodically in case the task is canceled.
+
+ // Finally call SkipAuthentication to indicate that we are not doing native WISPr authentication
+ // This call also serves the purpose of indicating a successful authentication.
+ _context.SkipAuthentication();
+ }
+ }
+
+ private void ContinueAuthenticationInForeground()
+ {
+ Debug.WriteLine("Triggering foreground application");
+ // Pass event token to application
+ ConfigStore.AuthenticationToken = _details.EventToken;
+
+ // Trigger notification
+ // Since TriggerAttentionRequired function throws NotImplementedException on phone we will be using
+ // regular Toast Notification to notify user about the authentication, Tapping on the notification will
+ // launch the application where user can complete the authentication
+ if (ConfigStore.UseNativeWISPr)
+ {
+ // The second parameter is used as the activation command line.
+ _context.TriggerAttentionRequired(_foregroundAppId, "");
+ }
+ else
+ {
+ var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
+ toastXml.GetElementsByTagName("text")[0].AppendChild(toastXml.CreateTextNode("Auth by foreground"));
+ IXmlNode toastNode = toastXml.SelectSingleNode("/toast");
+ ((XmlElement)toastNode).SetAttribute("launch", "AuthByForeground");
+
+ var toast = new ToastNotification(toastXml);
+ toast.Tag = "AuthByForeground";
+ toast.Group = "HotspotAuthAPI";
+
+ var notification = ToastNotificationManager.CreateToastNotifier();
+ notification.Show(toast);
+ }
+ }
+
+ // Handles background task cancellation.
+ private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
+ {
+ // Indicate that the background task is canceled.
+ _cancelRequested = true;
+
+ Debug.WriteLine("Background " + sender.Task.Name + " cancel requested...");
+ }
+ }
+}
diff --git a/Samples/HotspotAuthentication/cs/HotspotAuthenticationTask/ConfigStore.cs b/Samples/HotspotAuthentication/cs/HotspotAuthenticationTask/ConfigStore.cs
new file mode 100644
index 0000000000..6d34eec21e
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/HotspotAuthenticationTask/ConfigStore.cs
@@ -0,0 +1,65 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Diagnostics;
+using System.Threading;
+using Windows.ApplicationModel.Background;
+using Windows.Storage;
+using Windows.Networking.NetworkOperators;
+
+// The namespace for the background tasks.
+namespace HotspotAuthenticationTask
+{
+ // A helper class for providing the application configuration.
+ public sealed class ConfigStore
+ {
+ // For the sake of simplicity of the sample, the following authentication parameters are hard coded:
+ public static string AuthenticationHost => "login.contoso.com";
+ public static string UserName => "MyUserName";
+ public static string Password => "MyPassword";
+ public static string ExtraParameters => "";
+ public static bool MarkAsManualConnect => false;
+
+ public static bool UseNativeWISPr
+ {
+ get { return GetValueWithDefault("usenativewispr", true); }
+ set { ApplicationData.Current.LocalSettings.Values["usenativewispr"] = value; }
+ }
+
+ // This flag is set by the foreground app to toogle authentication to be done by the
+ // background task handler.
+ public static bool AuthenticateThroughBackgroundTask
+ {
+ get { return GetValueWithDefault("background", true); }
+ set { ApplicationData.Current.LocalSettings.Values["background"] = value; }
+ }
+
+ // This item is set by the background task handler to pass an authentication event
+ // token to the foreground app.
+ public static string AuthenticationToken
+ {
+ get { return GetValueWithDefault("token", ""); }
+ set { ApplicationData.Current.LocalSettings.Values["token"] = value; }
+ }
+
+ static T GetValueWithDefault(string name, T defaultValue)
+ {
+ object value;
+ if (ApplicationData.Current.LocalSettings.Values.TryGetValue(name, out value) &&
+ value is T)
+ {
+ return (T)value;
+ }
+ return defaultValue;
+ }
+ }
+}
diff --git a/Samples/HotspotAuthentication/cs/HotspotAuthenticationTask/HotspotAuthenticationTask.csproj b/Samples/HotspotAuthentication/cs/HotspotAuthenticationTask/HotspotAuthenticationTask.csproj
new file mode 100644
index 0000000000..7475c021b4
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/HotspotAuthenticationTask/HotspotAuthenticationTask.csproj
@@ -0,0 +1,118 @@
+
+
+
+
+ Debug
+ x86
+ {39343226-E6E6-5D21-B5B0-F0BEA809ABF2}
+ winmdobj
+ Properties
+ HotspotAuthenticationTask
+ HotspotAuthenticationTask
+ en-US
+ UAP
+ 10.0.15063.0
+ 10.0.15063.0
+ 15
+ true
+ 512
+ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ win10-arm;win10-arm-aot;win10-x86;win10-x86-aot;win10-x64;win10-x64-aot
+
+
+ ARM
+ true
+ bin\ARM\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ ARM
+ bin\ARM\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+ true
+
+
+ x64
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ x64
+ false
+ prompt
+ true
+
+
+ x64
+ bin\x64\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ x64
+ false
+ prompt
+ true
+ true
+
+
+ x86
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ x86
+ bin\x86\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+ true
+
+
+
+
+
+
+
+
+ 5.0.0
+
+
+
+ 14.0
+
+
+
+
\ No newline at end of file
diff --git a/Samples/HotspotAuthentication/cs/HotspotAuthenticationTask/Properties/AssemblyInfo.cs b/Samples/HotspotAuthentication/cs/HotspotAuthenticationTask/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..64f48cea1a
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/HotspotAuthenticationTask/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Hotspot Authentication CS sample")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)]
diff --git a/Samples/HotspotAuthentication/cs/Package.appxmanifest b/Samples/HotspotAuthentication/cs/Package.appxmanifest
new file mode 100644
index 0000000000..90b85ccffb
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/Package.appxmanifest
@@ -0,0 +1,51 @@
+
+
+
+
+
+ Hotspot Authentication C# Sample
+ Microsoft Corporation
+ Assets\StoreLogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/HotspotAuthentication/cs/ProvisioningData.xml b/Samples/HotspotAuthentication/cs/ProvisioningData.xml
new file mode 100644
index 0000000000..f149654d83
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/ProvisioningData.xml
@@ -0,0 +1,36 @@
+
+
+
+
+ {11111111-1111-1111-1111-111111111111}
+
+ 1234567890
+
+
+
+
+ Contoso Wi-Fi
+
+
+
+ contosowifi
+
+
+
+
+
+ open
+ none
+ false
+
+
+
+
+ Microsoft.SDKSamples.HotspotAuthentication.CS_8wekyb3d8bbwe
+
+
+
+
+
+
+
diff --git a/Samples/HotspotAuthentication/cs/SampleConfiguration.cs b/Samples/HotspotAuthentication/cs/SampleConfiguration.cs
new file mode 100644
index 0000000000..fe1a615854
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/SampleConfiguration.cs
@@ -0,0 +1,35 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using Windows.UI.Xaml.Controls;
+
+namespace SDKTemplate
+{
+ public partial class MainPage : Page
+ {
+ public const string FEATURE_NAME = "Hotspot Authentication";
+
+ List scenarios = new List
+ {
+ new Scenario() { Title="Initialization", ClassType=typeof(Scenario1_Initialization)},
+ new Scenario() { Title="Authentication by background task", ClassType=typeof(Scenario2_BackgroundTask)},
+ new Scenario() { Title="Authentication by foreground app", ClassType=typeof(Scenario3_ForegroundApp)},
+ };
+ }
+
+ public class Scenario
+ {
+ public string Title { get; set; }
+ public Type ClassType { get; set; }
+ }
+}
diff --git a/Samples/HotspotAuthentication/cs/Scenario1_Initialization.xaml b/Samples/HotspotAuthentication/cs/Scenario1_Initialization.xaml
new file mode 100644
index 0000000000..ea345b73bd
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/Scenario1_Initialization.xaml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/HotspotAuthentication/cs/Scenario1_Initialization.xaml.cs b/Samples/HotspotAuthentication/cs/Scenario1_Initialization.xaml.cs
new file mode 100644
index 0000000000..3679709607
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/Scenario1_Initialization.xaml.cs
@@ -0,0 +1,175 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+using HotspotAuthenticationTask;
+using System;
+using Windows.ApplicationModel.Background;
+using Windows.Data.Xml.Dom;
+using Windows.Networking.NetworkOperators;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace SDKTemplate
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class Scenario1_Initialization : Page
+ {
+ private MainPage rootPage = MainPage.Current;
+
+ public Scenario1_Initialization()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ConfigStore.UseNativeWISPr = true;
+
+ // Configure background task handler to perform authentication as default
+ ConfigStore.AuthenticateThroughBackgroundTask = true;
+
+ // Setup completion handler
+ var isTaskRegistered = ScenarioCommon.Instance.RegisteredCompletionHandlerForBackgroundTask();
+
+ // Initialize button state
+ UpdateButtonState(isTaskRegistered);
+
+ }
+
+ private async void ProvisionButton_Click(object sender, RoutedEventArgs e)
+ {
+ ProvisionButton.IsEnabled = false;
+
+ // Open the installation folder
+ var installLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
+
+ // Access the provisioning file
+ var provisioningFile = await installLocation.GetFileAsync("ProvisioningData.xml");
+
+ // Load with XML parser
+ var xmlDocument = await XmlDocument.LoadFromFileAsync(provisioningFile);
+
+ // Get raw XML
+ var provisioningXml = xmlDocument.GetXml();
+
+ // Create ProvisiongAgent Object
+ var provisioningAgent = new ProvisioningAgent();
+
+ try
+ {
+ // Create ProvisionFromXmlDocumentResults Object
+ var result = await provisioningAgent.ProvisionFromXmlDocumentAsync(provisioningXml);
+
+ if (result.AllElementsProvisioned)
+ {
+ rootPage.NotifyUser("Provisioning was successful", NotifyType.StatusMessage);
+ }
+ else
+ {
+ rootPage.NotifyUser("Provisioning result: " + result.ProvisionResultsXml, NotifyType.ErrorMessage);
+ }
+ }
+ catch (System.Exception ex)
+ {
+ // See https://docs.microsoft.com/en-us/uwp/api/windows.networking.networkoperators.provisioningagent.provisionfromxmldocumentasync
+ // for list of possible exceptions.
+ rootPage.NotifyUser($"Unable to provision: {ex}", NotifyType.ErrorMessage);
+ }
+
+ ProvisionButton.IsEnabled = true;
+ }
+
+ private void RegisterButton_Click(object sender, RoutedEventArgs e)
+ {
+ // Create a new background task builder.
+ var taskBuilder = new BackgroundTaskBuilder();
+
+ // Create a new NetworkOperatorHotspotAuthentication trigger.
+ var trigger = new NetworkOperatorHotspotAuthenticationTrigger();
+
+ // Associate the NetworkOperatorHotspotAuthentication trigger with the background task builder.
+ taskBuilder.SetTrigger(trigger);
+
+ // Specify the background task to run when the trigger fires.
+ taskBuilder.TaskEntryPoint = ScenarioCommon.BackgroundTaskEntryPoint;
+
+ // Name the background task.
+ taskBuilder.Name = ScenarioCommon.BackgroundTaskName;
+
+ try
+ {
+ // Register the background task.
+ var task = taskBuilder.Register();
+
+ // Associate progress and completed event handlers with the new background task.
+ task.Completed += ScenarioCommon.Instance.OnBackgroundTaskCompleted;
+
+ UpdateButtonState(true);
+
+ rootPage.NotifyUser("Register was successful", NotifyType.StatusMessage);
+ }
+ catch (System.Exception ex)
+ {
+ rootPage.NotifyUser(ex.ToString(), NotifyType.ErrorMessage);
+ }
+ }
+
+ private void UnregisterButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (UnregisterBackgroundTask())
+ {
+ UpdateButtonState(false);
+ rootPage.NotifyUser("Unregister was successful.", NotifyType.StatusMessage);
+ }
+ else
+ {
+ rootPage.NotifyUser(String.Format("Background {0} task is not registered", ScenarioCommon.BackgroundTaskName), NotifyType.StatusMessage);
+ }
+
+ }
+
+ private bool UnregisterBackgroundTask()
+ {
+ bool unregister = false;
+ // Loop through all background tasks and unregister any.
+ foreach (var cur in BackgroundTaskRegistration.AllTasks)
+ {
+ if (cur.Value.Name == ScenarioCommon.BackgroundTaskName)
+ {
+ cur.Value.Unregister(true);
+ unregister = true;
+ }
+ }
+ return unregister;
+
+ }
+
+ ///
+ /// Enables or disables register and unregister buttons
+ ///
+ /// True if background task is registered, false otherwise
+ private void UpdateButtonState(bool registered)
+ {
+ if (registered)
+ {
+ RegisterButton.IsEnabled = false;
+ UnregisterButton.IsEnabled = true;
+ }
+ else
+ {
+ RegisterButton.IsEnabled = true;
+ UnregisterButton.IsEnabled = false;
+ }
+ }
+ }
+}
diff --git a/Samples/HotspotAuthentication/cs/Scenario2_BackgroundTask.xaml b/Samples/HotspotAuthentication/cs/Scenario2_BackgroundTask.xaml
new file mode 100644
index 0000000000..0c26e93b7b
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/Scenario2_BackgroundTask.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ The background task handler can be used to perform the actual authentication. Connect to the hotspot configured in step one to see it happen. You may exit this application now.
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/HotspotAuthentication/cs/Scenario2_BackgroundTask.xaml.cs b/Samples/HotspotAuthentication/cs/Scenario2_BackgroundTask.xaml.cs
new file mode 100644
index 0000000000..c0d77bf593
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/Scenario2_BackgroundTask.xaml.cs
@@ -0,0 +1,44 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using HotspotAuthenticationTask;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace SDKTemplate
+{
+ ///
+ /// This page is used to handle authentication by background task scenario
+ ///
+ public sealed partial class Scenario2_BackgroundTask : Page
+ {
+ // A pointer back to the main page. This is needed if you call methods in MainPage such as NotifyUser()
+ MainPage rootPage = MainPage.Current;
+ public Scenario2_BackgroundTask()
+ {
+ this.InitializeComponent();
+ }
+
+ ///
+ /// Invoked when this page is about to be displayed in a Frame.
+ ///
+ /// Event data that describes how this page was reached. The Parameter
+ /// property is typically used to configure the page.
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ // Configure background task handler to perform authentication
+ ConfigStore.AuthenticateThroughBackgroundTask = true;
+
+ // Setup completion handler
+ ScenarioCommon.Instance.RegisteredCompletionHandlerForBackgroundTask();
+ }
+ }
+}
diff --git a/Samples/HotspotAuthentication/cs/Scenario3_ForegroundApp.xaml b/Samples/HotspotAuthentication/cs/Scenario3_ForegroundApp.xaml
new file mode 100644
index 0000000000..bede0d0d79
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/Scenario3_ForegroundApp.xaml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Authentication can also be performed by the foreground application. In this case, the background task handler triggers the foreground application being launched. This is useful if the application needs additional user input to perform the authentication. Connect to the hotspot configured in step 1 to see it happen. You may exit this application now, and it will be launched on demand.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/HotspotAuthentication/cs/Scenario3_ForegroundApp.xaml.cs b/Samples/HotspotAuthentication/cs/Scenario3_ForegroundApp.xaml.cs
new file mode 100644
index 0000000000..4bf2b54e1e
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/Scenario3_ForegroundApp.xaml.cs
@@ -0,0 +1,153 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using HotspotAuthenticationTask;
+using System;
+using Windows.Networking.NetworkOperators;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace SDKTemplate
+{
+ ///
+ /// The page is used to handle authenticate by foreground app scenario
+ ///
+ public sealed partial class Scenario3_ForegroundApp : Page
+ {
+ // A pointer back to the main page. This is needed to call methods in MainPage such as NotifyUser()
+ MainPage rootPage = MainPage.Current;
+
+ HotspotAuthenticationContext authenticationContext;
+
+ public Scenario3_ForegroundApp()
+ {
+ this.InitializeComponent();
+ }
+
+ ///
+ /// Invoked when this page is about to be displayed in a Frame.
+ ///
+ /// Event data that describes how this page was reached. The Parameter
+ /// property is typically used to configure the page.
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ // Configure background task handler to trigger foregound app for authentication
+ ConfigStore.AuthenticateThroughBackgroundTask = false;
+
+ // Setup completion handler
+ ScenarioCommon.Instance.RegisteredCompletionHandlerForBackgroundTask();
+
+ // Register event to update UI state on authentication event
+ ScenarioCommon.Instance.BackgroundAuthenticationCompleted += OnBackgroundAuthenticationCompleted;
+
+ // Check current authentication state
+ InitializeForegroundAppAuthentication();
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ ScenarioCommon.Instance.BackgroundAuthenticationCompleted -= OnBackgroundAuthenticationCompleted;
+ }
+
+ ///
+ /// Handle authentication event triggered by background task
+ ///
+ ///
+ ///
+ async void OnBackgroundAuthenticationCompleted(ScenarioCommon sender, BackgroundAuthenticationCompletedEventArgs e)
+ {
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ if (e.Succeeded)
+ {
+ InitializeForegroundAppAuthentication();
+ }
+ else
+ {
+ rootPage.NotifyUser($"Background task encountered exception: {e.ExtendedError}", NotifyType.ErrorMessage);
+ }
+ });
+ }
+
+ private async void AuthenticateButton_Click(object sender, RoutedEventArgs e)
+ {
+ AuthenticateButton.IsEnabled = false;
+
+ HotspotCredentialsAuthenticationResult result = await authenticationContext.IssueCredentialsAsync(
+ ConfigStore.UserName, ConfigStore.Password, ConfigStore.ExtraParameters, ConfigStore.MarkAsManualConnect);
+ if (result.ResponseCode == HotspotAuthenticationResponseCode.LoginSucceeded)
+ {
+ rootPage.NotifyUser("Issuing credentials succeeded", NotifyType.StatusMessage);
+ Uri logoffUrl = result.LogoffUrl;
+ if (logoffUrl != null)
+ {
+ rootPage.NotifyUser("The logoff URL is: " + logoffUrl.OriginalString, NotifyType.StatusMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Issuing credentials failed", NotifyType.ErrorMessage);
+ }
+ AuthenticateButton.IsEnabled = true;
+ }
+
+ private void SkipButton_Click(object sender, RoutedEventArgs e)
+ {
+ // Here you can implement custom authentication.
+ authenticationContext.SkipAuthentication();
+ rootPage.NotifyUser("Authentication skipped", NotifyType.StatusMessage);
+ ClearAuthenticationToken();
+ }
+
+ private void AbortButton_Click(object sender, RoutedEventArgs e)
+ {
+ authenticationContext.AbortAuthentication(ConfigStore.MarkAsManualConnect);
+ rootPage.NotifyUser("Authentication aborted", NotifyType.StatusMessage);
+ ClearAuthenticationToken();
+ }
+
+ ///
+ /// Query authentication token from application storage and update the UI.
+ /// The token gets passed from the background task handler.
+ ///
+ private void InitializeForegroundAppAuthentication()
+ {
+ string token = ConfigStore.AuthenticationToken;
+ if (String.IsNullOrEmpty(token))
+ {
+ return; // no token found
+ }
+ if (!HotspotAuthenticationContext.TryGetAuthenticationContext(token, out authenticationContext))
+ {
+ rootPage.NotifyUser("TryGetAuthenticationContext failed", NotifyType.ErrorMessage);
+ return;
+ }
+
+ AuthenticateButton.IsEnabled = true;
+ SkipButton.IsEnabled = true;
+ AbortButton.IsEnabled = true;
+ }
+
+
+ ///
+ /// Clear the authentication token in the application storage and update the UI.
+ ///
+ private void ClearAuthenticationToken()
+ {
+ ConfigStore.AuthenticationToken = "";
+ AuthenticateButton.IsEnabled = false;
+ SkipButton.IsEnabled = false;
+ AbortButton.IsEnabled = false;
+ }
+ }
+}
+
diff --git a/Samples/HotspotAuthentication/cs/ScenarioCommon.cs b/Samples/HotspotAuthentication/cs/ScenarioCommon.cs
new file mode 100644
index 0000000000..a24e052b66
--- /dev/null
+++ b/Samples/HotspotAuthentication/cs/ScenarioCommon.cs
@@ -0,0 +1,109 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using HotspotAuthenticationTask;
+using System;
+using Windows.ApplicationModel.Background;
+using Windows.UI.Core;
+
+namespace SDKTemplate
+{
+ // A delegate type for hooking up foreground authentication notifications.
+ public class BackgroundAuthenticationCompletedEventArgs
+ {
+ public BackgroundAuthenticationCompletedEventArgs(Exception exception)
+ {
+ ExtendedError = exception;
+ }
+ public bool Succeeded => ExtendedError == null;
+ public Exception ExtendedError { get; private set; }
+ }
+
+ public delegate void BackgroundAuthenticationCompletedEventHandler(ScenarioCommon sender, BackgroundAuthenticationCompletedEventArgs e);
+
+ // Shared code for all scenario pages
+ public class ScenarioCommon
+ {
+ public static ScenarioCommon Instance { get; } = new ScenarioCommon();
+
+ // The entry point name of the background task handler:
+
+ public const string BackgroundTaskEntryPoint = "HotspotAuthenticationTask.AuthenticationTask";
+
+ // The (arbitrarily chosen) name assigned to the background task:
+ public const string BackgroundTaskName = "AuthenticationBackgroundTask";
+
+ // A delegate for subscribing for foreground authentication events
+ public BackgroundAuthenticationCompletedEventHandler BackgroundAuthenticationCompleted;
+
+ // A pointer back to the main page. This is needed to call methods in MainPage such as NotifyUser()
+ MainPage rootPage = MainPage.Current;
+
+ // A flag to remember if a background task handler has been registered
+ private bool HasRegisteredBackgroundTaskHandler = false;
+
+ ///
+ /// Register completion handler for registered background task on application startup.
+ ///
+ /// True if a registerd task was found
+ public bool RegisteredCompletionHandlerForBackgroundTask()
+ {
+ if (!HasRegisteredBackgroundTaskHandler)
+ {
+ try
+ {
+ // Associate background task completed event handler with background task.
+ foreach (var cur in BackgroundTaskRegistration.AllTasks)
+ {
+ if (cur.Value.Name == BackgroundTaskName)
+ {
+ cur.Value.Completed += new BackgroundTaskCompletedEventHandler(OnBackgroundTaskCompleted);
+ HasRegisteredBackgroundTaskHandler = true;
+ break;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ rootPage.NotifyUser(ex.ToString(), NotifyType.ErrorMessage);
+ }
+ }
+ return HasRegisteredBackgroundTaskHandler;
+ }
+
+ ///
+ /// Background task completion handler. When authenticating through the foreground app, this triggers the authentication flow if the app is currently running.
+ ///
+ ///
+ ///
+ public void OnBackgroundTaskCompleted(IBackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs e)
+ {
+ if (sender.Name == BackgroundTaskName)
+ {
+ Exception exception = null;
+ try
+ {
+ // If the background task threw an exception, re-raise it here so we can pass it to the event handler.
+ e.CheckResult();
+ }
+ catch (Exception ex)
+ {
+ exception = ex;
+ }
+
+ if (!ConfigStore.AuthenticateThroughBackgroundTask)
+ {
+ BackgroundAuthenticationCompleted?.Invoke(this, new BackgroundAuthenticationCompletedEventArgs(null));
+ }
+ }
+ }
+ }
+}