* Initial work for WebAuthenticator API

* Fix page loaded in sample

* Fix weird generated item

* Fix error message

* Fix filename, too many .'s

* Remove unnecessary comment

* Tweak AppleSignIn API

* Cancel any previous waiting tasks

* Use WebAuthenticationBroker on UWP

* Make code more readable

* iOS10+ is only supported so remove check

* Move last fallback into TVOS

* Remove unnecessary duplicate attribute

* Change exception type.

* Better error message

* Make AppleSignIn accessible from shared code

* Added sample aspnet project for auth

* Apple Signin for iOS only for now

* Make auth sample use sample server

* Added some tests

* Make some methods private that shouldn't be public

* Add docs

* Increase device test timeout

* Add human interaction traits to some new tests

* Update devicetests cake

Updated to newer addins
Stop using cake bootstrappers

* Run device tests with cake dotnet core

* Bump xunit device runner

* Tests go back to netcore 2

* Bump xunit device runner in rest of devicetest projs

* Build that android app first!

* Cleanup web auth

- Change result type name
- Clean up result type properties
- Remove IsSupported from apple public api
- Throw not supported in public apple api on < iOS 13

* Update sample to check for iOS 13 independently

* Update docs

* Make code a bit more readable.

* More readable code changes

* Fix test

* Add some detection of callback activity

This adds some code to ensure the developer has subclassed `WebAuthenticatorCallbackActivity` and registered an appropriate intentfilter for it based on the `callbackUrl` being used.

Co-authored-by: James Montemagno <james.montemagno@gmail.com>
This commit is contained in:
Jonathan Dick 2020-01-30 21:54:06 -05:00 коммит произвёл GitHub
Родитель 72447a0c0a
Коммит ad22d9dea6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
52 изменённых файлов: 1818 добавлений и 402 удалений

2
.gitignore поставляемый
Просмотреть файл

@ -165,6 +165,8 @@ publish/
# in these scripts will be unencrypted
PublishScripts/
appsettings.Development.json
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore

Просмотреть файл

@ -59,7 +59,7 @@
<PackageReference Include="Xamarin.Android.Support.Core.Utils" Version="28.0.0.3" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.devices" Version="2.3.3" />
<PackageReference Include="xunit.runner.devices" Version="2.5.25" />
<PackageReference Include="UnitTests.HeadlessRunner" Version="2.0.0" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -25,7 +25,7 @@
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="Xamarin.Forms" Version="4.2.0.848062" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.devices" Version="2.3.3" />
<PackageReference Include="xunit.runner.devices" Version="2.5.25" />
<PackageReference Include="UnitTests.HeadlessRunner" Version="2.0.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<ProjectReference Include="..\..\Xamarin.Essentials\Xamarin.Essentials.csproj" />

Просмотреть файл

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Essentials;
using Xunit;
namespace DeviceTests
{
public class WebAuthenticator_Tests
{
[Theory]
[InlineData(
"https://xamarin-essentials-auth-sample.azurewebsites.net/redirect",
"xamarinessentials",
"testtokenvalue",
"testrefreshvalue",
99)]
[Trait(Traits.InteractionType, Traits.InteractionTypes.Human)]
public async Task Redirect(string urlBase, string callbackScheme, string accessToken, string refreshToken, int expires)
{
var r = await WebAuthenticator.AuthenticateAsync(
new Uri($"{urlBase}?access_token={accessToken}&refresh_token={refreshToken}&expires={expires}"),
new Uri($"{callbackScheme}://"));
Assert.Equal(accessToken, r?.AccessToken);
Assert.Equal(refreshToken, r?.RefreshToken);
Assert.NotNull(r?.ExpiresIn);
Assert.True(r?.ExpiresIn > DateTime.UtcNow);
}
[Theory]
[InlineData("xamarinessentials://#access_token=blah&refresh_token=blah2&expires=1", "blah", "blah2", "1")]
[InlineData("xamarinessentials://?access_token=blah&refresh_token=blah2&expires=1", "blah", "blah2", "1")]
[Trait(Traits.InteractionType, Traits.InteractionTypes.Human)]
public void ParseQueryString(string url, string accessToken, string refreshToken, string expires)
{
var r = WebUtils.ParseQueryString(url);
Assert.Equal(accessToken, r?["access_token"]);
Assert.Equal(refreshToken, r?["refresh_token"]);
Assert.Equal(expires, r?["expires"]);
}
}
}

Просмотреть файл

@ -117,7 +117,7 @@
<PackageReference Include="Xamarin.Forms" Version="4.2.0.848062" />
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="6.1.9" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.devices" Version="2.3.3" />
<PackageReference Include="xunit.runner.devices" Version="2.5.25" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -79,7 +79,7 @@
<ItemGroup>
<PackageReference Include="Xamarin.Forms" Version="4.2.0.848062" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.devices" Version="2.3.3" />
<PackageReference Include="xunit.runner.devices" Version="2.5.25" />
<PackageReference Include="UnitTests.HeadlessRunner" Version="2.0.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
</ItemGroup>

Просмотреть файл

@ -1,6 +1,6 @@
#addin nuget:?package=Cake.AppleSimulator
#addin nuget:?package=Cake.Android.Adb&version=2.0.6
#addin nuget:?package=Cake.Android.AvdManager&version=1.0.3
#addin nuget:?package=Cake.AppleSimulator&version=0.2.0
#addin nuget:?package=Cake.Android.Adb&version=3.2.0
#addin nuget:?package=Cake.Android.AvdManager&version=2.2.0
#addin nuget:?package=Cake.FileHelpers
var TARGET = Argument("target", "Default");
@ -17,14 +17,14 @@ var ANDROID_APK_PATH = "./DeviceTests.Android/bin/Release/com.xamarin.essentials
var ANDROID_TEST_RESULTS_PATH = "./xunit-android.xml";
var ANDROID_AVD = EnvironmentVariable("ANDROID_AVD") ?? "CABOODLE";
var ANDROID_PKG_NAME = "com.xamarin.essentials.devicetests";
var ANDROID_EMU_TARGET = EnvironmentVariable("ANDROID_EMU_TARGET") ?? "system-images;android-26;google_apis;x86";
var ANDROID_EMU_DEVICE = EnvironmentVariable("ANDROID_EMU_DEVICE") ?? "Nexus 5X";
var ANDROID_EMU_TARGET = EnvironmentVariable("ANDROID_EMU_TARGET") ?? "system-images;android-29;google_apis_playstore;x86_64";
var ANDROID_EMU_DEVICE = EnvironmentVariable("ANDROID_EMU_DEVICE") ?? "pixel";
var UWP_PROJ = "./DeviceTests.UWP/DeviceTests.UWP.csproj";
var UWP_TEST_RESULTS_PATH = "./xunit-uwp.xml";
var UWP_PACKAGE_ID = "ec0cc741-fd3e-485c-81be-68815c480690";
var TCP_LISTEN_TIMEOUT = 120;
var TCP_LISTEN_TIMEOUT = 240;
var TCP_LISTEN_PORT = 10578;
var TCP_LISTEN_HOST = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName())
.AddressList.First(f => f.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToString();
@ -180,37 +180,19 @@ Task ("test-android-emu")
.Does (() =>
{
var avdSettings = new AndroidAvdManagerToolSettings { SdkRoot = ANDROID_HOME };
Information ("Available AVDs:");
foreach (var avd in AndroidAvdListAvds (avdSettings)) {
Information (" - " + avd);
}
var emuSettings = new AndroidEmulatorToolSettings { SdkRoot = ANDROID_HOME };
// Create the AVD if necessary
if (EnvironmentVariable("ANDROID_SKIP_AVD_CREATE") == null) {
Information ("Creating AVD if necessary: {0}...", ANDROID_AVD);
if (!AndroidAvdListAvds (avdSettings).Any (a => a.Name == ANDROID_AVD))
AndroidAvdCreate (ANDROID_AVD, ANDROID_EMU_TARGET, ANDROID_EMU_DEVICE, force: true, settings: avdSettings);
}
// Delete AVD first, if it exists
Information ("Deleting AVD if exists: {0}...", ANDROID_AVD);
try { AndroidAvdDelete(ANDROID_AVD, avdSettings); }
catch { }
// We need to find `emulator` and the best way is to try within a specified ANDROID_HOME
var emulatorExt = IsRunningOnWindows() ? ".bat" : "";
string emulatorPath = "emulator" + emulatorExt;
if (ANDROID_HOME != null) {
var andHome = new DirectoryPath(ANDROID_HOME);
if (DirectoryExists(andHome)) {
emulatorPath = MakeAbsolute(andHome.Combine("tools").CombineWithFilePath("emulator" + emulatorExt)).FullPath;
if (!FileExists(emulatorPath))
emulatorPath = MakeAbsolute(andHome.Combine("emulator").CombineWithFilePath("emulator" + emulatorExt)).FullPath;
if (!FileExists(emulatorPath))
emulatorPath = "emulator" + emulatorExt;
}
}
// Start up the emulator by name
// Create the AVD
Information ("Creating AVD: {0}...", ANDROID_AVD);
AndroidAvdCreate (ANDROID_AVD, ANDROID_EMU_TARGET, ANDROID_EMU_DEVICE, force: true, settings: avdSettings);
Information ("Starting Emulator: {0}...", ANDROID_AVD);
var emu = StartAndReturnProcess (emulatorPath, new ProcessSettings {
Arguments = $"-avd {ANDROID_AVD}" });
var emulatorProcess = AndroidEmulatorStart(ANDROID_AVD, emuSettings);
var adbSettings = new AdbToolSettings { SdkRoot = ANDROID_HOME };
@ -265,8 +247,16 @@ Task ("test-android-emu")
AddPlatformToTestResults(ANDROID_TEST_RESULTS_PATH, "Android");
// Close emulator
emu.Kill();
// Stop / cleanup the emulator
AdbEmuKill(adbSettings);
System.Threading.Thread.Sleep(5000);
// Finally kill the process if it's not exited already
try { emulatorProcess.Kill(); }
catch { }
Information("Done Tests");
});

Просмотреть файл

@ -1,235 +0,0 @@
##########################################################################
# This is the Cake bootstrapper script for PowerShell.
# This file was downloaded from https://github.com/cake-build/resources
# Feel free to change this file to fit your needs.
##########################################################################
<#
.SYNOPSIS
This is a Powershell script to bootstrap a Cake build.
.DESCRIPTION
This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
and execute your Cake build script with the parameters you provide.
.PARAMETER Script
The build script to execute.
.PARAMETER Target
The build script target to run.
.PARAMETER Configuration
The build configuration to use.
.PARAMETER Verbosity
Specifies the amount of information to be displayed.
.PARAMETER ShowDescription
Shows description about tasks.
.PARAMETER DryRun
Performs a dry run.
.PARAMETER Experimental
Uses the nightly builds of the Roslyn script engine.
.PARAMETER Mono
Uses the Mono Compiler rather than the Roslyn script engine.
.PARAMETER SkipToolPackageRestore
Skips restoring of packages.
.PARAMETER ScriptArgs
Remaining arguments are added here.
.LINK
https://cakebuild.net
#>
[CmdletBinding()]
Param(
[string]$Script = "build.cake",
[string]$Target,
[string]$Configuration,
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
[string]$Verbosity,
[switch]$ShowDescription,
[Alias("WhatIf", "Noop")]
[switch]$DryRun,
[switch]$Experimental,
[switch]$Mono,
[switch]$SkipToolPackageRestore,
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
[string[]]$ScriptArgs
)
[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
function MD5HashFile([string] $filePath)
{
if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
{
return $null
}
[System.IO.Stream] $file = $null;
[System.Security.Cryptography.MD5] $md5 = $null;
try
{
$md5 = [System.Security.Cryptography.MD5]::Create()
$file = [System.IO.File]::OpenRead($filePath)
return [System.BitConverter]::ToString($md5.ComputeHash($file))
}
finally
{
if ($file -ne $null)
{
$file.Dispose()
}
}
}
function GetProxyEnabledWebClient
{
$wc = New-Object System.Net.WebClient
$proxy = [System.Net.WebRequest]::GetSystemWebProxy()
$proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials
$wc.Proxy = $proxy
return $wc
}
Write-Host "Preparing to run build script..."
if(!$PSScriptRoot){
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
}
$TOOLS_DIR = Join-Path $PSScriptRoot "tools"
$ADDINS_DIR = Join-Path $TOOLS_DIR "Addins"
$MODULES_DIR = Join-Path $TOOLS_DIR "Modules"
$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
$ADDINS_PACKAGES_CONFIG = Join-Path $ADDINS_DIR "packages.config"
$MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config"
# Make sure tools folder exists
if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
Write-Verbose -Message "Creating tools directory..."
New-Item -Path $TOOLS_DIR -Type directory | out-null
}
# Make sure that packages.config exist.
if (!(Test-Path $PACKAGES_CONFIG)) {
Write-Verbose -Message "Downloading packages.config..."
try {
$wc = GetProxyEnabledWebClient
$wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
Throw "Could not download packages.config."
}
}
# Try find NuGet.exe in path if not exists
if (!(Test-Path $NUGET_EXE)) {
Write-Verbose -Message "Trying to find nuget.exe in PATH..."
$existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) }
$NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
$NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
}
}
# Try download NuGet.exe if not exists
if (!(Test-Path $NUGET_EXE)) {
Write-Verbose -Message "Downloading NuGet.exe..."
try {
$wc = GetProxyEnabledWebClient
$wc.DownloadFile($NUGET_URL, $NUGET_EXE)
} catch {
Throw "Could not download NuGet.exe."
}
}
# Save nuget.exe path to environment to be available to child processed
$ENV:NUGET_EXE = $NUGET_EXE
# Restore tools from NuGet?
if(-Not $SkipToolPackageRestore.IsPresent) {
Push-Location
Set-Location $TOOLS_DIR
# Check for changes in packages.config and remove installed tools if true.
[string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
Write-Verbose -Message "Missing or changed package.config hash..."
Get-ChildItem -Exclude packages.config,nuget.exe,Cake.Bakery |
Remove-Item -Recurse
}
Write-Verbose -Message "Restoring tools from NuGet..."
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
if ($LASTEXITCODE -ne 0) {
Throw "An error occurred while restoring NuGet tools."
}
else
{
$md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
}
Write-Verbose -Message ($NuGetOutput | out-string)
Pop-Location
}
# Restore addins from NuGet
if (Test-Path $ADDINS_PACKAGES_CONFIG) {
Push-Location
Set-Location $ADDINS_DIR
Write-Verbose -Message "Restoring addins from NuGet..."
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`""
if ($LASTEXITCODE -ne 0) {
Throw "An error occurred while restoring NuGet addins."
}
Write-Verbose -Message ($NuGetOutput | out-string)
Pop-Location
}
# Restore modules from NuGet
if (Test-Path $MODULES_PACKAGES_CONFIG) {
Push-Location
Set-Location $MODULES_DIR
Write-Verbose -Message "Restoring modules from NuGet..."
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`""
if ($LASTEXITCODE -ne 0) {
Throw "An error occurred while restoring NuGet modules."
}
Write-Verbose -Message ($NuGetOutput | out-string)
Pop-Location
}
# Make sure that Cake has been installed.
if (!(Test-Path $CAKE_EXE)) {
Throw "Could not find Cake.exe at $CAKE_EXE"
}
# Build Cake arguments
$cakeArguments = @("$Script");
if ($Target) { $cakeArguments += "-target=$Target" }
if ($Configuration) { $cakeArguments += "-configuration=$Configuration" }
if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" }
if ($ShowDescription) { $cakeArguments += "-showdescription" }
if ($DryRun) { $cakeArguments += "-dryrun" }
if ($Experimental) { $cakeArguments += "-experimental" }
if ($Mono) { $cakeArguments += "-mono" }
$cakeArguments += $ScriptArgs
# Start Cake
Write-Host "Running build script..."
&$CAKE_EXE $cakeArguments
exit $LASTEXITCODE

