Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Avalonia.Controls.WebView.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@
<Project Path="samples/Avalonia.Xpf.Controls.WebView.Samples/Avalonia.Xpf.Controls.WebView.Samples.csproj" />
<Project Path="samples/NativeWebViewTest/NativeWebViewTest.csproj" />
</Folder>
<Folder Name="/Solution Items/">
<File Path=".editorconfig" />
<File Path=".gitignore" />
<File Path=".gitmodules" />
<File Path="LICENSE" />
<File Path="Readme.md" />
</Folder>
<Folder Name="/Tests/">
<Project Path="tests/Avalonia.Controls.WebView.Tests/Avalonia.Controls.WebView.Tests.csproj" />
</Folder>
Expand Down
7 changes: 7 additions & 0 deletions samples/Avalonia.Controls.WebView.Samples/MainView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@
<TextBox x:Name="RedirectUri"
UseFloatingPlaceholder="True"
PlaceholderText="Redirect Uri" />
<ComboBox x:Name="AuthMode"
SelectedIndex="0">
<ComboBoxItem Content="Auto" />
<ComboBoxItem Content="System" />
<ComboBoxItem Content="NativeWebDialog" />
<ComboBoxItem Content="Browser" />
</ComboBox>
<Button Content="Go" Click="WebAuthenticationBrokerButton_OnClick" />
<TextBox x:Name="CallbackUri"
AcceptsReturn="True"
Expand Down
33 changes: 31 additions & 2 deletions samples/Avalonia.Controls.WebView.Samples/MainView.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
#if AVALONIA
using Avalonia.Input;
using Avalonia.Interactivity;
Expand Down Expand Up @@ -214,7 +215,34 @@ private async void WebAuthenticationBrokerButton_OnClick(object? sender, RoutedE
#elif WPF
var topLevel = Window.GetWindow(this);
#endif
var options = new WebAuthenticatorOptions(new Uri(RequestUri.Text!), new Uri(RedirectUri.Text!, UriKind.RelativeOrAbsolute));
var requestUri = new Uri(RequestUri.Text!);

// Read the state back out of the request we are about to send, so an edited request uri
// stays consistent with the filter below.
var state = HttpUtility.ParseQueryString(requestUri.Query)["state"];

var options = new WebAuthenticatorOptions(requestUri, new Uri(RedirectUri.Text!, UriKind.RelativeOrAbsolute))
{
// The combo box order doesn't match the enum order, so map it explicitly.
// CA1416: this sample targets plain net10.0, so every mode looks reachable on every
// platform. Picking an unsupported one throws PlatformNotSupportedException at runtime.
#pragma warning disable CA1416
Mode = AuthMode.SelectedIndex switch
{
1 => WebAuthenticatorMode.System,
2 => WebAuthenticatorMode.NativeWebDialog,
3 => WebAuthenticatorMode.Browser,
_ => WebAuthenticatorMode.Auto
},
#pragma warning restore CA1416
BrowserOptions = new BrowserOptions
{
// The loopback listener is reachable by any local process, so ignore anything that
// doesn't carry the state we sent instead of letting it end the flow.
CallbackFilter = result =>
HttpUtility.ParseQueryString(result.CallbackUri.Query)["state"] == state
}
};

var result = await WebAuthenticationBroker.AuthenticateAsync(topLevel!, options);

Expand All @@ -236,7 +264,7 @@ private static (string requestUri, string redirectUri) GetGoogleAuth()
"com.AvaloniaUI.WebView.Samples:/oauth2redirect" :
OperatingSystem.IsBrowser() ?
href?.TrimEnd('/') + "/oauth2redirect" :
"http://localhost";
"http://127.0.0.1";
var clientId = OperatingSystem.IsIOS() ?
"457602913817-kd2547t40mrvqi63c4m7lphs5s6s5lt2.apps.googleusercontent.com" :
OperatingSystem.IsAndroid() ?
Expand All @@ -248,6 +276,7 @@ private static (string requestUri, string redirectUri) GetGoogleAuth()
var requestUri = "https://accounts.google.com/o/oauth2/auth?response_type=code&access_type=offline&scope=openid";
requestUri += "&client_id=" + clientId;
requestUri += "&redirect_uri=" + redirectUri;
requestUri += "&state=" + Guid.NewGuid().ToString("N");
return (requestUri, redirectUri);
}

Expand Down
6 changes: 6 additions & 0 deletions samples/Avalonia.Xpf.Controls.WebView.Samples/MainView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@
<StackPanel>
<TextBox x:Name="RequestUri" />
<TextBox x:Name="RedirectUri" />
<ComboBox x:Name="AuthMode"
SelectedIndex="0">
<ComboBoxItem Content="Default" />
<ComboBoxItem Content="NativeWebDialog" />
<ComboBoxItem Content="SystemBrowser" />
</ComboBox>
<Button Content="Go" Click="WebAuthenticationBrokerButton_OnClick" />
<TextBox x:Name="CallbackUri"
AcceptsReturn="True" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.IO;
using System.Net;

namespace Avalonia.Controls.Authentication;

/// <summary>
/// Represents the HTTP response sent to the browser after the authentication callback is received.
/// </summary>
public sealed class BrowserResponse
{
private Uri? _redirect;
internal BrowserResponse(Stream outputStream)
{
StatusCode = HttpStatusCode.OK;
OutputStream = outputStream;
}

/// <summary>
/// Gets or sets the HTTP status code of the response.
/// </summary>
public HttpStatusCode StatusCode { get; set; }

/// <summary>
/// Gets the stream to which the response content can be written.
/// </summary>
public Stream OutputStream { get; }

/// <summary>
/// Configures the response to redirect the browser to the specified URI.
/// Sets <see cref="StatusCode"/> to <see cref="HttpStatusCode.Found"/>.
/// </summary>
/// <param name="uri">Absolute uri to redirect the browser to.</param>
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="uri"/> is not absolute.</exception>
public void Redirect(Uri uri)
{
ArgumentNullException.ThrowIfNull(uri);

if (!uri.IsAbsoluteUri)
{
throw new ArgumentException("Redirect uri must be absolute.", nameof(uri));
}

_redirect = uri;
StatusCode = HttpStatusCode.Found;
}

internal Uri? ReadRedirect() => _redirect;
}
Loading
Loading