diff --git a/src/Auth0.OidcClient.MAUI/Auth0.OidcClient.MAUI.csproj b/src/Auth0.OidcClient.MAUI/Auth0.OidcClient.MAUI.csproj index 968e0c94..857de092 100644 --- a/src/Auth0.OidcClient.MAUI/Auth0.OidcClient.MAUI.csproj +++ b/src/Auth0.OidcClient.MAUI/Auth0.OidcClient.MAUI.csproj @@ -37,8 +37,7 @@ - - 2.2.0 + @@ -49,6 +48,7 @@ + @@ -62,5 +62,6 @@ + diff --git a/src/Auth0.OidcClient.MAUI/WebAuthenticatorBrowser.cs b/src/Auth0.OidcClient.MAUI/WebAuthenticatorBrowser.cs index 335fef65..0ea5ae7d 100644 --- a/src/Auth0.OidcClient.MAUI/WebAuthenticatorBrowser.cs +++ b/src/Auth0.OidcClient.MAUI/WebAuthenticatorBrowser.cs @@ -14,7 +14,40 @@ public async Task InvokeAsync(BrowserOptions options, Cancellatio try { #if WINDOWS - var result = await WinUIEx.WebAuthenticator.AuthenticateAsync(new Uri(options.StartUrl), new Uri(options.EndUrl)); + if (options.StartUrl.IndexOf("logout") > -1) + { + WinUIExEx.WebAuthenticator.BeforeProcessStart = (uri) => + { + var query = System.Web.HttpUtility.ParseQueryString(uri.Query); + // The state QueryString as generated by WinUIEx + var state = query["state"]; + // The original returnTo as configured externally + var returnTo = query["returnTo"]; + + + UriBuilder returnToBuilder = new UriBuilder(returnTo); + + // Get the original returnTo querystring params, so we can append state to it + var returnToQuery = System.Web.HttpUtility.ParseQueryString(new Uri(returnTo).Query); + // Append state as a querystring parameter to returnTo + // We need to escape it for it to be accepted + returnToQuery["state"] = Uri.EscapeDataString(state); + // Set the query again on the returnTo url + returnToBuilder.Query = returnToQuery.ToString(); + + // Update returnTo in the original query so that it now includes state + query["returnTo"] = returnToBuilder.Uri.ToString(); + + UriBuilder logoutUrlBuilder = new UriBuilder(uri); + // Set the query again on the logout url + logoutUrlBuilder.Query = query.ToString(); + + // Return the Uri so it can be used internally by WinUIEx to start the process and open the browser + return logoutUrlBuilder.Uri; + }; + } + + var result = await WinUIExEx.WebAuthenticator.AuthenticateAsync(new Uri(options.StartUrl), new Uri(options.EndUrl)); #else var result = await WebAuthenticator.Default.AuthenticateAsync(new Uri(options.StartUrl), new Uri(options.EndUrl)); #endif diff --git a/src/Auth0.OidcClient.MAUI/WinUIExEx/WebAuthenticator.cs b/src/Auth0.OidcClient.MAUI/WinUIExEx/WebAuthenticator.cs new file mode 100644 index 00000000..4d23cbde --- /dev/null +++ b/src/Auth0.OidcClient.MAUI/WinUIExEx/WebAuthenticator.cs @@ -0,0 +1,277 @@ +/// Based on https://github.com/dotMorten/WinUIEx but modified to work for our use-case untill it's solved in WinUIEx. + +#if WINDOWS +using WinUIEx; +namespace WinUIExEx +{ + /// + /// Handles OAuth redirection to the system browser and re-activation. + /// + /// + /// + /// Your app must be configured for OAuth. In you app package's Package.appxmanifest under Declarations, add a + /// Protocol declaration and add the scheme you registered for your application's oauth redirect url under "Name". + /// + /// + public sealed class WebAuthenticator + { + public static Func? BeforeProcessStart { get; set; } + + /// + /// Begin an authentication flow by navigating to the specified url and waiting for a callback/redirect to the callbackUrl scheme. + /// + /// Url to navigate to, beginning the authentication flow. + /// Expected callback url that the navigation flow will eventually redirect to. + /// Returns a result parsed out from the callback url. + /// Prior to calling this, a call to must be made during application startup. + /// + public static Task AuthenticateAsync(Uri authorizeUri, Uri callbackUri) => Instance.Authenticate(authorizeUri, callbackUri, CancellationToken.None); + + /// + /// Begin an authentication flow by navigating to the specified url and waiting for a callback/redirect to the callbackUrl scheme. + /// + /// Url to navigate to, beginning the authentication flow. + /// Expected callback url that the navigation flow will eventually redirect to. + /// Cancellation token. + /// Returns a result parsed out from the callback url. + /// Prior to calling this, a call to must be made during application startup. + /// + public static Task AuthenticateAsync(Uri authorizeUri, Uri callbackUri, CancellationToken cancellationToken) => Instance.Authenticate(authorizeUri, callbackUri, cancellationToken); + + private static readonly WebAuthenticator Instance = new WebAuthenticator(); + + private Dictionary> tasks = new Dictionary>(); + + private WebAuthenticator() + { + Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().Activated += CurrentAppInstance_Activated; + } + + private static bool IsUriProtocolDeclared(string scheme) + { + if (global::Windows.ApplicationModel.Package.Current is null) + return false; + var docPath = Path.Combine(global::Windows.ApplicationModel.Package.Current.InstalledLocation.Path, "AppxManifest.xml"); + var doc = XDocument.Load(docPath, LoadOptions.None); + var reader = doc.CreateReader(); + var namespaceManager = new XmlNamespaceManager(reader.NameTable); + namespaceManager.AddNamespace("x", "http://schemas.microsoft.com/appx/manifest/foundation/windows10"); + namespaceManager.AddNamespace("uap", "http://schemas.microsoft.com/appx/manifest/uap/windows10"); + + // Check if the protocol was declared + var decl = doc.Root?.XPathSelectElements($"//uap:Extension[@Category='windows.protocol']/uap:Protocol[@Name='{scheme}']", namespaceManager); + + return decl != null && decl.Any(); + } + + private static System.Collections.Specialized.NameValueCollection? GetState(Microsoft.Windows.AppLifecycle.AppActivationArguments activatedEventArgs) + { + if (activatedEventArgs.Kind == Microsoft.Windows.AppLifecycle.ExtendedActivationKind.Protocol && + activatedEventArgs.Data is IProtocolActivatedEventArgs protocolArgs) + { + return GetState(protocolArgs); + } + return null; + } + + private static NameValueCollection? GetState(IProtocolActivatedEventArgs protocolArgs) + { + NameValueCollection? vals = null; + try + { + vals = System.Web.HttpUtility.ParseQueryString(protocolArgs.Uri.Query); + } + catch { } + try + { + if (vals is null || !(vals["state"] is string)) + { + var fragment = protocolArgs.Uri.Fragment; + if (fragment.StartsWith("#")) + { + fragment = fragment.Substring(1); + } + vals = System.Web.HttpUtility.ParseQueryString(fragment); + } + } + catch { } + if (vals != null && vals["state"] is string state) + { + try + { + JsonObject? jsonObject; + + try + { + jsonObject = System.Text.Json.Nodes.JsonObject.Parse(state) as JsonObject; + } + catch (Exception e) + { + jsonObject = System.Text.Json.Nodes.JsonObject.Parse(Uri.UnescapeDataString(state)) as JsonObject; + } + + if (jsonObject is not null) + { + NameValueCollection vals2 = new NameValueCollection(jsonObject.Count); + if (jsonObject.ContainsKey("appInstanceId") && jsonObject["appInstanceId"] is JsonValue jvalue && jvalue.TryGetValue(out string? value)) + vals2.Add("appInstanceId", value); + if (jsonObject.ContainsKey("signinId") && jsonObject["signinId"] is JsonValue jvalue2 && jvalue2.TryGetValue(out string? value2)) + vals2.Add("signinId", value2); + return vals2; + } + } + catch { } + } + return null; + } + private static bool _oauthCheckWasPerformed; + + /// + /// Performs an OAuth protocol activation check and redirects activation to the correct application instance. + /// + /// If true, this application instance will not automatically be shut down. If set to + /// true ensure you handle instance exit, or you'll end up with multiple instances running. + /// true if the activation was redirected and this instance should be shut down, otherwise false. + /// + /// The call to this method should be done preferably in the Program.Main method, or the application constructor. It must be called + /// prior to using + /// + /// + public static bool CheckOAuthRedirectionActivation(bool skipShutDownOnActivation = false) + { + var activatedEventArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent()?.GetActivatedEventArgs(); + return CheckOAuthRedirectionActivation(activatedEventArgs, skipShutDownOnActivation); + } + + /// + /// Performs an OAuth protocol activation check and redirects activation to the correct application instance. + /// + /// The activation arguments + /// If true, this application instance will not automatically be shut down. If set to + /// true ensure you handle instance exit, or you'll end up with multiple instances running. + /// true if the activation was redirected and this instance should be shut down, otherwise false. + /// + /// The call to this method should be done preferably in the Program.Main method, or the application constructor. It must be called + /// prior to using + /// + /// + public static bool CheckOAuthRedirectionActivation(AppActivationArguments? activatedEventArgs, bool skipShutDownOnActivation = false) + { + _oauthCheckWasPerformed = true; + if (activatedEventArgs is null) + return false; + if (activatedEventArgs.Kind != Microsoft.Windows.AppLifecycle.ExtendedActivationKind.Protocol) + return false; + var state = GetState(activatedEventArgs); + if (state is not null && state["appInstanceId"] is string id && state["signinId"] is string signinId && !string.IsNullOrEmpty(signinId)) + { + var instance = Microsoft.Windows.AppLifecycle.AppInstance.GetInstances().Where(i => i.Key == id).FirstOrDefault(); + + if (instance is not null && !instance.IsCurrent) + { + // Redirect to correct instance and close this one + instance.RedirectActivationToAsync(activatedEventArgs).AsTask().Wait(); + if (!skipShutDownOnActivation) + System.Diagnostics.Process.GetCurrentProcess().Kill(); + return true; + } + } + else + { + var thisInstance = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent(); + if (string.IsNullOrEmpty(thisInstance.Key)) + { + Microsoft.Windows.AppLifecycle.AppInstance.FindOrRegisterForKey(Guid.NewGuid().ToString()); + } + } + return false; + } + + private void CurrentAppInstance_Activated(object? sender, Microsoft.Windows.AppLifecycle.AppActivationArguments e) + { + if (e.Kind == Microsoft.Windows.AppLifecycle.ExtendedActivationKind.Protocol) + { + if (e.Data is IProtocolActivatedEventArgs protocolArgs) + { + var vals = GetState(protocolArgs); + if (vals is not null && vals["signinId"] is string signinId) + { + ResumeSignin(protocolArgs.Uri, signinId); + } + } + } + } + + private void ResumeSignin(Uri callbackUri, string signinId) + { + if (signinId != null && tasks.ContainsKey(signinId)) + { + var task = tasks[signinId]; + tasks.Remove(signinId); + task.TrySetResult(callbackUri); + } + } + + private async Task Authenticate(Uri authorizeUri, Uri callbackUri, CancellationToken cancellationToken) + { + if (!_oauthCheckWasPerformed) + { + throw new InvalidOperationException("OAuth redirection check on app activation was not detected. Please make sure a call to WebAuthenticator.CheckOAuthRedirectionActivation was made during App creation."); + } + if (!Helpers.IsAppPackaged) + { + throw new InvalidOperationException("The WebAuthenticator requires a packaged app with an AppxManifest"); + } + 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(); + UriBuilder b = new UriBuilder(authorizeUri); + + var query = System.Web.HttpUtility.ParseQueryString(authorizeUri.Query); + var stateJson = new JsonObject + { + { "appInstanceId", Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().Key }, + { "signinId", taskId } + }; + if (query["state"] is string oldstate && !string.IsNullOrEmpty(oldstate)) + { + stateJson["state"] = oldstate; + } + + query["state"] = stateJson.ToJsonString(); + b.Query = query.ToString(); + authorizeUri = b.Uri; + + var tcs = new TaskCompletionSource(); + if (cancellationToken.CanBeCanceled) + { + cancellationToken.Register(() => + { + tcs.TrySetCanceled(); + if (tasks.ContainsKey(taskId)) + tasks.Remove(taskId); + }); + if (cancellationToken.IsCancellationRequested) + { + cancellationToken.ThrowIfCancellationRequested(); + } + } + + var newUri = BeforeProcessStart != null ? BeforeProcessStart(authorizeUri) : authorizeUri; + + var process = new System.Diagnostics.Process(); + process.StartInfo.FileName = "rundll32.exe"; + process.StartInfo.Arguments = $"url.dll,FileProtocolHandler \"{newUri.ToString().Replace("\"", "%22")}\""; + process.StartInfo.UseShellExecute = true; + process.Start(); + tasks.Add(taskId, tcs); + var uri = await tcs.Task.ConfigureAwait(false); + return new WebAuthenticatorResult(uri); + } + } +} + +#endif \ No newline at end of file diff --git a/test/Android/Resources/Resource.Designer.cs b/test/Android/Resources/Resource.Designer.cs index 53e75e9e..17dc5a0c 100644 --- a/test/Android/Resources/Resource.Designer.cs +++ b/test/Android/Resources/Resource.Designer.cs @@ -26,6 +26,187 @@ static Resource() public static void UpdateIdValues() { + global::Auth0.OidcClient.Resource.Attribute.alpha = global::AndroidTestApp.Resource.Attribute.alpha; + global::Auth0.OidcClient.Resource.Attribute.coordinatorLayoutStyle = global::AndroidTestApp.Resource.Attribute.coordinatorLayoutStyle; + global::Auth0.OidcClient.Resource.Attribute.font = global::AndroidTestApp.Resource.Attribute.font; + global::Auth0.OidcClient.Resource.Attribute.fontProviderAuthority = global::AndroidTestApp.Resource.Attribute.fontProviderAuthority; + global::Auth0.OidcClient.Resource.Attribute.fontProviderCerts = global::AndroidTestApp.Resource.Attribute.fontProviderCerts; + global::Auth0.OidcClient.Resource.Attribute.fontProviderFetchStrategy = global::AndroidTestApp.Resource.Attribute.fontProviderFetchStrategy; + global::Auth0.OidcClient.Resource.Attribute.fontProviderFetchTimeout = global::AndroidTestApp.Resource.Attribute.fontProviderFetchTimeout; + global::Auth0.OidcClient.Resource.Attribute.fontProviderPackage = global::AndroidTestApp.Resource.Attribute.fontProviderPackage; + global::Auth0.OidcClient.Resource.Attribute.fontProviderQuery = global::AndroidTestApp.Resource.Attribute.fontProviderQuery; + global::Auth0.OidcClient.Resource.Attribute.fontStyle = global::AndroidTestApp.Resource.Attribute.fontStyle; + global::Auth0.OidcClient.Resource.Attribute.fontVariationSettings = global::AndroidTestApp.Resource.Attribute.fontVariationSettings; + global::Auth0.OidcClient.Resource.Attribute.fontWeight = global::AndroidTestApp.Resource.Attribute.fontWeight; + global::Auth0.OidcClient.Resource.Attribute.keylines = global::AndroidTestApp.Resource.Attribute.keylines; + global::Auth0.OidcClient.Resource.Attribute.layout_anchor = global::AndroidTestApp.Resource.Attribute.layout_anchor; + global::Auth0.OidcClient.Resource.Attribute.layout_anchorGravity = global::AndroidTestApp.Resource.Attribute.layout_anchorGravity; + global::Auth0.OidcClient.Resource.Attribute.layout_behavior = global::AndroidTestApp.Resource.Attribute.layout_behavior; + global::Auth0.OidcClient.Resource.Attribute.layout_dodgeInsetEdges = global::AndroidTestApp.Resource.Attribute.layout_dodgeInsetEdges; + global::Auth0.OidcClient.Resource.Attribute.layout_insetEdge = global::AndroidTestApp.Resource.Attribute.layout_insetEdge; + global::Auth0.OidcClient.Resource.Attribute.layout_keyline = global::AndroidTestApp.Resource.Attribute.layout_keyline; + global::Auth0.OidcClient.Resource.Attribute.statusBarBackground = global::AndroidTestApp.Resource.Attribute.statusBarBackground; + global::Auth0.OidcClient.Resource.Attribute.ttcIndex = global::AndroidTestApp.Resource.Attribute.ttcIndex; + global::Auth0.OidcClient.Resource.Color.browser_actions_bg_grey = global::AndroidTestApp.Resource.Color.browser_actions_bg_grey; + global::Auth0.OidcClient.Resource.Color.browser_actions_divider_color = global::AndroidTestApp.Resource.Color.browser_actions_divider_color; + global::Auth0.OidcClient.Resource.Color.browser_actions_text_color = global::AndroidTestApp.Resource.Color.browser_actions_text_color; + global::Auth0.OidcClient.Resource.Color.browser_actions_title_color = global::AndroidTestApp.Resource.Color.browser_actions_title_color; + global::Auth0.OidcClient.Resource.Color.notification_action_color_filter = global::AndroidTestApp.Resource.Color.notification_action_color_filter; + global::Auth0.OidcClient.Resource.Color.notification_icon_bg_color = global::AndroidTestApp.Resource.Color.notification_icon_bg_color; + global::Auth0.OidcClient.Resource.Color.ripple_material_light = global::AndroidTestApp.Resource.Color.ripple_material_light; + global::Auth0.OidcClient.Resource.Color.secondary_text_default_material_light = global::AndroidTestApp.Resource.Color.secondary_text_default_material_light; + global::Auth0.OidcClient.Resource.Dimension.browser_actions_context_menu_max_width = global::AndroidTestApp.Resource.Dimension.browser_actions_context_menu_max_width; + global::Auth0.OidcClient.Resource.Dimension.browser_actions_context_menu_min_padding = global::AndroidTestApp.Resource.Dimension.browser_actions_context_menu_min_padding; + global::Auth0.OidcClient.Resource.Dimension.compat_button_inset_horizontal_material = global::AndroidTestApp.Resource.Dimension.compat_button_inset_horizontal_material; + global::Auth0.OidcClient.Resource.Dimension.compat_button_inset_vertical_material = global::AndroidTestApp.Resource.Dimension.compat_button_inset_vertical_material; + global::Auth0.OidcClient.Resource.Dimension.compat_button_padding_horizontal_material = global::AndroidTestApp.Resource.Dimension.compat_button_padding_horizontal_material; + global::Auth0.OidcClient.Resource.Dimension.compat_button_padding_vertical_material = global::AndroidTestApp.Resource.Dimension.compat_button_padding_vertical_material; + global::Auth0.OidcClient.Resource.Dimension.compat_control_corner_material = global::AndroidTestApp.Resource.Dimension.compat_control_corner_material; + global::Auth0.OidcClient.Resource.Dimension.compat_notification_large_icon_max_height = global::AndroidTestApp.Resource.Dimension.compat_notification_large_icon_max_height; + global::Auth0.OidcClient.Resource.Dimension.compat_notification_large_icon_max_width = global::AndroidTestApp.Resource.Dimension.compat_notification_large_icon_max_width; + global::Auth0.OidcClient.Resource.Dimension.notification_action_icon_size = global::AndroidTestApp.Resource.Dimension.notification_action_icon_size; + global::Auth0.OidcClient.Resource.Dimension.notification_action_text_size = global::AndroidTestApp.Resource.Dimension.notification_action_text_size; + global::Auth0.OidcClient.Resource.Dimension.notification_big_circle_margin = global::AndroidTestApp.Resource.Dimension.notification_big_circle_margin; + global::Auth0.OidcClient.Resource.Dimension.notification_content_margin_start = global::AndroidTestApp.Resource.Dimension.notification_content_margin_start; + global::Auth0.OidcClient.Resource.Dimension.notification_large_icon_height = global::AndroidTestApp.Resource.Dimension.notification_large_icon_height; + global::Auth0.OidcClient.Resource.Dimension.notification_large_icon_width = global::AndroidTestApp.Resource.Dimension.notification_large_icon_width; + global::Auth0.OidcClient.Resource.Dimension.notification_main_column_padding_top = global::AndroidTestApp.Resource.Dimension.notification_main_column_padding_top; + global::Auth0.OidcClient.Resource.Dimension.notification_media_narrow_margin = global::AndroidTestApp.Resource.Dimension.notification_media_narrow_margin; + global::Auth0.OidcClient.Resource.Dimension.notification_right_icon_size = global::AndroidTestApp.Resource.Dimension.notification_right_icon_size; + global::Auth0.OidcClient.Resource.Dimension.notification_right_side_padding_top = global::AndroidTestApp.Resource.Dimension.notification_right_side_padding_top; + global::Auth0.OidcClient.Resource.Dimension.notification_small_icon_background_padding = global::AndroidTestApp.Resource.Dimension.notification_small_icon_background_padding; + global::Auth0.OidcClient.Resource.Dimension.notification_small_icon_size_as_large = global::AndroidTestApp.Resource.Dimension.notification_small_icon_size_as_large; + global::Auth0.OidcClient.Resource.Dimension.notification_subtext_size = global::AndroidTestApp.Resource.Dimension.notification_subtext_size; + global::Auth0.OidcClient.Resource.Dimension.notification_top_pad = global::AndroidTestApp.Resource.Dimension.notification_top_pad; + global::Auth0.OidcClient.Resource.Dimension.notification_top_pad_large_text = global::AndroidTestApp.Resource.Dimension.notification_top_pad_large_text; + global::Auth0.OidcClient.Resource.Drawable.notification_action_background = global::AndroidTestApp.Resource.Drawable.notification_action_background; + global::Auth0.OidcClient.Resource.Drawable.notification_bg = global::AndroidTestApp.Resource.Drawable.notification_bg; + global::Auth0.OidcClient.Resource.Drawable.notification_bg_low = global::AndroidTestApp.Resource.Drawable.notification_bg_low; + global::Auth0.OidcClient.Resource.Drawable.notification_bg_low_normal = global::AndroidTestApp.Resource.Drawable.notification_bg_low_normal; + global::Auth0.OidcClient.Resource.Drawable.notification_bg_low_pressed = global::AndroidTestApp.Resource.Drawable.notification_bg_low_pressed; + global::Auth0.OidcClient.Resource.Drawable.notification_bg_normal = global::AndroidTestApp.Resource.Drawable.notification_bg_normal; + global::Auth0.OidcClient.Resource.Drawable.notification_bg_normal_pressed = global::AndroidTestApp.Resource.Drawable.notification_bg_normal_pressed; + global::Auth0.OidcClient.Resource.Drawable.notification_icon_background = global::AndroidTestApp.Resource.Drawable.notification_icon_background; + global::Auth0.OidcClient.Resource.Drawable.notification_template_icon_bg = global::AndroidTestApp.Resource.Drawable.notification_template_icon_bg; + global::Auth0.OidcClient.Resource.Drawable.notification_template_icon_low_bg = global::AndroidTestApp.Resource.Drawable.notification_template_icon_low_bg; + global::Auth0.OidcClient.Resource.Drawable.notification_tile_bg = global::AndroidTestApp.Resource.Drawable.notification_tile_bg; + global::Auth0.OidcClient.Resource.Drawable.notify_panel_notification_icon_bg = global::AndroidTestApp.Resource.Drawable.notify_panel_notification_icon_bg; + global::Auth0.OidcClient.Resource.Id.actions = global::AndroidTestApp.Resource.Id.actions; + global::Auth0.OidcClient.Resource.Id.action_container = global::AndroidTestApp.Resource.Id.action_container; + global::Auth0.OidcClient.Resource.Id.action_divider = global::AndroidTestApp.Resource.Id.action_divider; + global::Auth0.OidcClient.Resource.Id.action_image = global::AndroidTestApp.Resource.Id.action_image; + global::Auth0.OidcClient.Resource.Id.action_text = global::AndroidTestApp.Resource.Id.action_text; + global::Auth0.OidcClient.Resource.Id.all = global::AndroidTestApp.Resource.Id.all; + global::Auth0.OidcClient.Resource.Id.async = global::AndroidTestApp.Resource.Id.async; + global::Auth0.OidcClient.Resource.Id.blocking = global::AndroidTestApp.Resource.Id.blocking; + global::Auth0.OidcClient.Resource.Id.bottom = global::AndroidTestApp.Resource.Id.bottom; + global::Auth0.OidcClient.Resource.Id.browser_actions_header_text = global::AndroidTestApp.Resource.Id.browser_actions_header_text; + global::Auth0.OidcClient.Resource.Id.browser_actions_menu_items = global::AndroidTestApp.Resource.Id.browser_actions_menu_items; + global::Auth0.OidcClient.Resource.Id.browser_actions_menu_item_icon = global::AndroidTestApp.Resource.Id.browser_actions_menu_item_icon; + global::Auth0.OidcClient.Resource.Id.browser_actions_menu_item_text = global::AndroidTestApp.Resource.Id.browser_actions_menu_item_text; + global::Auth0.OidcClient.Resource.Id.browser_actions_menu_view = global::AndroidTestApp.Resource.Id.browser_actions_menu_view; + global::Auth0.OidcClient.Resource.Id.center = global::AndroidTestApp.Resource.Id.center; + global::Auth0.OidcClient.Resource.Id.center_horizontal = global::AndroidTestApp.Resource.Id.center_horizontal; + global::Auth0.OidcClient.Resource.Id.center_vertical = global::AndroidTestApp.Resource.Id.center_vertical; + global::Auth0.OidcClient.Resource.Id.chronometer = global::AndroidTestApp.Resource.Id.chronometer; + global::Auth0.OidcClient.Resource.Id.clip_horizontal = global::AndroidTestApp.Resource.Id.clip_horizontal; + global::Auth0.OidcClient.Resource.Id.clip_vertical = global::AndroidTestApp.Resource.Id.clip_vertical; + global::Auth0.OidcClient.Resource.Id.end = global::AndroidTestApp.Resource.Id.end; + global::Auth0.OidcClient.Resource.Id.fill = global::AndroidTestApp.Resource.Id.fill; + global::Auth0.OidcClient.Resource.Id.fill_horizontal = global::AndroidTestApp.Resource.Id.fill_horizontal; + global::Auth0.OidcClient.Resource.Id.fill_vertical = global::AndroidTestApp.Resource.Id.fill_vertical; + global::Auth0.OidcClient.Resource.Id.forever = global::AndroidTestApp.Resource.Id.forever; + global::Auth0.OidcClient.Resource.Id.icon = global::AndroidTestApp.Resource.Id.icon; + global::Auth0.OidcClient.Resource.Id.icon_group = global::AndroidTestApp.Resource.Id.icon_group; + global::Auth0.OidcClient.Resource.Id.info = global::AndroidTestApp.Resource.Id.info; + global::Auth0.OidcClient.Resource.Id.italic = global::AndroidTestApp.Resource.Id.italic; + global::Auth0.OidcClient.Resource.Id.left = global::AndroidTestApp.Resource.Id.left; + global::Auth0.OidcClient.Resource.Id.line1 = global::AndroidTestApp.Resource.Id.line1; + global::Auth0.OidcClient.Resource.Id.line3 = global::AndroidTestApp.Resource.Id.line3; + global::Auth0.OidcClient.Resource.Id.none = global::AndroidTestApp.Resource.Id.none; + global::Auth0.OidcClient.Resource.Id.normal = global::AndroidTestApp.Resource.Id.normal; + global::Auth0.OidcClient.Resource.Id.notification_background = global::AndroidTestApp.Resource.Id.notification_background; + global::Auth0.OidcClient.Resource.Id.notification_main_column = global::AndroidTestApp.Resource.Id.notification_main_column; + global::Auth0.OidcClient.Resource.Id.notification_main_column_container = global::AndroidTestApp.Resource.Id.notification_main_column_container; + global::Auth0.OidcClient.Resource.Id.right = global::AndroidTestApp.Resource.Id.right; + global::Auth0.OidcClient.Resource.Id.right_icon = global::AndroidTestApp.Resource.Id.right_icon; + global::Auth0.OidcClient.Resource.Id.right_side = global::AndroidTestApp.Resource.Id.right_side; + global::Auth0.OidcClient.Resource.Id.start = global::AndroidTestApp.Resource.Id.start; + global::Auth0.OidcClient.Resource.Id.tag_transition_group = global::AndroidTestApp.Resource.Id.tag_transition_group; + global::Auth0.OidcClient.Resource.Id.tag_unhandled_key_event_manager = global::AndroidTestApp.Resource.Id.tag_unhandled_key_event_manager; + global::Auth0.OidcClient.Resource.Id.tag_unhandled_key_listeners = global::AndroidTestApp.Resource.Id.tag_unhandled_key_listeners; + global::Auth0.OidcClient.Resource.Id.text = global::AndroidTestApp.Resource.Id.text; + global::Auth0.OidcClient.Resource.Id.text2 = global::AndroidTestApp.Resource.Id.text2; + global::Auth0.OidcClient.Resource.Id.time = global::AndroidTestApp.Resource.Id.time; + global::Auth0.OidcClient.Resource.Id.title = global::AndroidTestApp.Resource.Id.title; + global::Auth0.OidcClient.Resource.Id.top = global::AndroidTestApp.Resource.Id.top; + global::Auth0.OidcClient.Resource.Integer.status_bar_notification_info_maxnum = global::AndroidTestApp.Resource.Integer.status_bar_notification_info_maxnum; + global::Auth0.OidcClient.Resource.Layout.browser_actions_context_menu_page = global::AndroidTestApp.Resource.Layout.browser_actions_context_menu_page; + global::Auth0.OidcClient.Resource.Layout.browser_actions_context_menu_row = global::AndroidTestApp.Resource.Layout.browser_actions_context_menu_row; + global::Auth0.OidcClient.Resource.Layout.notification_action = global::AndroidTestApp.Resource.Layout.notification_action; + global::Auth0.OidcClient.Resource.Layout.notification_action_tombstone = global::AndroidTestApp.Resource.Layout.notification_action_tombstone; + global::Auth0.OidcClient.Resource.Layout.notification_template_custom_big = global::AndroidTestApp.Resource.Layout.notification_template_custom_big; + global::Auth0.OidcClient.Resource.Layout.notification_template_icon_group = global::AndroidTestApp.Resource.Layout.notification_template_icon_group; + global::Auth0.OidcClient.Resource.Layout.notification_template_part_chronometer = global::AndroidTestApp.Resource.Layout.notification_template_part_chronometer; + global::Auth0.OidcClient.Resource.Layout.notification_template_part_time = global::AndroidTestApp.Resource.Layout.notification_template_part_time; + global::Auth0.OidcClient.Resource.String.status_bar_notification_info_overflow = global::AndroidTestApp.Resource.String.status_bar_notification_info_overflow; + global::Auth0.OidcClient.Resource.Style.TextAppearance_Compat_Notification = global::AndroidTestApp.Resource.Style.TextAppearance_Compat_Notification; + global::Auth0.OidcClient.Resource.Style.TextAppearance_Compat_Notification_Info = global::AndroidTestApp.Resource.Style.TextAppearance_Compat_Notification_Info; + global::Auth0.OidcClient.Resource.Style.TextAppearance_Compat_Notification_Line2 = global::AndroidTestApp.Resource.Style.TextAppearance_Compat_Notification_Line2; + global::Auth0.OidcClient.Resource.Style.TextAppearance_Compat_Notification_Time = global::AndroidTestApp.Resource.Style.TextAppearance_Compat_Notification_Time; + global::Auth0.OidcClient.Resource.Style.TextAppearance_Compat_Notification_Title = global::AndroidTestApp.Resource.Style.TextAppearance_Compat_Notification_Title; + global::Auth0.OidcClient.Resource.Style.Widget_Compat_NotificationActionContainer = global::AndroidTestApp.Resource.Style.Widget_Compat_NotificationActionContainer; + global::Auth0.OidcClient.Resource.Style.Widget_Compat_NotificationActionText = global::AndroidTestApp.Resource.Style.Widget_Compat_NotificationActionText; + global::Auth0.OidcClient.Resource.Style.Widget_Support_CoordinatorLayout = global::AndroidTestApp.Resource.Style.Widget_Support_CoordinatorLayout; + global::Auth0.OidcClient.Resource.Styleable.ColorStateListItem = global::AndroidTestApp.Resource.Styleable.ColorStateListItem; + global::Auth0.OidcClient.Resource.Styleable.ColorStateListItem_alpha = global::AndroidTestApp.Resource.Styleable.ColorStateListItem_alpha; + global::Auth0.OidcClient.Resource.Styleable.ColorStateListItem_android_alpha = global::AndroidTestApp.Resource.Styleable.ColorStateListItem_android_alpha; + global::Auth0.OidcClient.Resource.Styleable.ColorStateListItem_android_color = global::AndroidTestApp.Resource.Styleable.ColorStateListItem_android_color; + global::Auth0.OidcClient.Resource.Styleable.CoordinatorLayout = global::AndroidTestApp.Resource.Styleable.CoordinatorLayout; + global::Auth0.OidcClient.Resource.Styleable.CoordinatorLayout_keylines = global::AndroidTestApp.Resource.Styleable.CoordinatorLayout_keylines; + global::Auth0.OidcClient.Resource.Styleable.CoordinatorLayout_Layout = global::AndroidTestApp.Resource.Styleable.CoordinatorLayout_Layout; + global::Auth0.OidcClient.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity = global::AndroidTestApp.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity; + global::Auth0.OidcClient.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor = global::AndroidTestApp.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor; + global::Auth0.OidcClient.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity = global::AndroidTestApp.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity; + global::Auth0.OidcClient.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior = global::AndroidTestApp.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior; + global::Auth0.OidcClient.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges = global::AndroidTestApp.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges; + global::Auth0.OidcClient.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge = global::AndroidTestApp.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge; + global::Auth0.OidcClient.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline = global::AndroidTestApp.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline; + global::Auth0.OidcClient.Resource.Styleable.CoordinatorLayout_statusBarBackground = global::AndroidTestApp.Resource.Styleable.CoordinatorLayout_statusBarBackground; + global::Auth0.OidcClient.Resource.Styleable.FontFamily = global::AndroidTestApp.Resource.Styleable.FontFamily; + global::Auth0.OidcClient.Resource.Styleable.FontFamilyFont = global::AndroidTestApp.Resource.Styleable.FontFamilyFont; + global::Auth0.OidcClient.Resource.Styleable.FontFamilyFont_android_font = global::AndroidTestApp.Resource.Styleable.FontFamilyFont_android_font; + global::Auth0.OidcClient.Resource.Styleable.FontFamilyFont_android_fontStyle = global::AndroidTestApp.Resource.Styleable.FontFamilyFont_android_fontStyle; + global::Auth0.OidcClient.Resource.Styleable.FontFamilyFont_android_fontVariationSettings = global::AndroidTestApp.Resource.Styleable.FontFamilyFont_android_fontVariationSettings; + global::Auth0.OidcClient.Resource.Styleable.FontFamilyFont_android_fontWeight = global::AndroidTestApp.Resource.Styleable.FontFamilyFont_android_fontWeight; + global::Auth0.OidcClient.Resource.Styleable.FontFamilyFont_android_ttcIndex = global::AndroidTestApp.Resource.Styleable.FontFamilyFont_android_ttcIndex; + global::Auth0.OidcClient.Resource.Styleable.FontFamilyFont_font = global::AndroidTestApp.Resource.Styleable.FontFamilyFont_font; + global::Auth0.OidcClient.Resource.Styleable.FontFamilyFont_fontStyle = global::AndroidTestApp.Resource.Styleable.FontFamilyFont_fontStyle; + global::Auth0.OidcClient.Resource.Styleable.FontFamilyFont_fontVariationSettings = global::AndroidTestApp.Resource.Styleable.FontFamilyFont_fontVariationSettings; + global::Auth0.OidcClient.Resource.Styleable.FontFamilyFont_fontWeight = global::AndroidTestApp.Resource.Styleable.FontFamilyFont_fontWeight; + global::Auth0.OidcClient.Resource.Styleable.FontFamilyFont_ttcIndex = global::AndroidTestApp.Resource.Styleable.FontFamilyFont_ttcIndex; + global::Auth0.OidcClient.Resource.Styleable.FontFamily_fontProviderAuthority = global::AndroidTestApp.Resource.Styleable.FontFamily_fontProviderAuthority; + global::Auth0.OidcClient.Resource.Styleable.FontFamily_fontProviderCerts = global::AndroidTestApp.Resource.Styleable.FontFamily_fontProviderCerts; + global::Auth0.OidcClient.Resource.Styleable.FontFamily_fontProviderFetchStrategy = global::AndroidTestApp.Resource.Styleable.FontFamily_fontProviderFetchStrategy; + global::Auth0.OidcClient.Resource.Styleable.FontFamily_fontProviderFetchTimeout = global::AndroidTestApp.Resource.Styleable.FontFamily_fontProviderFetchTimeout; + global::Auth0.OidcClient.Resource.Styleable.FontFamily_fontProviderPackage = global::AndroidTestApp.Resource.Styleable.FontFamily_fontProviderPackage; + global::Auth0.OidcClient.Resource.Styleable.FontFamily_fontProviderQuery = global::AndroidTestApp.Resource.Styleable.FontFamily_fontProviderQuery; + global::Auth0.OidcClient.Resource.Styleable.GradientColor = global::AndroidTestApp.Resource.Styleable.GradientColor; + global::Auth0.OidcClient.Resource.Styleable.GradientColorItem = global::AndroidTestApp.Resource.Styleable.GradientColorItem; + global::Auth0.OidcClient.Resource.Styleable.GradientColorItem_android_color = global::AndroidTestApp.Resource.Styleable.GradientColorItem_android_color; + global::Auth0.OidcClient.Resource.Styleable.GradientColorItem_android_offset = global::AndroidTestApp.Resource.Styleable.GradientColorItem_android_offset; + global::Auth0.OidcClient.Resource.Styleable.GradientColor_android_centerColor = global::AndroidTestApp.Resource.Styleable.GradientColor_android_centerColor; + global::Auth0.OidcClient.Resource.Styleable.GradientColor_android_centerX = global::AndroidTestApp.Resource.Styleable.GradientColor_android_centerX; + global::Auth0.OidcClient.Resource.Styleable.GradientColor_android_centerY = global::AndroidTestApp.Resource.Styleable.GradientColor_android_centerY; + global::Auth0.OidcClient.Resource.Styleable.GradientColor_android_endColor = global::AndroidTestApp.Resource.Styleable.GradientColor_android_endColor; + global::Auth0.OidcClient.Resource.Styleable.GradientColor_android_endX = global::AndroidTestApp.Resource.Styleable.GradientColor_android_endX; + global::Auth0.OidcClient.Resource.Styleable.GradientColor_android_endY = global::AndroidTestApp.Resource.Styleable.GradientColor_android_endY; + global::Auth0.OidcClient.Resource.Styleable.GradientColor_android_gradientRadius = global::AndroidTestApp.Resource.Styleable.GradientColor_android_gradientRadius; + global::Auth0.OidcClient.Resource.Styleable.GradientColor_android_startColor = global::AndroidTestApp.Resource.Styleable.GradientColor_android_startColor; + global::Auth0.OidcClient.Resource.Styleable.GradientColor_android_startX = global::AndroidTestApp.Resource.Styleable.GradientColor_android_startX; + global::Auth0.OidcClient.Resource.Styleable.GradientColor_android_startY = global::AndroidTestApp.Resource.Styleable.GradientColor_android_startY; + global::Auth0.OidcClient.Resource.Styleable.GradientColor_android_tileMode = global::AndroidTestApp.Resource.Styleable.GradientColor_android_tileMode; + global::Auth0.OidcClient.Resource.Styleable.GradientColor_android_type = global::AndroidTestApp.Resource.Styleable.GradientColor_android_type; } public partial class Attribute