Просмотреть файл

@ -1,117 +0,0 @@
#!/usr/bin/env bash
##########################################################################
# This is the Cake bootstrapper script for Linux and OS X.
# This file was downloaded from https://github.com/cake-build/resources
# Feel free to change this file to fit your needs.
##########################################################################
# Define directories.
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
TOOLS_DIR=$SCRIPT_DIR/tools
ADDINS_DIR=$TOOLS_DIR/Addins
MODULES_DIR=$TOOLS_DIR/Modules
NUGET_EXE=$TOOLS_DIR/nuget.exe
CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe
PACKAGES_CONFIG=$TOOLS_DIR/packages.config
PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum
ADDINS_PACKAGES_CONFIG=$ADDINS_DIR/packages.config
MODULES_PACKAGES_CONFIG=$MODULES_DIR/packages.config
# Define md5sum or md5 depending on Linux/OSX
MD5_EXE=
if [[ "$(uname -s)" == "Darwin" ]]; then
MD5_EXE="md5 -r"
else
MD5_EXE="md5sum"
fi
# Define default arguments.
SCRIPT="build.cake"
CAKE_ARGUMENTS=()
# Parse arguments.
for i in "$@"; do
case $1 in
-s|--script) SCRIPT="$2"; shift ;;
--) shift; CAKE_ARGUMENTS+=("$@"); break ;;
*) CAKE_ARGUMENTS+=("$1") ;;
esac
shift
done
# Make sure the tools folder exist.
if [ ! -d "$TOOLS_DIR" ]; then
mkdir "$TOOLS_DIR"
fi
# Make sure that packages.config exist.
if [ ! -f "$TOOLS_DIR/packages.config" ]; then
echo "Downloading packages.config..."
curl -Lsfo "$TOOLS_DIR/packages.config" https://cakebuild.net/download/bootstrapper/packages
if [ $? -ne 0 ]; then
echo "An error occurred while downloading packages.config."
exit 1
fi
fi
# Download NuGet if it does not exist.
if [ ! -f "$NUGET_EXE" ]; then
echo "Downloading NuGet..."
curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
if [ $? -ne 0 ]; then
echo "An error occurred while downloading nuget.exe."
exit 1
fi
fi
# Restore tools from NuGet.
pushd "$TOOLS_DIR" >/dev/null
if [ ! -f "$PACKAGES_CONFIG_MD5" ] || [ "$( cat "$PACKAGES_CONFIG_MD5" | sed 's/\r$//' )" != "$( $MD5_EXE "$PACKAGES_CONFIG" | awk '{ print $1 }' )" ]; then
find . -type d ! -name . ! -name 'Cake.Bakery' | xargs rm -rf
fi
mono "$NUGET_EXE" install -ExcludeVersion
if [ $? -ne 0 ]; then
echo "Could not restore NuGet tools."
exit 1
fi
$MD5_EXE "$PACKAGES_CONFIG" | awk '{ print $1 }' >| "$PACKAGES_CONFIG_MD5"
popd >/dev/null
# Restore addins from NuGet.
if [ -f "$ADDINS_PACKAGES_CONFIG" ]; then
pushd "$ADDINS_DIR" >/dev/null
mono "$NUGET_EXE" install -ExcludeVersion
if [ $? -ne 0 ]; then
echo "Could not restore NuGet addins."
exit 1
fi
popd >/dev/null
fi
# Restore modules from NuGet.
if [ -f "$MODULES_PACKAGES_CONFIG" ]; then
pushd "$MODULES_DIR" >/dev/null
mono "$NUGET_EXE" install -ExcludeVersion
if [ $? -ne 0 ]; then
echo "Could not restore NuGet modules."
exit 1
fi
popd >/dev/null
fi
# Make sure that Cake has been installed.
if [ ! -f "$CAKE_EXE" ]; then
echo "Could not find Cake.exe at '$CAKE_EXE'."
exit 1
fi
# Start Cake
exec mono "$CAKE_EXE" $SCRIPT "${CAKE_ARGUMENTS[@]}"

