diff --git a/docs/concepts/WebAuthenticator.md b/docs/concepts/WebAuthenticator.md
index d10415b..9162b8c 100644
--- a/docs/concepts/WebAuthenticator.md
+++ b/docs/concepts/WebAuthenticator.md
@@ -17,8 +17,29 @@ Next you can make a make a call to authenticate using your default browser:
WebAuthenticatorResult result = await WinUIEx.WebAuthenticator.AuthenticateAsync(authorizeUrl, callbackUri);
```
-Your callback uri must use a custom scheme, and you must define this scheme in your application manifest. For example if your callback uri is "myscheme://loggedin", your manifest dialog should look like this:
+### Configuration
+
+Your app must be configured for OAuth with schema activation. The scheme must be the first part of the url, ie if your oauth redirection url starts with for instance `myscheme://signin/`, the scheme would be `myscheme`. Note that http(s) schemes are not supported here.
+
+#### Packaged Apps
+
+If your app is packaged, in your app's `Package.appxmanifest` under `Declarations`, add a Protocol declaration and add the scheme you registered for your application's oauth redirect url under "Name".
+For example if your callback uri is "myscheme://loggedin", your manifest dialog should look like this:
![image](https://user-images.githubusercontent.com/1378165/166501267-1da07930-ab4d-431e-87cf-a7b183cc3c87.png)
+#### Unpackaged Apps
+
+If your app is unpackaged, instead of relying on the app manifest to handle this for you, make sure you register the application for protocol activation. For example:
+``` cs
+try
+{
+ Microsoft.Windows.AppLifecycle.ActivationRegistrationManager.RegisterForProtocolActivation("myscheme", "Assets\\Square150x150Logo.scale-100", "My App Name", null);
+ var result = await WebAuthenticator.AuthenticateAsync(authorizeUri, callbackUri, cancellationToken);
+}
+finally
+{
+ Microsoft.Windows.AppLifecycle.ActivationRegistrationManager.UnregisterForProtocolActivation("myscheme", null);
+}
+```
\ No newline at end of file
diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets
index 9a1a617..f4a053d 100644
--- a/src/Directory.Build.targets
+++ b/src/Directory.Build.targets
@@ -17,8 +17,8 @@
Morten Nielsen - https://xaml.dev
Morten Nielsen - https://xaml.dev
logo.png
- 2.5.0
-
+ 2.5.1
+ 2.5.0
diff --git a/src/WinUIEx/WebAuthenticator.cs b/src/WinUIEx/WebAuthenticator.cs
index 4243499..48798e5 100644
--- a/src/WinUIEx/WebAuthenticator.cs
+++ b/src/WinUIEx/WebAuthenticator.cs
@@ -19,9 +19,30 @@ namespace WinUIEx
///
///
///
- /// Your app must be configured for OAuth. In you app package's Package.appxmanifest under Declarations, add a
+ /// Your app must be configured for OAuth with schema activation. The scheme must be the first part of the url, ie if your
+ /// oauth redirection url starts with for instance myappscheme://signin/, the scheme would be myappscheme.
+ /// Note that http(s) schemes are not supported here.
+ ///
+ ///
+ /// If your app is packaged, in your app's Package.appxmanifest under Declarations, add a
/// Protocol declaration and add the scheme you registered for your application's oauth redirect url under "Name".
///
+ ///
+ /// If your app is unpackaged, make sure you register the application for protocol activation.
+ ///
+ ///
+ ///
+ /// try
+ /// {
+ /// Microsoft.Windows.AppLifecycle.ActivationRegistrationManager.RegisterForProtocolActivation("myappscheme", "Assets\\Square150x150Logo.scale-100", "My App Name", null);
+ /// var result = await WebAuthenticator.AuthenticateAsync(authorizeUri, callbackUri, cancellationToken);
+ /// }
+ /// finally
+ /// {
+ /// Microsoft.Windows.AppLifecycle.ActivationRegistrationManager.UnregisterForProtocolActivation("myappscheme", null);
+ /// }
+ ///
+ ///
///
public sealed class WebAuthenticator
{
@@ -218,11 +239,20 @@ private async Task Authenticate(Uri authorizeUri, Uri ca
}
if (!Helpers.IsAppPackaged)
{
- throw new InvalidOperationException("The WebAuthenticator requires a packaged app with an AppxManifest");
+ if(callbackUri.Scheme == "http" || callbackUri.Scheme == "https")
+ throw new InvalidOperationException($"{callbackUri.Scheme}:// schemes are not allowed for callbackUri. Use a custom scheme like 'myapp' instead.");
+ var value = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(callbackUri.Scheme);
+ if(value is null || value.GetValue("URL Protocol") is null)
+ {
+ throw new InvalidOperationException($"The URI Scheme '{callbackUri.Scheme}' is not registered. Call ActivationRegistrationManager.RegisterForProtocolActivation to register protocol activation.");
+ }
}
- if (!IsUriProtocolDeclared(callbackUri.Scheme))
+ else
{
- throw new InvalidOperationException($"The URI Scheme {callbackUri.Scheme} is not declared in AppxManifest.xml");
+ if (!IsUriProtocolDeclared(callbackUri.Scheme))
+ {
+ throw new InvalidOperationException($"The URI Scheme {callbackUri.Scheme} is not declared in AppxManifest.xml");
+ }
}
var g = Guid.NewGuid();
var taskId = g.ToString();
diff --git a/src/WinUIEx/WinUIEx.csproj b/src/WinUIEx/WinUIEx.csproj
index 51350d9..80180ca 100644
--- a/src/WinUIEx/WinUIEx.csproj
+++ b/src/WinUIEx/WinUIEx.csproj
@@ -25,7 +25,7 @@
WinUIEx
WinUI Extensions
- - Added `SimpleSplashScreen` for display application launch splash screens
+ - WebAuthenticator: Added support for unpackaged apps.
diff --git a/src/WinUIExSample/App.xaml.cs b/src/WinUIExSample/App.xaml.cs
index db5a56b..0212ad8 100644
--- a/src/WinUIExSample/App.xaml.cs
+++ b/src/WinUIExSample/App.xaml.cs
@@ -29,16 +29,12 @@ public App()
fss = SimpleSplashScreen.ShowDefaultSplashScreen();
#endif
this.InitializeComponent();
- int length = 0;
- var sb = new System.Text.StringBuilder(0);
- int result = GetCurrentPackageFullName(ref length, sb);
- if(result == 15700L)
- {
- // Not a packaged app. Configure file-based persistence instead
- WinUIEx.WindowManager.PersistenceStorage = new FilePersistence("WinUIExPersistence.json");
- }
-
+#if UNPACKAGED
+ // Use file-based persistence since we can't rely on default storage for window persistence when unpackaged
+ WinUIEx.WindowManager.PersistenceStorage = new FilePersistence("WinUIExPersistence.json");
+#endif
}
+
internal SimpleSplashScreen fss { get; set; }
///
/// Invoked when the application is launched normally by the end user. Other entry points
@@ -67,9 +63,7 @@ private void Splash_Activated(object sender, WindowActivatedEventArgs args)
public WindowEx MainWindow => m_window;
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
- private static extern int GetCurrentPackageFullName(ref int packageFullNameLength, System.Text.StringBuilder packageFullName);
-
+#if UNPACKAGED
private class FilePersistence : IDictionary
{
private readonly Dictionary _data = new Dictionary();
@@ -143,6 +137,7 @@ public void Clear()
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); // TODO
}
+#endif
}
#if DISABLE_XAML_GENERATED_MAIN
@@ -156,7 +151,11 @@ static void Main(string[] args)
{
if (WebAuthenticator.CheckOAuthRedirectionActivation(true))
return;
+#if UNPACKAGED
+ var fss = SimpleSplashScreen.ShowSplashScreenImage("Assets\\SplashScreen.scale-100.png");
+#else
var fss = SimpleSplashScreen.ShowDefaultSplashScreen();
+#endif
global::WinRT.ComWrappersSupport.InitializeComWrappers();
global::Microsoft.UI.Xaml.Application.Start((p) => {
var context = new global::Microsoft.UI.Dispatching.DispatcherQueueSynchronizationContext(global::Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread());
@@ -166,4 +165,5 @@ static void Main(string[] args)
}
}
#endif
+ }
}
diff --git a/src/WinUIExSample/Pages/OAuth.xaml.cs b/src/WinUIExSample/Pages/OAuth.xaml.cs
index 725c0c9..3e28de5 100644
--- a/src/WinUIExSample/Pages/OAuth.xaml.cs
+++ b/src/WinUIExSample/Pages/OAuth.xaml.cs
@@ -65,6 +65,10 @@ private async void DoOAuth(string responseType)
OAuthWindow.Visibility = Visibility.Visible;
try
{
+#if UNPACKAGED
+ // Packaged app uses appxmanifest for protocol activation. Unpackaged apps must manually register
+ Microsoft.Windows.AppLifecycle.ActivationRegistrationManager.RegisterForProtocolActivation("winuiex", "Assets\\Square150x150Logo.scale-100", "WinUI EX", null);
+#endif
var result = await WebAuthenticator.AuthenticateAsync(new Uri(authorizeUri), new Uri(callbackUri), oauthCancellationSource.Token);
MainWindow.BringToFront();
OAuthWindow.Visibility = Visibility.Collapsed;
@@ -75,6 +79,12 @@ private async void DoOAuth(string responseType)
catch (TaskCanceledException) {
Result.Text = "Sign in cancelled";
}
+ finally
+ {
+#if UNPACKAGED
+ Microsoft.Windows.AppLifecycle.ActivationRegistrationManager.UnregisterForProtocolActivation("winuiex", null);
+#endif
+ }
}
private void OAuthCancel_Click(object sender, RoutedEventArgs e)
diff --git a/src/WinUIExSample/WinUIExSample.csproj b/src/WinUIExSample/WinUIExSample.csproj
index 258cacb..3a674d9 100644
--- a/src/WinUIExSample/WinUIExSample.csproj
+++ b/src/WinUIExSample/WinUIExSample.csproj
@@ -18,6 +18,7 @@
10.0.22621.38
DISABLE_XAML_GENERATED_MAIN;$(DefineConstants)
+ UNPACKAGED;$(DefineConstants)
true