Просмотреть файл

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Sample.Server.WebAuthenticator
{
[Route("mobileauth")]
[ApiController]
public class AuthController : ControllerBase
{
const string callbackScheme = "xamarinessentials";
[HttpGet("{scheme}")]
public async Task Get([FromRoute]string scheme)
{
var auth = await Request.HttpContext.AuthenticateAsync(scheme);
if (!auth.Succeeded
|| auth?.Principal == null
|| !auth.Principal.Identities.Any(id => id.IsAuthenticated)
|| string.IsNullOrEmpty(auth.Properties.GetTokenValue("access_token")))
{
// Not authenticated, challenge
await Request.HttpContext.ChallengeAsync(scheme);
}
else
{
// Get parameters to send back to the callback
var qs = new Dictionary<string, string>
{
{ "access_token", auth.Properties.GetTokenValue("access_token") },
{ "refresh_token", auth.Properties.GetTokenValue("refresh_token") ?? string.Empty },
{ "expires", (auth.Properties.ExpiresUtc?.ToUnixTimeSeconds() ?? -1).ToString() }
};
// Build the result url
var url = callbackScheme + "://#" + string.Join(
"&",
qs.Where(kvp => !string.IsNullOrEmpty(kvp.Value) && kvp.Value != "-1")
.Select(kvp => $"{WebUtility.UrlEncode(kvp.Key)}={WebUtility.UrlEncode(kvp.Value)}"));
// Redirect to final url
Request.HttpContext.Response.Redirect(url);
}
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Sample.Server.WebAuthenticator
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

Просмотреть файл

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AspNet.Security.OAuth.Apple" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Facebook" Version="3.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="3.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="3.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Sample.Server.WebAuthenticator
{
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment webHostEnvironment)
{
Configuration = configuration;
WebHostEnvironment = webHostEnvironment;
}
IConfiguration Configuration { get; }
IWebHostEnvironment WebHostEnvironment { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddAuthentication()
.AddCookie()
.AddFacebook(fb =>
{
fb.AppId = Configuration["FacebookAppId"];
fb.AppSecret = Configuration["FacebookAppSecret"];
fb.SaveTokens = true;
})
.AddGoogle(g =>
{
g.ClientId = Configuration["GoogleClientId"];
g.ClientSecret = Configuration["GoogleClientSecret"];
g.SaveTokens = true;
})
.AddMicrosoftAccount(ms =>
{
ms.ClientId = Configuration["MicrosoftClientId"];
ms.ClientSecret = Configuration["MicrosoftClientSecret"];
ms.SaveTokens = true;
})
.AddApple(a =>
{
a.ClientId = Configuration["AppleClientId"];
a.KeyId = Configuration["AppleKeyId"];
a.TeamId = Configuration["AppleTeamId"];
a.UsePrivateKey(keyId
=> WebHostEnvironment.ContentRootFileProvider.GetFileInfo($"AuthKey_{keyId}.p8"));
a.SaveTokens = true;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}

Просмотреть файл

@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}

Просмотреть файл

@ -1,4 +1,5 @@
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Runtime;
@ -25,6 +26,13 @@ namespace Samples.Droid
LoadApplication(new App());
}
protected override void OnResume()
{
base.OnResume();
Xamarin.Essentials.Platform.OnResume();
}
protected override void OnDestroy()
{
base.OnDestroy();
@ -41,4 +49,10 @@ namespace Samples.Droid
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
[Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop)]
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable }, DataScheme = "xamarinessentials")]
public class WebAuthenticationCallbackActivity : Xamarin.Essentials.WebAuthenticatorCallbackActivity
{
}
}

Просмотреть файл

@ -20,6 +20,13 @@
</uap:DefaultTile>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
<Extensions>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="xamarinessentials">
<uap:DisplayName>Xamarin Essentials</uap:DisplayName>
</uap:Protocol>
</uap:Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>

Просмотреть файл

@ -16,5 +16,13 @@ namespace Samples.iOS
return base.FinishedLaunching(app, options);
}
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
if (Xamarin.Essentials.Platform.OpenUrl(app, url, options))
return true;
return base.OpenUrl(app, url, options);
}
}
}

Просмотреть файл

@ -63,6 +63,16 @@
<string>appcenter-APP_SECRET</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>xamarinessentials</string>
<key>CFBundleURLSchemes</key>
<array>
<string>xamarinessentials</string>
</array>
<key>CFBundleTypeRole</key>
<string>Editor</string>
</dict>
</array>
<key>NSCameraUsageDescription</key>
<string>Camera Photos</string>

Просмотреть файл

@ -0,0 +1,28 @@
<views:BasePage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:Samples.View"
xmlns:viewmodels="clr-namespace:Samples.ViewModel"
x:Class="Samples.View.WebAuthenticatorPage"
Title="Web Authenticator">
<views:BasePage.BindingContext>
<viewmodels:WebAuthenticatorViewModel />
</views:BasePage.BindingContext>
<StackLayout>
<Label Text="Quickly and easily authenticate and wait for callbacks on external urls." FontAttributes="Bold" Margin="12" />
<ScrollView>
<StackLayout Padding="12,0,12,12" Spacing="6">
<Button Text="Microsoft" Command="{Binding MicrosoftCommand}" BackgroundColor="#00A4EF" TextColor="White" />
<Button Text="Google" Command="{Binding GoogleCommand}" BackgroundColor="#d34836" TextColor="White" />
<Button Text="Facebook" Command="{Binding FacebookCommand}" BackgroundColor="#3b5998" TextColor="White" />
<Button Text="Apple" Command="{Binding AppleCommand}" BackgroundColor="Black" TextColor="White" />
<Label Text="Access Token:" FontAttributes="Bold" Margin="12,12,12,0" />
<Label Text="{Binding AccessToken}" TextColor="Red" FontAttributes="Italic" />
</StackLayout>
</ScrollView>
</StackLayout>
</views:BasePage>

Просмотреть файл

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Samples.View
{
public partial class WebAuthenticatorPage : BasePage
{
public WebAuthenticatorPage()
{
InitializeComponent();
}
}
}

Просмотреть файл

@ -204,6 +204,12 @@ namespace Samples.ViewModel
typeof(VibrationPage),
"Quickly and easily make the device vibrate.",
new[] { "vibration", "vibrate", "hardware", "device" }),
new SampleItem(
"🔓",
"Web Authenticator",
typeof(WebAuthenticatorPage),
"Quickly and easily authenticate and wait for a callback.",
new[] { "auth", "authenticate", "authenticator", "web", "webauth" }),
};
filteredItems = samples;
filterText = string.Empty;

Просмотреть файл

@ -0,0 +1,66 @@
using System;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace Samples.ViewModel
{
public class WebAuthenticatorViewModel : BaseViewModel
{
const string authenticationUrl = "https://xamarin-essentials-auth-sample.azurewebsites.net/mobileauth/";
public WebAuthenticatorViewModel()
{
MicrosoftCommand = new Command(async () => await OnAuthenticate("Microsoft"));
GoogleCommand = new Command(async () => await OnAuthenticate("Google"));
FacebookCommand = new Command(async () => await OnAuthenticate("Facebook"));
AppleCommand = new Command(async () => await OnAuthenticate("Apple"));
}
public ICommand MicrosoftCommand { get; }
public ICommand GoogleCommand { get; }
public ICommand FacebookCommand { get; }
public ICommand AppleCommand { get; }
string accessToken = string.Empty;
public string AccessToken
{
get => accessToken;
set => SetProperty(ref accessToken, value);
}
async Task OnAuthenticate(string scheme)
{
try
{
WebAuthenticatorResult r = null;
if (scheme.Equals("Apple")
&& DeviceInfo.Platform == DevicePlatform.iOS
&& DeviceInfo.Version.Major >= 13)
{
r = await AppleSignInAuthenticator.AuthenticateAsync();
}
else
{
var authUrl = new Uri(authenticationUrl + scheme);
var callbackUrl = new Uri("xamarinessentials://");
r = await WebAuthenticator.AuthenticateAsync(authUrl, callbackUrl);
}
AccessToken = r?.AccessToken;
}
catch (Exception ex)
{
AccessToken = string.Empty;
await DisplayAlertAsync($"Failed: {ex.Message}");
}
}
}
}

Просмотреть файл

@ -29,6 +29,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{6330
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{EE4495FA-9869-45CF-A11D-69F2218C6F62}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.Server.WebAuthenticator", "Samples\Sample.Server.WebAuthenticator\Sample.Server.WebAuthenticator.csproj", "{553D51A8-8E79-40D9-9FB3-9FC2386FF886}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -435,6 +437,34 @@ Global
{4BD0D88F-7E7A-4C3B-9E34-BF3717A8FF4B}.Release|x86.ActiveCfg = Release|x86
{4BD0D88F-7E7A-4C3B-9E34-BF3717A8FF4B}.Release|x86.Build.0 = Release|x86
{4BD0D88F-7E7A-4C3B-9E34-BF3717A8FF4B}.Release|x86.Deploy.0 = Release|x86
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|Any CPU.Build.0 = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|ARM.ActiveCfg = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|ARM.Build.0 = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|ARM64.Build.0 = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|iPhone.Build.0 = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|x64.ActiveCfg = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|x64.Build.0 = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|x86.ActiveCfg = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Debug|x86.Build.0 = Debug|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|Any CPU.ActiveCfg = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|Any CPU.Build.0 = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|ARM.ActiveCfg = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|ARM.Build.0 = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|ARM64.ActiveCfg = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|ARM64.Build.0 = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|iPhone.ActiveCfg = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|iPhone.Build.0 = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|x64.ActiveCfg = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|x64.Build.0 = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|x86.ActiveCfg = Release|Any CPU
{553D51A8-8E79-40D9-9FB3-9FC2386FF886}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -450,6 +480,7 @@ Global
{CB2072E0-A437-4811-AE17-16CAE0DDA1B1} = {EE4495FA-9869-45CF-A11D-69F2218C6F62}
{EE8FC716-27FC-405B-BD27-AF17E01A6671} = {EE4495FA-9869-45CF-A11D-69F2218C6F62}
{4BD0D88F-7E7A-4C3B-9E34-BF3717A8FF4B} = {EE4495FA-9869-45CF-A11D-69F2218C6F62}
{553D51A8-8E79-40D9-9FB3-9FC2386FF886} = {6330A0D0-E784-42A6-B975-451E609B907B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E012047E-6826-4037-8D1A-5606CD7D345D}

Просмотреть файл

@ -13,15 +13,12 @@ namespace Xamarin.Essentials
{
public static partial class Permissions
{
const string appManifestFilename = "AppxManifest.xml";
const string appManifestXmlns = "http://schemas.microsoft.com/appx/manifest/foundation/windows10";
public static bool IsCapabilityDeclared(string capabilityName)
{
var doc = XDocument.Load(appManifestFilename, LoadOptions.None);
var doc = XDocument.Load(Platform.AppManifestFilename, LoadOptions.None);
var reader = doc.CreateReader();
var namespaceManager = new XmlNamespaceManager(reader.NameTable);
namespaceManager.AddNamespace("x", appManifestXmlns);
namespaceManager.AddNamespace("x", Platform.AppManifestXmlns);
// If the manifest doesn't contain a capability we need, throw
return (!doc.Root.XPathSelectElements($"//x:DeviceCapability[@Name='{capabilityName}']", namespaceManager)?.Any() ?? false) &&

Просмотреть файл

@ -79,6 +79,9 @@ namespace Xamarin.Essentials
public static void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults) =>
Permissions.OnRequestPermissionsResult(requestCode, permissions, grantResults);
public static void OnResume() =>
WebAuthenticator.OnResume(null);
internal static bool HasSystemFeature(string systemFeature)
{
var packageManager = AppContext.PackageManager;

Просмотреть файл

@ -16,6 +16,11 @@ namespace Xamarin.Essentials
{
public static partial class Platform
{
#if __IOS__ || __TVOS__
public static bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
=> WebAuthenticator.OpenUrl(new Uri(url.AbsoluteString));
#endif
#if __IOS__
[DllImport(Constants.SystemLibrary, EntryPoint = "sysctlbyname")]
#else
@ -85,6 +90,27 @@ namespace Xamarin.Essentials
return viewController;
}
internal static UIWindow GetCurrentWindow(bool throwIfNull = true)
{
var window = UIApplication.SharedApplication.KeyWindow;
if (window.WindowLevel == UIWindowLevel.Normal)
return window;
if (window == null)
{
window = UIApplication.SharedApplication
.Windows
.OrderByDescending(w => w.WindowLevel)
.FirstOrDefault(w => w.RootViewController != null && w.WindowLevel == UIWindowLevel.Normal);
}
if (throwIfNull && window == null)
throw new InvalidOperationException("Could not find current window.");
return window;
}
#endif
#if __IOS__ || __WATCHOS__

Просмотреть файл

@ -1,7 +1,12 @@
namespace Xamarin.Essentials
using Windows.ApplicationModel.Activation;
namespace Xamarin.Essentials
{
public static partial class Platform
{
internal const string AppManifestFilename = "AppxManifest.xml";
internal const string AppManifestXmlns = "http://schemas.microsoft.com/appx/manifest/foundation/windows10";
public static string MapServiceToken { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xamarin.Essentials
{
static class WebUtils
{
internal static IDictionary<string, string> ParseQueryString(string url)
{
var d = new Dictionary<string, string>();
if (string.IsNullOrWhiteSpace(url) || (!url.Contains("?") && !url.Contains("#")))
return d;
var qsStartIndex = url.IndexOf('?');
if (qsStartIndex < 0)
qsStartIndex = url.IndexOf('#');
if (url.Length - 1 < qsStartIndex + 1)
return d;
var qs = url.Substring(qsStartIndex + 1);
var kvps = qs.Split('&');
if (kvps == null || !kvps.Any())
return d;
foreach (var kvp in kvps)
{
var pair = kvp.Split(new char[] { '=' }, 2);
if (pair == null || pair.Length != 2)
continue;
d[pair[0]] = pair[1];
}
return d;
}
internal static bool CanHandleCallback(Uri expectedUrl, Uri callbackUrl)
{
if (!callbackUrl.Scheme.Equals(expectedUrl.Scheme, StringComparison.OrdinalIgnoreCase))
return false;
if (!string.IsNullOrEmpty(expectedUrl.Host))
{
if (!callbackUrl.Host.Equals(expectedUrl.Host, StringComparison.OrdinalIgnoreCase))
return false;
}
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using AuthenticationServices;
using Foundation;
using UIKit;
namespace Xamarin.Essentials
{
public static partial class AppleSignInAuthenticator
{
static AuthManager authManager;
static async Task<WebAuthenticatorResult> PlatformAuthenticateAsync(AppleSignInOptions options)
{
if (DeviceInfo.Version.Major < 13)
throw new FeatureNotSupportedException();
var provider = new ASAuthorizationAppleIdProvider();
var req = provider.CreateRequest();
authManager = new AuthManager(Platform.GetCurrentWindow());
var scopes = new List<ASAuthorizationScope>();
if (options.IncludeFullNameScope)
scopes.Add(ASAuthorizationScope.FullName);
if (options.IncludeEmailScope)
scopes.Add(ASAuthorizationScope.Email);
req.RequestedScopes = scopes.ToArray();
var controller = new ASAuthorizationController(new[] { req });
controller.Delegate = authManager;
controller.PresentationContextProvider = authManager;
controller.PerformRequests();
var creds = await authManager.Credentials;
if (creds == null)
return null;
var appleAccount = new WebAuthenticatorResult();
appleAccount.Properties.Add("id_token", new NSString(creds.IdentityToken, NSStringEncoding.UTF8).ToString());
appleAccount.Properties.Add("email", creds.Email);
appleAccount.Properties.Add("user_id", creds.User);
appleAccount.Properties.Add("name", NSPersonNameComponentsFormatter.GetLocalizedString(creds.FullName, NSPersonNameComponentsFormatterStyle.Default, NSPersonNameComponentsFormatterOptions.Phonetic));
appleAccount.Properties.Add("realuserstatus", creds.RealUserStatus.ToString());
return appleAccount;
}
}
class AuthManager : NSObject, IASAuthorizationControllerDelegate, IASAuthorizationControllerPresentationContextProviding
{
public Task<ASAuthorizationAppleIdCredential> Credentials
=> tcsCredential?.Task;
TaskCompletionSource<ASAuthorizationAppleIdCredential> tcsCredential;
UIWindow presentingAnchor;
public AuthManager(UIWindow presentingWindow)
{
tcsCredential = new TaskCompletionSource<ASAuthorizationAppleIdCredential>();
presentingAnchor = presentingWindow;
}
public UIWindow GetPresentationAnchor(ASAuthorizationController controller)
=> presentingAnchor;
[Export("authorizationController:didCompleteWithAuthorization:")]
public void DidComplete(ASAuthorizationController controller, ASAuthorization authorization)
{
var creds = authorization.GetCredential<ASAuthorizationAppleIdCredential>();
tcsCredential?.TrySetResult(creds);
}
[Export("authorizationController:didCompleteWithError:")]
public void DidComplete(ASAuthorizationController controller, NSError error)
=> tcsCredential?.TrySetException(new Exception(error.LocalizedDescription));
}
}

Просмотреть файл

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Xamarin.Essentials
{
public static partial class AppleSignInAuthenticator
{
static Task<WebAuthenticatorResult> PlatformAuthenticateAsync(AppleSignInOptions options) =>
throw ExceptionUtils.NotSupportedOrImplementedException;
}
}

Просмотреть файл

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Xamarin.Essentials
{
public static partial class AppleSignInAuthenticator
{
public static Task<WebAuthenticatorResult> AuthenticateAsync(AppleSignInOptions options = null)
=> PlatformAuthenticateAsync(options ?? new AppleSignInOptions());
public class AppleSignInOptions
{
public bool IncludeFullNameScope { get; set; } = false;
public bool IncludeEmailScope { get; set; } = false;
}
}
}

Просмотреть файл

@ -0,0 +1,130 @@
using System;
using System.Threading.Tasks;
using Android.Content;
using Android.Support.CustomTabs;
namespace Xamarin.Essentials
{
public partial class WebAuthenticator
{
static TaskCompletionSource<WebAuthenticatorResult> tcsResponse = null;
static Uri uri = null;
static CustomTabsActivityManager CustomTabsActivityManager { get; set; }
static Uri RedirectUri { get; set; }
internal static Task<WebAuthenticatorResult> ResponseTask
=> tcsResponse?.Task;
internal static bool OnResume(Intent intent)
{
// If we aren't waiting on a task, don't handle the url
if (tcsResponse?.Task?.IsCompleted ?? true)
return false;
if (intent == null)
{
tcsResponse.TrySetCanceled();
return false;
}
try
{
var intentUri = new Uri(intent.Data.ToString());
// Only handle schemes we expect
if (!WebUtils.CanHandleCallback(RedirectUri, intentUri))
{
tcsResponse.TrySetException(new InvalidOperationException($"Invalid Redirect URI, detected `{intentUri}` but expected a URI in the format of `{RedirectUri}`"));
return false;
}
tcsResponse?.TrySetResult(new WebAuthenticatorResult(intentUri));
return true;
}
catch (Exception ex)
{
tcsResponse.TrySetException(ex);
return false;
}
}
static Task<WebAuthenticatorResult> PlatformAuthenticateAsync(Uri url, Uri callbackUrl)
{
var packageName = Platform.AppContext.PackageName;
// Create an intent to see if the app developer wired up the callback activity correctly
var intent = new Intent(Intent.ActionView);
intent.AddCategory(Intent.CategoryBrowsable);
intent.AddCategory(Intent.CategoryDefault);
intent.SetPackage(packageName);
intent.SetData(global::Android.Net.Uri.Parse(callbackUrl.OriginalString));
// Try to find the activity for the callback intent
var c = intent.ResolveActivity(Platform.AppContext.PackageManager);
if (c == null || c.PackageName != packageName)
throw new InvalidOperationException($"You must subclass the `{nameof(WebAuthenticatorCallbackActivity)}` and create an IntentFilter for it which matches your `{nameof(callbackUrl)}`.");
// Cancel any previous task that's still pending
if (tcsResponse?.Task != null && !tcsResponse.Task.IsCompleted)
tcsResponse.TrySetCanceled();
tcsResponse = new TaskCompletionSource<WebAuthenticatorResult>();
tcsResponse.Task.ContinueWith(t =>
{
// Cleanup when done
if (CustomTabsActivityManager != null)
{
CustomTabsActivityManager.NavigationEvent -= CustomTabsActivityManager_NavigationEvent;
CustomTabsActivityManager.CustomTabsServiceConnected -= CustomTabsActivityManager_CustomTabsServiceConnected;
try
{
CustomTabsActivityManager?.Client?.Dispose();
}
finally
{
CustomTabsActivityManager = null;
}
}
});
uri = url;
RedirectUri = callbackUrl;
CustomTabsActivityManager = CustomTabsActivityManager.From(Platform.GetCurrentActivity(true));
CustomTabsActivityManager.NavigationEvent += CustomTabsActivityManager_NavigationEvent;
CustomTabsActivityManager.CustomTabsServiceConnected += CustomTabsActivityManager_CustomTabsServiceConnected;
if (!CustomTabsActivityManager.BindService())
{
// Fall back to opening the system browser if necessary
var browserIntent = new Intent(Intent.ActionView, global::Android.Net.Uri.Parse(url.OriginalString));
Platform.CurrentActivity.StartActivity(browserIntent);
}
return WebAuthenticator.ResponseTask;
}
static void CustomTabsActivityManager_CustomTabsServiceConnected(ComponentName name, CustomTabsClient client)
{
var builder = new CustomTabsIntent.Builder(CustomTabsActivityManager.Session)
.SetShowTitle(true);
var customTabsIntent = builder.Build();
customTabsIntent.Intent.AddFlags(ActivityFlags.SingleTop | ActivityFlags.NoHistory | ActivityFlags.NewTask);
var ctx = Platform.CurrentActivity;
CustomTabsHelper.AddKeepAliveExtra(ctx, customTabsIntent.Intent);
customTabsIntent.LaunchUrl(ctx, global::Android.Net.Uri.Parse(uri.OriginalString));
}
static void CustomTabsActivityManager_NavigationEvent(int navigationEvent, global::Android.OS.Bundle extras) =>
System.Diagnostics.Debug.WriteLine($"CustomTabs.NavigationEvent: {navigationEvent}");
}
}

Просмотреть файл

@ -0,0 +1,190 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AuthenticationServices;
using Foundation;
#if __IOS__
using SafariServices;
#endif
using UIKit;
namespace Xamarin.Essentials
{
public static partial class WebAuthenticator
{
static TaskCompletionSource<WebAuthenticatorResult> tcsResponse;
static UIViewController currentViewController;
static Uri redirectUri;
internal static async Task<WebAuthenticatorResult> PlatformAuthenticateAsync(Uri url, Uri callbackUrl)
{
// Cancel any previous task that's still pending
if (tcsResponse?.Task != null && !tcsResponse.Task.IsCompleted)
tcsResponse.TrySetCanceled();
tcsResponse = new TaskCompletionSource<WebAuthenticatorResult>();
redirectUri = callbackUrl;
try
{
var scheme = redirectUri.Scheme;
if (!VerifyHasUrlSchemeOrDoesntRequire(scheme))
{
tcsResponse.TrySetException(new InvalidOperationException("You must register your URL Scheme handler in your app's Info.plist!"));
return await tcsResponse.Task;
}
#if __IOS__
void AuthSessionCallback(NSUrl cbUrl, NSError error)
{
if (error == null)
OpenUrl(cbUrl);
else
tcsResponse.TrySetException(new NSErrorException(error));
}
if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
{
var was = new ASWebAuthenticationSession(new NSUrl(url.OriginalString), scheme, AuthSessionCallback);
was.PresentationContextProvider = new ContextProvider(Platform.GetCurrentWindow());
was.Start();
return await tcsResponse.Task;
}
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
{
var sf = new SFAuthenticationSession(new NSUrl(url.OriginalString), scheme, AuthSessionCallback);
sf.Start();
return await tcsResponse.Task;
}
// THis is only on iOS9+ but we only support 10+ in Essentials anyway
var controller = new SFSafariViewController(new NSUrl(url.OriginalString), false)
{
Delegate = new NativeSFSafariViewControllerDelegate
{
DidFinishHandler = (svc) =>
{
// Cancel our task if it wasn't already marked as completed
if (!(tcsResponse?.Task?.IsCompleted ?? true))
tcsResponse.TrySetException(new OperationCanceledException());
}
},
};
currentViewController = controller;
await Platform.GetCurrentUIViewController().PresentViewControllerAsync(controller, true);
return await tcsResponse.Task;
#else
var opened = UIApplication.SharedApplication.OpenUrl(url);
if (!opened)
tcsResponse.TrySetException(new Exception("Error opening Safari"));
#endif
}
catch (Exception ex)
{
tcsResponse.TrySetException(ex);
}
return await tcsResponse.Task;
}
internal static bool OpenUrl(Uri uri)
{
// If we aren't waiting on a task, don't handle the url
if (tcsResponse?.Task?.IsCompleted ?? true)
return false;
try
{
// If we can't handle the url, don't
if (!WebUtils.CanHandleCallback(redirectUri, uri))
return false;
currentViewController?.DismissViewControllerAsync(true);
currentViewController = null;
tcsResponse.TrySetResult(new WebAuthenticatorResult(uri));
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return false;
}
static bool VerifyHasUrlSchemeOrDoesntRequire(string scheme)
{
// iOS11+ uses sfAuthenticationSession which handles its own url routing
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
return true;
var cleansed = scheme.Replace("://", string.Empty);
var schemes = GetCFBundleURLSchemes().ToList();
return schemes.Any(x => x != null && x.Equals(cleansed, StringComparison.InvariantCultureIgnoreCase));
}
static IEnumerable<string> GetCFBundleURLSchemes()
{
var schemes = new List<string>();
NSObject nsobj = null;
if (!NSBundle.MainBundle.InfoDictionary.TryGetValue((NSString)"CFBundleURLTypes", out nsobj))
return schemes;
var array = nsobj as NSArray;
if (array == null)
return schemes;
for (nuint i = 0; i < array.Count; i++)
{
var d = array.GetItem<NSDictionary>(i);
if (d == null || !d.Any())
continue;
if (!d.TryGetValue((NSString)"CFBundleURLSchemes", out nsobj))
continue;
var a = nsobj as NSArray;
var urls = ConvertToIEnumerable<NSString>(a).Select(x => x.ToString()).ToArray();
foreach (var url in urls)
schemes.Add(url);
}
return schemes;
}
static IEnumerable<T> ConvertToIEnumerable<T>(NSArray array)
where T : class, ObjCRuntime.INativeObject
{
for (nuint i = 0; i < array.Count; i++)
yield return array.GetItem<T>(i);
}
#if __IOS__
class NativeSFSafariViewControllerDelegate : SFSafariViewControllerDelegate
{
public Action<SFSafariViewController> DidFinishHandler { get; set; }
public override void DidFinish(SFSafariViewController controller) =>
DidFinishHandler?.Invoke(controller);
}
class ContextProvider : NSObject, IASWebAuthenticationPresentationContextProviding
{
public ContextProvider(UIWindow window) =>
Window = window;
public UIWindow Window { get; private set; }
public UIWindow GetPresentationAnchor(ASWebAuthenticationSession session)
=> Window;
}
#endif
}
}

Просмотреть файл

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Xamarin.Essentials
{
public static partial class WebAuthenticator
{
static Task<WebAuthenticatorResult> PlatformAuthenticateAsync(Uri url, Uri callbackUrl)
=> throw ExceptionUtils.NotSupportedOrImplementedException;
}
}

Просмотреть файл

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Xamarin.Essentials
{
public static partial class WebAuthenticator
{
public static Task<WebAuthenticatorResult> AuthenticateAsync(Uri url, Uri callbackUrl)
=> PlatformAuthenticateAsync(url, callbackUrl);
}
}

Просмотреть файл

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using Windows.Security.Authentication.Web;
namespace Xamarin.Essentials
{
public static partial class WebAuthenticator
{
static async Task<WebAuthenticatorResult> PlatformAuthenticateAsync(Uri url, Uri callbackUrl)
{
if (!IsUriProtocolDeclared(callbackUrl.Scheme))
throw new InvalidOperationException($"You need to declare the windows.protocol usage of the protocol/scheme `{callbackUrl.Scheme}` in your AppxManifest.xml file");
var r = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, url, callbackUrl);
switch (r.ResponseStatus)
{
case WebAuthenticationStatus.Success:
// For GET requests this is a URI:
var resultUri = new Uri(r.ResponseData.ToString());
return new WebAuthenticatorResult(resultUri);
case WebAuthenticationStatus.ErrorHttp:
throw new UnauthorizedAccessException();
default:
throw new Exception(r.ResponseData.ToString());
}
}
static bool IsUriProtocolDeclared(string scheme)
{
var doc = XDocument.Load(Platform.AppManifestFilename, LoadOptions.None);
var reader = doc.CreateReader();
var namespaceManager = new XmlNamespaceManager(reader.NameTable);
namespaceManager.AddNamespace("x", Platform.AppManifestXmlns);
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();
}
}
}

Просмотреть файл

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
using Android.App;
using Android.OS;
namespace Xamarin.Essentials
{
public abstract class WebAuthenticatorCallbackActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
WebAuthenticator.OnResume(Intent);
Finish();
}
}
}

Просмотреть файл

@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xamarin.Essentials
{
public class WebAuthenticatorResult
{
public WebAuthenticatorResult()
{
}
public WebAuthenticatorResult(Uri uri)
{
foreach (var kvp in WebUtils.ParseQueryString(uri.ToString()))
{
Properties[kvp.Key] = kvp.Value;
}
}
public WebAuthenticatorResult(IDictionary<string, string> properties)
{
foreach (var kvp in properties)
Properties[kvp.Key] = kvp.Value;
}
public DateTimeOffset Timestamp { get; set; } = new DateTimeOffset(DateTime.UtcNow);
public Dictionary<string, string> Properties { get; set; } = new Dictionary<string, string>();
public void Put(string key, string value)
=> Properties[key] = value;
public string Get(string key)
{
if (Properties.TryGetValue(key, out var v))
return v;
return default;
}
public string AccessToken
=> Get("access_token");
public string TokenType
=> Get("token_type");
public string RefreshToken
=> Get("refresh_token");
public DateTimeOffset? RefreshTokenExpiresIn
{
get
{
if (Properties.TryGetValue("refresh_token_expires_in", out var v))
{
if (int.TryParse(v, out var i))
return Timestamp.AddSeconds(i);
}
return null;
}
}
public DateTimeOffset? ExpiresIn
{
get
{
if (Properties.TryGetValue("expires_in", out var v))
{
if (int.TryParse(v, out var i))
return Timestamp.AddSeconds(i);
}
return null;
}
}
}
}

Просмотреть файл

@ -6,7 +6,7 @@ variables:
NugetPackageVersion: '$(CurrentSemanticVersion)'
MONO_VERSION: 6_4_0
XCODE_VERSION: 11.1
NETCORE_VERSION: '3.0.x'
NETCORE_VERSION: '3.1.x'
NETCORE_TEST_VERSION: '2.2.x'
IOS_SIM_NAME: 'iPhone 11'
IOS_SIM_RUNTIME: 'com.apple.CoreSimulator.SimRuntime.iOS-13-2'
@ -200,7 +200,8 @@ jobs:
provProfileSecureFile: 'Components iOS Provisioning.mobileprovision'
- bash: |
cd DeviceTests
sh ./build.sh --target=test-ios-emu --settings_skipverification=true --verbosity=diagnostic
dotnet tool install -g cake.tool --version 0.36.0
dotnet cake --target=test-ios-emu --settings_skipverification=true --verbosity=diagnostic
displayName: 'Run Device Tests - iOS'
- task: PublishTestResults@2
displayName: 'Publish Test Results'
@ -237,7 +238,8 @@ jobs:
PATH="$ANDROID_HOME/tools/bin:$PATH"
PATH="$ANDROID_HOME/emulator:$PATH"
cd DeviceTests
sh ./build.sh --target=test-android-emu --settings_skipverification=true --verbosity=diagnostic
dotnet tool install -g cake.tool --version 0.36.0
dotnet cake --target=test-android-emu --settings_skipverification=true --verbosity=diagnostic
displayName: 'Run Device Tests - Android'
- task: PublishTestResults@2
displayName: 'Publish Test Results'

Просмотреть файл

@ -47,6 +47,14 @@
<Member Id="P:Xamarin.Essentials.AppInfo.Version" />
<Member Id="P:Xamarin.Essentials.AppInfo.VersionString" />
</Type>
<Type Name="Xamarin.Essentials.AppleSignInAuthenticator" Id="T:Xamarin.Essentials.AppleSignInAuthenticator">
<Member Id="M:Xamarin.Essentials.AppleSignInAuthenticator.AuthenticateAsync(Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions)" />
</Type>
<Type Name="Xamarin.Essentials.AppleSignInAuthenticator/AppleSignInOptions" Id="T:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions">
<Member Id="M:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.#ctor" />
<Member Id="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeEmailScope" />
<Member Id="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeFullNameScope" />
</Type>
<Type Name="Xamarin.Essentials.AppTheme" Id="T:Xamarin.Essentials.AppTheme">
<Member Id="F:Xamarin.Essentials.AppTheme.Dark" />
<Member Id="F:Xamarin.Essentials.AppTheme.Light" />
@ -668,6 +676,7 @@
<Member Id="M:Xamarin.Essentials.Platform.Init(Android.App.Activity,Android.OS.Bundle)" />
<Member Id="M:Xamarin.Essentials.Platform.Init(Android.App.Application)" />
<Member Id="M:Xamarin.Essentials.Platform.OnRequestPermissionsResult(System.Int32,System.String[],Android.Content.PM.Permission[])" />
<Member Id="M:Xamarin.Essentials.Platform.OnResume" />
<Member Id="M:Xamarin.Essentials.Platform.WaitForActivityAsync(System.Threading.CancellationToken)" />
<Member Id="P:Xamarin.Essentials.Platform.AppContext" />
<Member Id="P:Xamarin.Essentials.Platform.CurrentActivity" />
@ -846,5 +855,26 @@
<Member Id="M:Xamarin.Essentials.Vibration.Vibrate(System.Double)" />
<Member Id="M:Xamarin.Essentials.Vibration.Vibrate(System.TimeSpan)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticator" Id="T:Xamarin.Essentials.WebAuthenticator">
<Member Id="M:Xamarin.Essentials.WebAuthenticator.AuthenticateAsync(System.Uri,System.Uri)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticatorCallbackActivity" Id="T:Xamarin.Essentials.WebAuthenticatorCallbackActivity">
<Member Id="M:Xamarin.Essentials.WebAuthenticatorCallbackActivity.#ctor" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorCallbackActivity.OnCreate(Android.OS.Bundle)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticatorResult" Id="T:Xamarin.Essentials.WebAuthenticatorResult">
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Collections.Generic.IDictionary{System.String,System.String})" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Uri)" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.Get(System.String)" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.Put(System.String,System.String)" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.AccessToken" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.ExpiresIn" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.Properties" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshToken" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshTokenExpiresIn" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.Timestamp" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.TokenType" />
</Type>
</Namespace>
</Framework>

Просмотреть файл

@ -34,6 +34,14 @@
<Member Id="P:Xamarin.Essentials.AppInfo.Version" />
<Member Id="P:Xamarin.Essentials.AppInfo.VersionString" />
</Type>
<Type Name="Xamarin.Essentials.AppleSignInAuthenticator" Id="T:Xamarin.Essentials.AppleSignInAuthenticator">
<Member Id="M:Xamarin.Essentials.AppleSignInAuthenticator.AuthenticateAsync(Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions)" />
</Type>
<Type Name="Xamarin.Essentials.AppleSignInAuthenticator/AppleSignInOptions" Id="T:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions">
<Member Id="M:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.#ctor" />
<Member Id="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeEmailScope" />
<Member Id="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeFullNameScope" />
</Type>
<Type Name="Xamarin.Essentials.AppTheme" Id="T:Xamarin.Essentials.AppTheme">
<Member Id="F:Xamarin.Essentials.AppTheme.Dark" />
<Member Id="F:Xamarin.Essentials.AppTheme.Light" />
@ -669,6 +677,7 @@
</Type>
<Type Name="Xamarin.Essentials.Platform" Id="T:Xamarin.Essentials.Platform">
<Member Id="M:Xamarin.Essentials.Platform.GetCurrentUIViewController" />
<Member Id="M:Xamarin.Essentials.Platform.OpenUrl(UIKit.UIApplication,Foundation.NSUrl,Foundation.NSDictionary)" />
</Type>
<Type Name="Xamarin.Essentials.PointExtensions" Id="T:Xamarin.Essentials.PointExtensions">
<Member Id="M:Xamarin.Essentials.PointExtensions.ToSystemPoint(CoreGraphics.CGPoint)" />
@ -846,5 +855,22 @@
<Member Id="M:Xamarin.Essentials.Vibration.Vibrate(System.Double)" />
<Member Id="M:Xamarin.Essentials.Vibration.Vibrate(System.TimeSpan)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticator" Id="T:Xamarin.Essentials.WebAuthenticator">
<Member Id="M:Xamarin.Essentials.WebAuthenticator.AuthenticateAsync(System.Uri,System.Uri)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticatorResult" Id="T:Xamarin.Essentials.WebAuthenticatorResult">
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Collections.Generic.IDictionary{System.String,System.String})" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Uri)" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.Get(System.String)" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.Put(System.String,System.String)" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.AccessToken" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.ExpiresIn" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.Properties" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshToken" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshTokenExpiresIn" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.Timestamp" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.TokenType" />
</Type>
</Namespace>
</Framework>

Просмотреть файл

@ -34,6 +34,14 @@
<Member Id="P:Xamarin.Essentials.AppInfo.Version" />
<Member Id="P:Xamarin.Essentials.AppInfo.VersionString" />
</Type>
<Type Name="Xamarin.Essentials.AppleSignInAuthenticator" Id="T:Xamarin.Essentials.AppleSignInAuthenticator">
<Member Id="M:Xamarin.Essentials.AppleSignInAuthenticator.AuthenticateAsync(Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions)" />
</Type>
<Type Name="Xamarin.Essentials.AppleSignInAuthenticator/AppleSignInOptions" Id="T:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions">
<Member Id="M:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.#ctor" />
<Member Id="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeEmailScope" />
<Member Id="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeFullNameScope" />
</Type>
<Type Name="Xamarin.Essentials.AppTheme" Id="T:Xamarin.Essentials.AppTheme">
<Member Id="F:Xamarin.Essentials.AppTheme.Dark" />
<Member Id="F:Xamarin.Essentials.AppTheme.Light" />
@ -635,6 +643,7 @@
</Type>
<Type Name="Xamarin.Essentials.Platform" Id="T:Xamarin.Essentials.Platform">
<Member Id="M:Xamarin.Essentials.Platform.GetCurrentUIViewController" />
<Member Id="M:Xamarin.Essentials.Platform.OpenUrl(UIKit.UIApplication,Foundation.NSUrl,Foundation.NSDictionary)" />
</Type>
<Type Name="Xamarin.Essentials.PointExtensions" Id="T:Xamarin.Essentials.PointExtensions">
<Member Id="M:Xamarin.Essentials.PointExtensions.ToSystemPoint(CoreGraphics.CGPoint)" />
@ -808,5 +817,22 @@
<Member Id="M:Xamarin.Essentials.Vibration.Vibrate(System.Double)" />
<Member Id="M:Xamarin.Essentials.Vibration.Vibrate(System.TimeSpan)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticator" Id="T:Xamarin.Essentials.WebAuthenticator">
<Member Id="M:Xamarin.Essentials.WebAuthenticator.AuthenticateAsync(System.Uri,System.Uri)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticatorResult" Id="T:Xamarin.Essentials.WebAuthenticatorResult">
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Collections.Generic.IDictionary{System.String,System.String})" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Uri)" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.Get(System.String)" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.Put(System.String,System.String)" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.AccessToken" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.ExpiresIn" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.Properties" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshToken" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshTokenExpiresIn" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.Timestamp" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.TokenType" />
</Type>
</Namespace>
</Framework>

Просмотреть файл

@ -34,6 +34,14 @@
<Member Id="P:Xamarin.Essentials.AppInfo.Version" />
<Member Id="P:Xamarin.Essentials.AppInfo.VersionString" />
</Type>
<Type Name="Xamarin.Essentials.AppleSignInAuthenticator" Id="T:Xamarin.Essentials.AppleSignInAuthenticator">
<Member Id="M:Xamarin.Essentials.AppleSignInAuthenticator.AuthenticateAsync(Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions)" />
</Type>
<Type Name="Xamarin.Essentials.AppleSignInAuthenticator/AppleSignInOptions" Id="T:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions">
<Member Id="M:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.#ctor" />
<Member Id="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeEmailScope" />
<Member Id="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeFullNameScope" />
</Type>
<Type Name="Xamarin.Essentials.AppTheme" Id="T:Xamarin.Essentials.AppTheme">
<Member Id="F:Xamarin.Essentials.AppTheme.Dark" />
<Member Id="F:Xamarin.Essentials.AppTheme.Light" />
@ -808,5 +816,22 @@
<Member Id="M:Xamarin.Essentials.Vibration.Vibrate(System.Double)" />
<Member Id="M:Xamarin.Essentials.Vibration.Vibrate(System.TimeSpan)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticator" Id="T:Xamarin.Essentials.WebAuthenticator">
<Member Id="M:Xamarin.Essentials.WebAuthenticator.AuthenticateAsync(System.Uri,System.Uri)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticatorResult" Id="T:Xamarin.Essentials.WebAuthenticatorResult">
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Collections.Generic.IDictionary{System.String,System.String})" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Uri)" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.Get(System.String)" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.Put(System.String,System.String)" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.AccessToken" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.ExpiresIn" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.Properties" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshToken" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshTokenExpiresIn" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.Timestamp" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.TokenType" />
</Type>
</Namespace>
</Framework>

Просмотреть файл

@ -34,6 +34,14 @@
<Member Id="P:Xamarin.Essentials.AppInfo.Version" />
<Member Id="P:Xamarin.Essentials.AppInfo.VersionString" />
</Type>
<Type Name="Xamarin.Essentials.AppleSignInAuthenticator" Id="T:Xamarin.Essentials.AppleSignInAuthenticator">
<Member Id="M:Xamarin.Essentials.AppleSignInAuthenticator.AuthenticateAsync(Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions)" />
</Type>
<Type Name="Xamarin.Essentials.AppleSignInAuthenticator/AppleSignInOptions" Id="T:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions">
<Member Id="M:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.#ctor" />
<Member Id="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeEmailScope" />
<Member Id="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeFullNameScope" />
</Type>
<Type Name="Xamarin.Essentials.AppTheme" Id="T:Xamarin.Essentials.AppTheme">
<Member Id="F:Xamarin.Essentials.AppTheme.Dark" />
<Member Id="F:Xamarin.Essentials.AppTheme.Light" />
@ -818,5 +826,22 @@
<Member Id="M:Xamarin.Essentials.Vibration.Vibrate(System.Double)" />
<Member Id="M:Xamarin.Essentials.Vibration.Vibrate(System.TimeSpan)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticator" Id="T:Xamarin.Essentials.WebAuthenticator">
<Member Id="M:Xamarin.Essentials.WebAuthenticator.AuthenticateAsync(System.Uri,System.Uri)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticatorResult" Id="T:Xamarin.Essentials.WebAuthenticatorResult">
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Collections.Generic.IDictionary{System.String,System.String})" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Uri)" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.Get(System.String)" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.Put(System.String,System.String)" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.AccessToken" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.ExpiresIn" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.Properties" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshToken" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshTokenExpiresIn" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.Timestamp" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.TokenType" />
</Type>
</Namespace>
</Framework>

Просмотреть файл

@ -34,6 +34,14 @@
<Member Id="P:Xamarin.Essentials.AppInfo.Version" />
<Member Id="P:Xamarin.Essentials.AppInfo.VersionString" />
</Type>
<Type Name="Xamarin.Essentials.AppleSignInAuthenticator" Id="T:Xamarin.Essentials.AppleSignInAuthenticator">
<Member Id="M:Xamarin.Essentials.AppleSignInAuthenticator.AuthenticateAsync(Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions)" />
</Type>
<Type Name="Xamarin.Essentials.AppleSignInAuthenticator/AppleSignInOptions" Id="T:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions">
<Member Id="M:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.#ctor" />
<Member Id="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeEmailScope" />
<Member Id="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeFullNameScope" />
</Type>
<Type Name="Xamarin.Essentials.AppTheme" Id="T:Xamarin.Essentials.AppTheme">
<Member Id="F:Xamarin.Essentials.AppTheme.Dark" />
<Member Id="F:Xamarin.Essentials.AppTheme.Light" />
@ -782,5 +790,22 @@
<Member Id="M:Xamarin.Essentials.Vibration.Vibrate(System.Double)" />
<Member Id="M:Xamarin.Essentials.Vibration.Vibrate(System.TimeSpan)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticator" Id="T:Xamarin.Essentials.WebAuthenticator">
<Member Id="M:Xamarin.Essentials.WebAuthenticator.AuthenticateAsync(System.Uri,System.Uri)" />
</Type>
<Type Name="Xamarin.Essentials.WebAuthenticatorResult" Id="T:Xamarin.Essentials.WebAuthenticatorResult">
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Collections.Generic.IDictionary{System.String,System.String})" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Uri)" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.Get(System.String)" />
<Member Id="M:Xamarin.Essentials.WebAuthenticatorResult.Put(System.String,System.String)" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.AccessToken" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.ExpiresIn" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.Properties" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshToken" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshTokenExpiresIn" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.Timestamp" />
<Member Id="P:Xamarin.Essentials.WebAuthenticatorResult.TokenType" />
</Type>
</Namespace>
</Framework>

Просмотреть файл

@ -0,0 +1,74 @@
<Type Name="AppleSignInAuthenticator+AppleSignInOptions" FullName="Xamarin.Essentials.AppleSignInAuthenticator+AppleSignInOptions">
<TypeSignature Language="C#" Value="public class AppleSignInAuthenticator.AppleSignInOptions" />
<TypeSignature Language="ILAsm" Value=".class nested public auto ansi beforefieldinit AppleSignInAuthenticator/AppleSignInOptions extends System.Object" />
<TypeSignature Language="DocId" Value="T:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions" />
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Object</BaseTypeName>
</Base>
<Interfaces />
<Docs>
<summary>Native Apple Sign In Options</summary>
<remarks>
<para />
</remarks>
</Docs>
<Members>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public AppleSignInOptions ();" />
<MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
<MemberSignature Language="DocId" Value="M:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.#ctor" />
<MemberType>Constructor</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Parameters />
<Docs>
<summary>
<para />
</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="IncludeEmailScope">
<MemberSignature Language="C#" Value="public bool IncludeEmailScope { get; set; }" />
<MemberSignature Language="ILAsm" Value=".property instance bool IncludeEmailScope" />
<MemberSignature Language="DocId" Value="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeEmailScope" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Boolean</ReturnType>
</ReturnValue>
<Docs>
<summary>Request email scope.</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="IncludeFullNameScope">
<MemberSignature Language="C#" Value="public bool IncludeFullNameScope { get; set; }" />
<MemberSignature Language="ILAsm" Value=".property instance bool IncludeFullNameScope" />
<MemberSignature Language="DocId" Value="P:Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions.IncludeFullNameScope" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Boolean</ReturnType>
</ReturnValue>
<Docs>
<summary>Request full name scope.</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
</Members>
</Type>

Просмотреть файл

@ -0,0 +1,41 @@
<Type Name="AppleSignInAuthenticator" FullName="Xamarin.Essentials.AppleSignInAuthenticator">
<TypeSignature Language="C#" Value="public static class AppleSignInAuthenticator" />
<TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit AppleSignInAuthenticator extends System.Object" />
<TypeSignature Language="DocId" Value="T:Xamarin.Essentials.AppleSignInAuthenticator" />
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Object</BaseTypeName>
</Base>
<Interfaces />
<Docs>
<summary>Native Apple Sign In authentication API.</summary>
<remarks>This API is only supported on iOS 13.0+ and should not be called on other devices at runtime.</remarks>
</Docs>
<Members>
<Member MemberName="AuthenticateAsync">
<MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;Xamarin.Essentials.WebAuthenticatorResult&gt; AuthenticateAsync (Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions options = null);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;class Xamarin.Essentials.WebAuthenticatorResult&gt; AuthenticateAsync(class Xamarin.Essentials.AppleSignInAuthenticator/AppleSignInOptions options) cil managed" />
<MemberSignature Language="DocId" Value="M:Xamarin.Essentials.AppleSignInAuthenticator.AuthenticateAsync(Xamarin.Essentials.AppleSignInAuthenticator.AppleSignInOptions)" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Threading.Tasks.Task&lt;Xamarin.Essentials.WebAuthenticatorResult&gt;</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="options" Type="Xamarin.Essentials.AppleSignInAuthenticator+AppleSignInOptions" />
</Parameters>
<Docs>
<param name="options">To be added.</param>
<summary>Performs a native Apple Sign In authentication request.</summary>
<returns>To be added.</returns>
<remarks>To be added.</remarks>
</Docs>
</Member>
</Members>
</Type>

Просмотреть файл

@ -190,6 +190,50 @@
</remarks>
</Docs>
</Member>
<Member MemberName="OnResume">
<MemberSignature Language="C#" Value="public static void OnResume ();" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig void OnResume() cil managed" />
<MemberSignature Language="DocId" Value="M:Xamarin.Essentials.Platform.OnResume" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters />
<Docs>
<summary>Pass Resume lifecycle events of your main activity to be used for internal API handling.</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="OpenUrl">
<MemberSignature Language="C#" Value="public static bool OpenUrl (UIKit.UIApplication app, Foundation.NSUrl url, Foundation.NSDictionary options);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig bool OpenUrl(class UIKit.UIApplication app, class Foundation.NSUrl url, class Foundation.NSDictionary options) cil managed" />
<MemberSignature Language="DocId" Value="M:Xamarin.Essentials.Platform.OpenUrl(UIKit.UIApplication,Foundation.NSUrl,Foundation.NSDictionary)" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Boolean</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="app" Type="UIKit.UIApplication" Index="0" FrameworkAlternate="xamarin-essentials-ios;xamarin-essentials-tvos" />
<Parameter Name="url" Type="Foundation.NSUrl" Index="1" FrameworkAlternate="xamarin-essentials-ios;xamarin-essentials-tvos" />
<Parameter Name="options" Type="Foundation.NSDictionary" Index="2" FrameworkAlternate="xamarin-essentials-ios;xamarin-essentials-tvos" />
</Parameters>
<Docs>
<param name="app">To be added.</param>
<param name="url">To be added.</param>
<param name="options">To be added.</param>
<summary>Passes the OpenUrl callback of your app to be used for internal API handling.</summary>
<returns>To be added.</returns>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="WaitForActivityAsync">
<MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;Android.App.Activity&gt; WaitForActivityAsync (System.Threading.CancellationToken cancelToken = null);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;class Android.App.Activity&gt; WaitForActivityAsync(valuetype System.Threading.CancellationToken cancelToken) cil managed" />

Просмотреть файл

@ -0,0 +1,45 @@
<Type Name="WebAuthenticator" FullName="Xamarin.Essentials.WebAuthenticator">
<TypeSignature Language="C#" Value="public static class WebAuthenticator" />
<TypeSignature Language="ILAsm" Value=".class public auto ansi abstract sealed beforefieldinit WebAuthenticator extends System.Object" />
<TypeSignature Language="DocId" Value="T:Xamarin.Essentials.WebAuthenticator" />
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Object</BaseTypeName>
</Base>
<Interfaces />
<Docs>
<summary>A web navigation API intended to be used for Authentication with external web services such as OAuth.</summary>
<remarks>This API helps with navigating to a start URL and waiting for a callback URL to the app.  Your app must be registered to handle the callback scheme you provide in the call to authenticate.</remarks>
</Docs>
<Members>
<Member MemberName="AuthenticateAsync">
<MemberSignature Language="C#" Value="public static System.Threading.Tasks.Task&lt;Xamarin.Essentials.WebAuthenticatorResult&gt; AuthenticateAsync (Uri url, Uri callbackUrl);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig class System.Threading.Tasks.Task`1&lt;class Xamarin.Essentials.WebAuthenticatorResult&gt; AuthenticateAsync(class System.Uri url, class System.Uri callbackUrl) cil managed" />
<MemberSignature Language="DocId" Value="M:Xamarin.Essentials.WebAuthenticator.AuthenticateAsync(System.Uri,System.Uri)" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Threading.Tasks.Task&lt;Xamarin.Essentials.WebAuthenticatorResult&gt;</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="url" Type="System.Uri" />
<Parameter Name="callbackUrl" Type="System.Uri" />
</Parameters>
<Docs>
<param name="url">Url to navigate to, beginning the authentication flow.</param>
<param name="callbackUrl">Expected callback url that the navigation flow will eventually redirect to.</param>
<summary>Begin an authentication flow by navigating to the specified url and waiting for a callback/redirect to the callbackUrl scheme.</summary>
<returns>Returns a result parsed out from the callback url.</returns>
<remarks>
<para />
</remarks>
</Docs>
</Member>
</Members>
</Type>

Просмотреть файл

@ -0,0 +1,59 @@
<Type Name="WebAuthenticatorCallbackActivity" FullName="Xamarin.Essentials.WebAuthenticatorCallbackActivity">
<TypeSignature Language="C#" Value="public abstract class WebAuthenticatorCallbackActivity : Android.App.Activity" />
<TypeSignature Language="ILAsm" Value=".class public auto ansi abstract beforefieldinit WebAuthenticatorCallbackActivity extends Android.App.Activity" />
<TypeSignature Language="DocId" Value="T:Xamarin.Essentials.WebAuthenticatorCallbackActivity" />
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>Android.App.Activity</BaseTypeName>
</Base>
<Interfaces />
<Docs>
<summary>The activity meant to be subclassed and implemented to receive callbacks on Android.</summary>
<remarks>This activity should be decorated with the appropriate Intent Filter to handle callbacks to the appropriate URI scheme.</remarks>
</Docs>
<Members>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="protected WebAuthenticatorCallbackActivity ();" />
<MemberSignature Language="ILAsm" Value=".method familyhidebysig specialname rtspecialname instance void .ctor() cil managed" />
<MemberSignature Language="DocId" Value="M:Xamarin.Essentials.WebAuthenticatorCallbackActivity.#ctor" />
<MemberType>Constructor</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Parameters />
<Docs>
<summary>
<para />
</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="OnCreate">
<MemberSignature Language="C#" Value="protected override void OnCreate (Android.OS.Bundle savedInstanceState);" />
<MemberSignature Language="ILAsm" Value=".method familyhidebysig virtual instance void OnCreate(class Android.OS.Bundle savedInstanceState) cil managed" />
<MemberSignature Language="DocId" Value="M:Xamarin.Essentials.WebAuthenticatorCallbackActivity.OnCreate(Android.OS.Bundle)" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="savedInstanceState" Type="Android.OS.Bundle" />
</Parameters>
<Docs>
<param name="savedInstanceState">To be added.</param>
<summary>
<para />
</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
</Members>
</Type>

Просмотреть файл

@ -0,0 +1,225 @@
<Type Name="WebAuthenticatorResult" FullName="Xamarin.Essentials.WebAuthenticatorResult">
<TypeSignature Language="C#" Value="public class WebAuthenticatorResult" />
<TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit WebAuthenticatorResult extends System.Object" />
<TypeSignature Language="DocId" Value="T:Xamarin.Essentials.WebAuthenticatorResult" />
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Object</BaseTypeName>
</Base>
<Interfaces />
<Docs>
<summary>Web Authenticator Result parsed from the callback Url.</summary>
<remarks>All of the querystring or url fragment properties are parsed into a dictionary and can be accessed by their key.</remarks>
</Docs>
<Members>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public WebAuthenticatorResult ();" />
<MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
<MemberSignature Language="DocId" Value="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor" />
<MemberType>Constructor</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Parameters />
<Docs>
<summary>
<para />
</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public WebAuthenticatorResult (System.Collections.Generic.IDictionary&lt;string,string&gt; properties);" />
<MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Collections.Generic.IDictionary`2&lt;string, string&gt; properties) cil managed" />
<MemberSignature Language="DocId" Value="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Collections.Generic.IDictionary{System.String,System.String})" />
<MemberType>Constructor</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Parameters>
<Parameter Name="properties" Type="System.Collections.Generic.IDictionary&lt;System.String,System.String&gt;" />
</Parameters>
<Docs>
<param name="properties">To be added.</param>
<summary>Create a new instance from an existing dictionary.</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName=".ctor">
<MemberSignature Language="C#" Value="public WebAuthenticatorResult (Uri uri);" />
<MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor(class System.Uri uri) cil managed" />
<MemberSignature Language="DocId" Value="M:Xamarin.Essentials.WebAuthenticatorResult.#ctor(System.Uri)" />
<MemberType>Constructor</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Parameters>
<Parameter Name="uri" Type="System.Uri" />
</Parameters>
<Docs>
<param name="uri">To be added.</param>
<summary>Create a new instance by parsing a Uri's querystring parameters.</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="AccessToken">
<MemberSignature Language="C#" Value="public string AccessToken { get; }" />
<MemberSignature Language="ILAsm" Value=".property instance string AccessToken" />
<MemberSignature Language="DocId" Value="P:Xamarin.Essentials.WebAuthenticatorResult.AccessToken" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>The value for the `access_token` key.</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="ExpiresIn">
<MemberSignature Language="C#" Value="public Nullable&lt;DateTimeOffset&gt; ExpiresIn { get; }" />
<MemberSignature Language="ILAsm" Value=".property instance valuetype System.Nullable`1&lt;valuetype System.DateTimeOffset&gt; ExpiresIn" />
<MemberSignature Language="DocId" Value="P:Xamarin.Essentials.WebAuthenticatorResult.ExpiresIn" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Nullable&lt;System.DateTimeOffset&gt;</ReturnType>
</ReturnValue>
<Docs>
<summary>The expiry date as calculated by the timestamp of when the result was created plus the value in seconds for the `expires_in` key.</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="Get">
<MemberSignature Language="C#" Value="public string Get (string key);" />
<MemberSignature Language="ILAsm" Value=".method public hidebysig instance string Get(string key) cil managed" />
<MemberSignature Language="DocId" Value="M:Xamarin.Essentials.WebAuthenticatorResult.Get(System.String)" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="key" Type="System.String" />
</Parameters>
<Docs>
<param name="key">To be added.</param>
<summary>Gets a value for a given key from the dictionary.</summary>
<returns>To be added.</returns>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="Properties">
<MemberSignature Language="C#" Value="public System.Collections.Generic.Dictionary&lt;string,string&gt; Properties { get; set; }" />
<MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.Dictionary`2&lt;string, string&gt; Properties" />
<MemberSignature Language="DocId" Value="P:Xamarin.Essentials.WebAuthenticatorResult.Properties" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Collections.Generic.Dictionary&lt;System.String,System.String&gt;</ReturnType>
</ReturnValue>
<Docs>
<summary>The dictionary of parsed key/value pairs.</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="Put">
<MemberSignature Language="C#" Value="public void Put (string key, string value);" />
<MemberSignature Language="ILAsm" Value=".method public hidebysig instance void Put(string key, string value) cil managed" />
<MemberSignature Language="DocId" Value="M:Xamarin.Essentials.WebAuthenticatorResult.Put(System.String,System.String)" />
<MemberType>Method</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Void</ReturnType>
</ReturnValue>
<Parameters>
<Parameter Name="key" Type="System.String" />
<Parameter Name="value" Type="System.String" />
</Parameters>
<Docs>
<param name="key">To be added.</param>
<param name="value">To be added.</param>
<summary>Puts a key/value pair into the dictionary.</summary>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="RefreshToken">
<MemberSignature Language="C#" Value="public string RefreshToken { get; }" />
<MemberSignature Language="ILAsm" Value=".property instance string RefreshToken" />
<MemberSignature Language="DocId" Value="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshToken" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.String</ReturnType>
</ReturnValue>
<Docs>
<summary>The value for the `refresh_token` key.</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="RefreshTokenExpiresIn">
<MemberSignature Language="C#" Value="public Nullable&lt;DateTimeOffset&gt; RefreshTokenExpiresIn { get; }" />
<MemberSignature Language="ILAsm" Value=".property instance valuetype System.Nullable`1&lt;valuetype System.DateTimeOffset&gt; RefreshTokenExpiresIn" />
<MemberSignature Language="DocId" Value="P:Xamarin.Essentials.WebAuthenticatorResult.RefreshTokenExpiresIn" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.Nullable&lt;System.DateTimeOffset&gt;</ReturnType>
</ReturnValue>
<Docs>
<summary>The expiry date as calculated by the timestamp of when the result was created plus the value in seconds for the `refresh_token_expires_in` key.</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="Timestamp">
<MemberSignature Language="C#" Value="public DateTimeOffset Timestamp { get; set; }" />
<MemberSignature Language="ILAsm" Value=".property instance valuetype System.DateTimeOffset Timestamp" />
<MemberSignature Language="DocId" Value="P:Xamarin.Essentials.WebAuthenticatorResult.Timestamp" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyName>Xamarin.Essentials</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>System.DateTimeOffset</ReturnType>
</ReturnValue>
<Docs>
<summary>The timestamp when the class was instantiated, which usually corresponds with the parsed result of a request.</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
</Members>
</Type>

Просмотреть файл

@ -93,7 +93,7 @@
<AttributeName>System.Runtime.Versioning.TargetFramework("MonoAndroid,Version=v10.0", FrameworkDisplayName="Xamarin.Android v10.0 Support")</AttributeName>
</Attribute>
<Attribute>
<AttributeName>System.Reflection.AssemblyInformationalVersion("1.0.0+a719d90eb3b235bbe16cd61ecbadc79db4d0dd7f")</AttributeName>
<AttributeName>System.Reflection.AssemblyInformationalVersion("1.0.0+c54a859c367ff3108025090d317b2ab4c66624a9")</AttributeName>
</Attribute>
</Attributes>
</Assembly>
@ -108,6 +108,8 @@
<Type Name="ActivityState" Kind="Enumeration" />
<Type Name="ActivityStateChangedEventArgs" Kind="Class" />
<Type Name="AppInfo" Kind="Class" />
<Type Name="AppleSignInAuthenticator" Kind="Class" />
<Type Name="AppleSignInAuthenticator+AppleSignInOptions" Kind="Class" />
<Type Name="AppTheme" Kind="Enumeration" />
<Type Name="Barometer" Kind="Class" />
<Type Name="BarometerChangedEventArgs" Kind="Class" />
@ -229,6 +231,9 @@
<Type Name="UnitConverters" Kind="Class" />
<Type Name="VersionTracking" Kind="Class" />
<Type Name="Vibration" Kind="Class" />
<Type Name="WebAuthenticator" Kind="Class" />
<Type Name="WebAuthenticatorCallbackActivity" Kind="Class" />
<Type Name="WebAuthenticatorResult" Kind="Class" />
</Namespace>
</Types>
<Title>Untitled</Title>