GoogleAuth: fix 94 issue
This commit is contained in:
parent
6fb3547652
commit
d40d73a3a5
BIN
.nuget/packages/GoogleAuthenticator.2.4.1.nupkg
Normal file
BIN
.nuget/packages/GoogleAuthenticator.2.4.1.nupkg
Normal file
Binary file not shown.
43
thirdparty/Google.Authenticator/Google.Authenticator.Tests/AuthCodeTest.cs
vendored
Normal file
43
thirdparty/Google.Authenticator/Google.Authenticator.Tests/AuthCodeTest.cs
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
using System.Text;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace Google.Authenticator.Tests
|
||||
{
|
||||
public class AuthCodeTest
|
||||
{
|
||||
[Fact]
|
||||
public void BasicAuthCodeTest()
|
||||
{
|
||||
var secretKey = "PJWUMZKAUUFQKJBAMD6VGJ6RULFVW4ZH";
|
||||
var expected = "551508";
|
||||
|
||||
var tfa = new TwoFactorAuthenticator();
|
||||
|
||||
var currentTime = 1416643820;
|
||||
|
||||
// I actually think you are supposed to divide the time by 30 seconds?
|
||||
// Maybe need an overload that takes a DateTime?
|
||||
var actual = tfa.GeneratePINAtInterval(secretKey, currentTime, 6);
|
||||
|
||||
actual.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Base32AuthCodeTest()
|
||||
{
|
||||
var secretKey = Base32Encoding.ToString(Encoding.UTF8.GetBytes("PJWUMZKAUUFQKJBAMD6VGJ6RULFVW4ZH"));
|
||||
var expected = "551508";
|
||||
|
||||
var tfa = new TwoFactorAuthenticator();
|
||||
|
||||
var currentTime = 1416643820;
|
||||
|
||||
// I actually think you are supposed to divide the time by 30 seconds?
|
||||
// Maybe need an overload that takes a DateTime?
|
||||
var actual = tfa.GeneratePINAtInterval(secretKey, currentTime, 6, true);
|
||||
|
||||
actual.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
33
thirdparty/Google.Authenticator/Google.Authenticator.Tests/GeneratePinTests.cs
vendored
Normal file
33
thirdparty/Google.Authenticator/Google.Authenticator.Tests/GeneratePinTests.cs
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
using Xunit;
|
||||
using Shouldly;
|
||||
using System.Text;
|
||||
using System.Net.NetworkInformation;
|
||||
|
||||
namespace Google.Authenticator.Tests
|
||||
{
|
||||
public class GeneratePinTests
|
||||
{
|
||||
[Fact]
|
||||
public void OverloadsReturnSamePIN()
|
||||
{
|
||||
var secret = "JBSWY3DPEHPK3PXP";
|
||||
var secretAsBytes = Encoding.UTF8.GetBytes(secret);
|
||||
var secretAsBase32 = Base32Encoding.ToString(secretAsBytes);
|
||||
long counter = 54615912;
|
||||
var expected = "508826";
|
||||
|
||||
var subject = new TwoFactorAuthenticator();
|
||||
|
||||
var pinFromString = subject.GeneratePINAtInterval(secret, counter);
|
||||
var pinFromBytes = subject.GeneratePINAtInterval(secretAsBytes, counter);
|
||||
var pinFromBase32 = subject.GeneratePINAtInterval(secretAsBase32, counter, secretIsBase32: true);
|
||||
|
||||
pinFromString.ShouldBe(expected);
|
||||
pinFromBytes.ShouldBe(expected);
|
||||
pinFromBase32.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// private long GetCurrentCounter(DateTime now, DateTime epoch, int timeStep) =>
|
||||
//(long) (now - epoch).TotalSeconds / timeStep;
|
29
thirdparty/Google.Authenticator/Google.Authenticator.Tests/Google.Authenticator.Tests.csproj
vendored
Normal file
29
thirdparty/Google.Authenticator/Google.Authenticator.Tests/Google.Authenticator.Tests.csproj
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.1;net452;net5.0</TargetFrameworks>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
||||
<PackageReference Include="Shouldly" Version="3.0.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="ZXing.Net" Version="0.16.7" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' != 'net452'">
|
||||
<PackageReference Include="ZXing.Net.Bindings.Magick" Version="0.16.9" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Google.Authenticator\Google.Authenticator.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
64
thirdparty/Google.Authenticator/Google.Authenticator.Tests/QRCodeTest.cs
vendored
Normal file
64
thirdparty/Google.Authenticator/Google.Authenticator.Tests/QRCodeTest.cs
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
using Xunit;
|
||||
using Shouldly;
|
||||
using System.Diagnostics;
|
||||
using System;
|
||||
using ZXing;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Google.Authenticator.Tests
|
||||
{
|
||||
public class QRCodeTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("issuer", "otpauth://totp/issuer:a@b.com?secret=ONSWG4TFOQ&issuer=issuer")]
|
||||
[InlineData("Foo & Bar", "otpauth://totp/Foo%20%26%20Bar:a@b.com?secret=ONSWG4TFOQ&issuer=Foo%20%26%20Bar")]
|
||||
[InlineData("个", "otpauth://totp/%E4%B8%AA:a@b.com?secret=ONSWG4TFOQ&issuer=%E4%B8%AA")]
|
||||
public void CanGenerateQRCode(string issuer, string expectedUrl)
|
||||
{
|
||||
var subject = new TwoFactorAuthenticator();
|
||||
var setupCodeInfo = subject.GenerateSetupCode(
|
||||
issuer,
|
||||
"a@b.com",
|
||||
"secret",
|
||||
false,
|
||||
2);
|
||||
|
||||
var actualUrl = ExtractUrlFromQRImage(setupCodeInfo.QrCodeSetupImageUrl);
|
||||
|
||||
actualUrl.ShouldBe(expectedUrl);
|
||||
}
|
||||
|
||||
private static string ExtractUrlFromQRImage(string qrCodeSetupImageUrl)
|
||||
{
|
||||
var headerLength = "data:image/png;base64,".Length;
|
||||
var rawImageData = qrCodeSetupImageUrl.Substring(headerLength, qrCodeSetupImageUrl.Length - headerLength);
|
||||
var imageData = Convert.FromBase64String(rawImageData);
|
||||
|
||||
//var reader = new BarcodeReaderGeneric();
|
||||
//reader.Options.PossibleFormats = new List<BarcodeFormat> {
|
||||
// BarcodeFormat.QR_CODE
|
||||
//};
|
||||
|
||||
#if NETFRAMEWORK
|
||||
var reader = new BarcodeReader();
|
||||
reader.Options.PossibleFormats = new List<BarcodeFormat> {
|
||||
BarcodeFormat.QR_CODE
|
||||
};
|
||||
using (var ms = new MemoryStream(imageData))
|
||||
{
|
||||
var image = new System.Drawing.Bitmap(ms);
|
||||
return reader.Decode(image).Text;
|
||||
}
|
||||
#else
|
||||
var reader = new BarcodeReaderGeneric();
|
||||
reader.Options.PossibleFormats = new List<BarcodeFormat> {
|
||||
BarcodeFormat.QR_CODE
|
||||
};
|
||||
var image = new ImageMagick.MagickImage(imageData);
|
||||
var wrappedImage = new ZXing.Magick.MagickImageLuminanceSource(image);
|
||||
return reader.Decode(wrappedImage).Text;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
30
thirdparty/Google.Authenticator/Google.Authenticator.Tests/SetupCodeTests.cs
vendored
Normal file
30
thirdparty/Google.Authenticator/Google.Authenticator.Tests/SetupCodeTests.cs
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
using Xunit;
|
||||
using Shouldly;
|
||||
using System.Text;
|
||||
|
||||
namespace Google.Authenticator.Tests
|
||||
{
|
||||
public class SetupCodeTests
|
||||
{
|
||||
[Fact]
|
||||
public void ByteAndStringGeneratesSameSetupCode()
|
||||
{
|
||||
var secret = "12345678901234567890123456789012";
|
||||
var secretAsByteArray = Encoding.UTF8.GetBytes(secret);
|
||||
var secretAsBase32 = Base32Encoding.ToString(secretAsByteArray);
|
||||
var issuer = "Test";
|
||||
var accountName = "TestAccount";
|
||||
var expected = "GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZA";
|
||||
|
||||
var subject = new TwoFactorAuthenticator();
|
||||
|
||||
var setupCodeFromString = subject.GenerateSetupCode(issuer, accountName, secret, false);
|
||||
var setupCodeFromByteArray = subject.GenerateSetupCode(issuer, accountName, secretAsByteArray, 3, false);
|
||||
var setupCodeFromBase32 = subject.GenerateSetupCode(issuer, accountName, secretAsBase32, true);
|
||||
|
||||
setupCodeFromString.ManualEntryKey.ShouldBe(expected);
|
||||
setupCodeFromByteArray.ManualEntryKey.ShouldBe(expected);
|
||||
setupCodeFromBase32.ManualEntryKey.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
45
thirdparty/Google.Authenticator/Google.Authenticator.Tests/ValidationTests.cs
vendored
Normal file
45
thirdparty/Google.Authenticator/Google.Authenticator.Tests/ValidationTests.cs
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
using Xunit;
|
||||
using Shouldly;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System;
|
||||
|
||||
namespace Google.Authenticator.Tests
|
||||
{
|
||||
public class ValidationTests
|
||||
{
|
||||
const string secret = "ggggjhG&^*&^jfSSSddd";
|
||||
private readonly static byte[] secretAsBytes = Encoding.UTF8.GetBytes(secret);
|
||||
private readonly static string secretAsBase32 = Base32Encoding.ToString(secretAsBytes);
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetPins))]
|
||||
public void ValidateWorksWithDifferentSecretTypes(string pin, int irrelevantNumberToAvoidDuplicatePinsBeingRemoved)
|
||||
{
|
||||
// We can't directly test that the different overloads for GetCurrentPIN creates the same result,
|
||||
// as the time difference may may cause different PINS to be created.
|
||||
// So instead we generate the PINs by each method and validate each one by each method.
|
||||
var subject = new TwoFactorAuthenticator();
|
||||
|
||||
subject.ValidateTwoFactorPIN(secret, pin, false);
|
||||
subject.ValidateTwoFactorPIN(secret, pin, TimeSpan.FromMinutes(irrelevantNumberToAvoidDuplicatePinsBeingRemoved), false);
|
||||
subject.ValidateTwoFactorPIN(secretAsBytes, pin);
|
||||
subject.ValidateTwoFactorPIN(secretAsBytes, pin, TimeSpan.FromMinutes(irrelevantNumberToAvoidDuplicatePinsBeingRemoved));
|
||||
subject.ValidateTwoFactorPIN(secretAsBase32, pin, true);
|
||||
subject.ValidateTwoFactorPIN(secretAsBase32, pin, TimeSpan.FromMinutes(irrelevantNumberToAvoidDuplicatePinsBeingRemoved), true);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetPins()
|
||||
{
|
||||
var subject = new TwoFactorAuthenticator();
|
||||
|
||||
yield return new object[] { subject.GetCurrentPIN(secret), 2 };
|
||||
yield return new object[] { subject.GetCurrentPIN(secret, DateTime.UtcNow), 3 };
|
||||
yield return new object[] { subject.GetCurrentPIN(secretAsBytes), 4 };
|
||||
yield return new object[] { subject.GetCurrentPIN(secretAsBytes, DateTime.UtcNow), 5 };
|
||||
yield return new object[] { subject.GetCurrentPIN(secretAsBase32, true), 6 };
|
||||
yield return new object[] { subject.GetCurrentPIN(secretAsBase32, DateTime.UtcNow, true), 7 };
|
||||
}
|
||||
}
|
||||
}
|
30
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Default.aspx
vendored
Normal file
30
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Default.aspx
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Google.Authenticator.WebSample.Default" %>
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head runat="server">
|
||||
<title>Google Authenticator Sample</title>
|
||||
<style type="text/css">
|
||||
body
|
||||
{
|
||||
font-family: Arial;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<form id="form1" runat="server">
|
||||
<div>
|
||||
<strong>Account Secret Key (randomly generated):</strong> <asp:Label runat="server" ID="lblSecretKey"></asp:Label>
|
||||
<hr />
|
||||
<strong>Setup QR Code:</strong><br />
|
||||
<asp:Image ID="imgQrCode" runat="server" /><br />
|
||||
<br />
|
||||
<strong>Manual Setup Code: </strong> <asp:Label runat="server" ID="lblManualSetupCode"></asp:Label>
|
||||
<hr />
|
||||
Validate Code: <asp:TextBox runat="server" ID="txtCode"></asp:TextBox> <asp:Button runat="server" ID="btnValidate" Text="Validate My Code!" OnClick="btnValidate_Click" /><br /><asp:Label runat="server" Font-Bold="true" ID="lblValidationResult"></asp:Label>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
48
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Default.aspx.cs
vendored
Normal file
48
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Default.aspx.cs
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
using System.Web.UI.WebControls;
|
||||
|
||||
namespace Google.Authenticator.WebSample
|
||||
{
|
||||
public partial class Default : System.Web.UI.Page
|
||||
{
|
||||
protected void Page_Load(object sender, EventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Request.QueryString["key"]))
|
||||
{
|
||||
Response.Redirect("~/default.aspx?key=" + Guid.NewGuid().ToString().Replace("-", "").Substring(0, 10));
|
||||
}
|
||||
|
||||
this.lblSecretKey.Text = Request.QueryString["key"];
|
||||
|
||||
TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
|
||||
var setupInfo = tfa.GenerateSetupCode("我 & You", "user@example.com", Request.QueryString["key"], false, 10);
|
||||
|
||||
string qrCodeImageUrl = setupInfo.QrCodeSetupImageUrl;
|
||||
string manualEntrySetupCode = setupInfo.ManualEntryKey;
|
||||
|
||||
this.imgQrCode.ImageUrl = qrCodeImageUrl;
|
||||
this.lblManualSetupCode.Text = manualEntrySetupCode;
|
||||
}
|
||||
|
||||
protected void btnValidate_Click(object sender, EventArgs e)
|
||||
{
|
||||
TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
|
||||
var result = tfa.ValidateTwoFactorPIN(Request.QueryString["key"], this.txtCode.Text);
|
||||
|
||||
if (result)
|
||||
{
|
||||
this.lblValidationResult.Text = this.txtCode.Text + " is a valid PIN at UTC time " + DateTime.UtcNow.ToString();
|
||||
this.lblValidationResult.ForeColor = System.Drawing.Color.Green;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.lblValidationResult.Text = this.txtCode.Text + " is not a valid PIN at UTC time " + DateTime.UtcNow.ToString();
|
||||
this.lblValidationResult.ForeColor = System.Drawing.Color.Red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
78
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Default.aspx.designer.cs
generated
vendored
Normal file
78
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Default.aspx.designer.cs
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Google.Authenticator.WebSample {
|
||||
|
||||
|
||||
public partial class Default {
|
||||
|
||||
/// <summary>
|
||||
/// form1 control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.HtmlControls.HtmlForm form1;
|
||||
|
||||
/// <summary>
|
||||
/// lblSecretKey control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Label lblSecretKey;
|
||||
|
||||
/// <summary>
|
||||
/// imgQrCode control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Image imgQrCode;
|
||||
|
||||
/// <summary>
|
||||
/// lblManualSetupCode control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Label lblManualSetupCode;
|
||||
|
||||
/// <summary>
|
||||
/// txtCode control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.TextBox txtCode;
|
||||
|
||||
/// <summary>
|
||||
/// btnValidate control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Button btnValidate;
|
||||
|
||||
/// <summary>
|
||||
/// lblValidationResult control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Auto-generated field.
|
||||
/// To modify move field declaration from designer file to code-behind file.
|
||||
/// </remarks>
|
||||
protected global::System.Web.UI.WebControls.Label lblValidationResult;
|
||||
}
|
||||
}
|
1
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Global.asax
vendored
Normal file
1
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Global.asax
vendored
Normal file
@ -0,0 +1 @@
|
||||
<%@ Application Codebehind="Global.asax.cs" Inherits="Google.Authenticator.WebSample.Global" Language="C#" %>
|
16
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Global.asax.cs
vendored
Normal file
16
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Global.asax.cs
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Security;
|
||||
using System.Web.SessionState;
|
||||
|
||||
namespace Google.Authenticator.WebSample
|
||||
{
|
||||
public class Global : System.Web.HttpApplication
|
||||
{
|
||||
protected void Application_Start(object sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
133
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Google.Authenticator.WebSample.csproj
vendored
Normal file
133
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Google.Authenticator.WebSample.csproj
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>
|
||||
</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{21A63F79-D85F-4FE7-AC74-5171FAC0DCBF}</ProjectGuid>
|
||||
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Google.Authenticator.WebSample</RootNamespace>
|
||||
<AssemblyName>Google.Authenticator.WebSample</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<UseIISExpress>true</UseIISExpress>
|
||||
<IISExpressSSLPort />
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
<TargetFrameworkProfile />
|
||||
<Use64BitIISExpress />
|
||||
<UseGlobalApplicationHostFile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Web.DynamicData" />
|
||||
<Reference Include="System.Web.Entity" />
|
||||
<Reference Include="System.Web.ApplicationServices" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Web.Services" />
|
||||
<Reference Include="System.EnterpriseServices" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Properties\PublishProfiles\gauthtwofactorsample.pubxml" />
|
||||
<None Include="Web.Debug.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</None>
|
||||
<None Include="Web.Release.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Default.aspx" />
|
||||
<Content Include="Global.asax" />
|
||||
<Content Include="Web.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Default.aspx.cs">
|
||||
<DependentUpon>Default.aspx</DependentUpon>
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Default.aspx.designer.cs">
|
||||
<DependentUpon>Default.aspx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Global.asax.cs">
|
||||
<DependentUpon>Global.asax</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Google.Authenticator\Google.Authenticator.csproj">
|
||||
<Project>{3d92de47-0ab8-466f-9083-af65d865e4be}</Project>
|
||||
<Name>Google.Authenticator</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="App_Data\" />
|
||||
<Folder Include="Models\" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>11275</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:11275/</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
</CustomServerUrl>
|
||||
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
||||
</WebProjectProperties>
|
||||
</FlavorProperties>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
35
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Properties/AssemblyInfo.cs
vendored
Normal file
35
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Properties/AssemblyInfo.cs
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Google.Authenticator.WebSample")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Google.Authenticator.WebSample")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("59ad50f8-c7b9-4b70-bd7c-c2caa8d8d6b7")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
30
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Web.Debug.config
vendored
Normal file
30
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Web.Debug.config
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
|
||||
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<!--
|
||||
In the example below, the "SetAttributes" transform will change the value of
|
||||
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
|
||||
finds an attribute "name" that has a value of "MyDB".
|
||||
|
||||
<connectionStrings>
|
||||
<add name="MyDB"
|
||||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
|
||||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
|
||||
</connectionStrings>
|
||||
-->
|
||||
<system.web>
|
||||
<!--
|
||||
In the example below, the "Replace" transform will replace the entire
|
||||
<customErrors> section of your web.config file.
|
||||
Note that because there is only one customErrors section under the
|
||||
<system.web> node, there is no need to use the "xdt:Locator" attribute.
|
||||
|
||||
<customErrors defaultRedirect="GenericError.htm"
|
||||
mode="RemoteOnly" xdt:Transform="Replace">
|
||||
<error statusCode="500" redirect="InternalError.htm"/>
|
||||
</customErrors>
|
||||
-->
|
||||
</system.web>
|
||||
</configuration>
|
31
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Web.Release.config
vendored
Normal file
31
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Web.Release.config
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 -->
|
||||
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<!--
|
||||
In the example below, the "SetAttributes" transform will change the value of
|
||||
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator
|
||||
finds an attribute "name" that has a value of "MyDB".
|
||||
|
||||
<connectionStrings>
|
||||
<add name="MyDB"
|
||||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True"
|
||||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
|
||||
</connectionStrings>
|
||||
-->
|
||||
<system.web>
|
||||
<compilation xdt:Transform="RemoveAttributes(debug)" />
|
||||
<!--
|
||||
In the example below, the "Replace" transform will replace the entire
|
||||
<customErrors> section of your web.config file.
|
||||
Note that because there is only one customErrors section under the
|
||||
<system.web> node, there is no need to use the "xdt:Locator" attribute.
|
||||
|
||||
<customErrors defaultRedirect="GenericError.htm"
|
||||
mode="RemoteOnly" xdt:Transform="Replace">
|
||||
<error statusCode="500" redirect="InternalError.htm"/>
|
||||
</customErrors>
|
||||
-->
|
||||
</system.web>
|
||||
</configuration>
|
19
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Web.config
vendored
Normal file
19
thirdparty/Google.Authenticator/Google.Authenticator.WebSample/Web.config
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
For more information on how to configure your ASP.NET application, please visit
|
||||
http://go.microsoft.com/fwlink/?LinkId=169433
|
||||
-->
|
||||
<configuration>
|
||||
<!--
|
||||
For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.
|
||||
|
||||
The following attributes can be set on the <httpRuntime> tag.
|
||||
<system.Web>
|
||||
<httpRuntime targetFramework="4.6.2" />
|
||||
</system.Web>
|
||||
-->
|
||||
<system.web>
|
||||
<compilation debug="true" targetFramework="4.8"/>
|
||||
<httpRuntime targetFramework="4.5"/>
|
||||
</system.web>
|
||||
</configuration>
|
6
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/App.config
vendored
Normal file
6
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/App.config
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
|
||||
</startup>
|
||||
</configuration>
|
208
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Form1.Designer.cs
generated
vendored
Normal file
208
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Form1.Designer.cs
generated
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
namespace Google.Authenticator.WinTest
|
||||
{
|
||||
partial class Form1
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.txtAccountTitle = new System.Windows.Forms.TextBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.txtSecretKey = new System.Windows.Forms.TextBox();
|
||||
this.pbQR = new System.Windows.Forms.PictureBox();
|
||||
this.btnSetup = new System.Windows.Forms.Button();
|
||||
this.btnGetCurrentCode = new System.Windows.Forms.Button();
|
||||
this.txtSetupCode = new System.Windows.Forms.TextBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.txtCode = new System.Windows.Forms.TextBox();
|
||||
this.btnTest = new System.Windows.Forms.Button();
|
||||
this.txtCurrentCodes = new System.Windows.Forms.TextBox();
|
||||
this.btnDebugTest = new System.Windows.Forms.Button();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pbQR)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// txtAccountTitle
|
||||
//
|
||||
this.txtAccountTitle.Location = new System.Drawing.Point(92, 15);
|
||||
this.txtAccountTitle.Name = "txtAccountTitle";
|
||||
this.txtAccountTitle.Size = new System.Drawing.Size(155, 21);
|
||||
this.txtAccountTitle.TabIndex = 0;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(13, 18);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(73, 13);
|
||||
this.label1.TabIndex = 1;
|
||||
this.label1.Text = "Account Title:";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(24, 44);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(63, 13);
|
||||
this.label2.TabIndex = 3;
|
||||
this.label2.Text = "Secret Key:";
|
||||
//
|
||||
// txtSecretKey
|
||||
//
|
||||
this.txtSecretKey.Location = new System.Drawing.Point(92, 41);
|
||||
this.txtSecretKey.Name = "txtSecretKey";
|
||||
this.txtSecretKey.Size = new System.Drawing.Size(155, 21);
|
||||
this.txtSecretKey.TabIndex = 2;
|
||||
//
|
||||
// pbQR
|
||||
//
|
||||
this.pbQR.BackColor = System.Drawing.Color.White;
|
||||
this.pbQR.Location = new System.Drawing.Point(34, 67);
|
||||
this.pbQR.Name = "pbQR";
|
||||
this.pbQR.Size = new System.Drawing.Size(231, 223);
|
||||
this.pbQR.TabIndex = 4;
|
||||
this.pbQR.TabStop = false;
|
||||
//
|
||||
// btnSetup
|
||||
//
|
||||
this.btnSetup.Location = new System.Drawing.Point(337, 15);
|
||||
this.btnSetup.Name = "btnSetup";
|
||||
this.btnSetup.Size = new System.Drawing.Size(243, 46);
|
||||
this.btnSetup.TabIndex = 5;
|
||||
this.btnSetup.Text = "Generate Setup / Get QR Code";
|
||||
this.btnSetup.UseVisualStyleBackColor = true;
|
||||
this.btnSetup.Click += new System.EventHandler(this.btnSetup_Click);
|
||||
//
|
||||
// btnGetCurrentCode
|
||||
//
|
||||
this.btnGetCurrentCode.Location = new System.Drawing.Point(396, 250);
|
||||
this.btnGetCurrentCode.Name = "btnGetCurrentCode";
|
||||
this.btnGetCurrentCode.Size = new System.Drawing.Size(173, 27);
|
||||
this.btnGetCurrentCode.TabIndex = 6;
|
||||
this.btnGetCurrentCode.Text = "Get Current";
|
||||
this.btnGetCurrentCode.UseVisualStyleBackColor = true;
|
||||
this.btnGetCurrentCode.Click += new System.EventHandler(this.btnGetCurrentCode_Click);
|
||||
//
|
||||
// txtSetupCode
|
||||
//
|
||||
this.txtSetupCode.Location = new System.Drawing.Point(337, 67);
|
||||
this.txtSetupCode.Multiline = true;
|
||||
this.txtSetupCode.Name = "txtSetupCode";
|
||||
this.txtSetupCode.ReadOnly = true;
|
||||
this.txtSetupCode.Size = new System.Drawing.Size(243, 105);
|
||||
this.txtSetupCode.TabIndex = 7;
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(330, 182);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(60, 13);
|
||||
this.label3.TabIndex = 8;
|
||||
this.label3.Text = "Test Code:";
|
||||
//
|
||||
// txtCode
|
||||
//
|
||||
this.txtCode.Location = new System.Drawing.Point(396, 179);
|
||||
this.txtCode.Name = "txtCode";
|
||||
this.txtCode.Size = new System.Drawing.Size(124, 21);
|
||||
this.txtCode.TabIndex = 9;
|
||||
//
|
||||
// btnTest
|
||||
//
|
||||
this.btnTest.Location = new System.Drawing.Point(396, 217);
|
||||
this.btnTest.Name = "btnTest";
|
||||
this.btnTest.Size = new System.Drawing.Size(173, 27);
|
||||
this.btnTest.TabIndex = 10;
|
||||
this.btnTest.Text = "Test Two-Factor Code";
|
||||
this.btnTest.UseVisualStyleBackColor = true;
|
||||
this.btnTest.Click += new System.EventHandler(this.btnTest_Click);
|
||||
//
|
||||
// txtCurrentCodes
|
||||
//
|
||||
this.txtCurrentCodes.Location = new System.Drawing.Point(337, 283);
|
||||
this.txtCurrentCodes.Multiline = true;
|
||||
this.txtCurrentCodes.Name = "txtCurrentCodes";
|
||||
this.txtCurrentCodes.ReadOnly = true;
|
||||
this.txtCurrentCodes.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.txtCurrentCodes.Size = new System.Drawing.Size(243, 105);
|
||||
this.txtCurrentCodes.TabIndex = 11;
|
||||
//
|
||||
// btnDebugTest
|
||||
//
|
||||
this.btnDebugTest.Location = new System.Drawing.Point(27, 361);
|
||||
this.btnDebugTest.Name = "btnDebugTest";
|
||||
this.btnDebugTest.Size = new System.Drawing.Size(173, 27);
|
||||
this.btnDebugTest.TabIndex = 12;
|
||||
this.btnDebugTest.Text = "Misc Test";
|
||||
this.btnDebugTest.UseVisualStyleBackColor = true;
|
||||
this.btnDebugTest.Click += new System.EventHandler(this.btnDebugTest_Click);
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(607, 408);
|
||||
this.Controls.Add(this.btnDebugTest);
|
||||
this.Controls.Add(this.txtCurrentCodes);
|
||||
this.Controls.Add(this.btnTest);
|
||||
this.Controls.Add(this.txtCode);
|
||||
this.Controls.Add(this.label3);
|
||||
this.Controls.Add(this.txtSetupCode);
|
||||
this.Controls.Add(this.btnGetCurrentCode);
|
||||
this.Controls.Add(this.btnSetup);
|
||||
this.Controls.Add(this.pbQR);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.txtSecretKey);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.txtAccountTitle);
|
||||
this.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.Name = "Form1";
|
||||
this.Text = "Google Authenticator Test App";
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pbQR)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox txtAccountTitle;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.TextBox txtSecretKey;
|
||||
private System.Windows.Forms.PictureBox pbQR;
|
||||
private System.Windows.Forms.Button btnSetup;
|
||||
private System.Windows.Forms.Button btnGetCurrentCode;
|
||||
private System.Windows.Forms.TextBox txtSetupCode;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.TextBox txtCode;
|
||||
private System.Windows.Forms.Button btnTest;
|
||||
private System.Windows.Forms.TextBox txtCurrentCodes;
|
||||
private System.Windows.Forms.Button btnDebugTest;
|
||||
}
|
||||
}
|
||||
|
60
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Form1.cs
vendored
Normal file
60
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Form1.cs
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Google.Authenticator.WinTest
|
||||
{
|
||||
public partial class Form1 : Form
|
||||
{
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Form1_Load(object sender, EventArgs e)
|
||||
{
|
||||
this.txtAccountTitle.Text = "QRTestAccount";
|
||||
this.txtSecretKey.Text = "f68f1fe894d548a1bbc66165c46e61eb"; //Guid.NewGuid().ToString().Replace("-", "");
|
||||
}
|
||||
|
||||
private void btnSetup_Click(object sender, EventArgs e)
|
||||
{
|
||||
TwoFactorAuthenticator tfA = new TwoFactorAuthenticator();
|
||||
var setupCode = tfA.GenerateSetupCode(this.txtAccountTitle.Text, this.txtAccountTitle.Text, this.txtSecretKey.Text, false, 3);
|
||||
|
||||
//WebClient wc = new WebClient();
|
||||
using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(setupCode.QrCodeSetupImageUrl.Replace("data:image/png;base64,", ""))))
|
||||
this.pbQR.Image = Image.FromStream(ms);
|
||||
|
||||
this.txtSetupCode.Text = "Account: " + setupCode.Account + System.Environment.NewLine +
|
||||
"Secret Key: " + this.txtSecretKey.Text + System.Environment.NewLine +
|
||||
"Encoded Key: " + setupCode.ManualEntryKey;
|
||||
}
|
||||
|
||||
private void btnTest_Click(object sender, EventArgs e)
|
||||
{
|
||||
TwoFactorAuthenticator tfA = new TwoFactorAuthenticator();
|
||||
var result = tfA.ValidateTwoFactorPIN(txtSecretKey.Text, this.txtCode.Text);
|
||||
|
||||
MessageBox.Show(result ? "Validated!" : "Incorrect", "Result");
|
||||
}
|
||||
|
||||
private void btnGetCurrentCode_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.txtCurrentCodes.Text = string.Join(System.Environment.NewLine, new TwoFactorAuthenticator().GetCurrentPINs(this.txtSecretKey.Text));
|
||||
}
|
||||
|
||||
private void btnDebugTest_Click(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
120
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Form1.resx
vendored
Normal file
120
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Form1.resx
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
100
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Google.Authenticator.WinTest.csproj
vendored
Normal file
100
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Google.Authenticator.WinTest.csproj
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{C2B44C17-B77B-4DA8-B924-96B28B50D198}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Google.Authenticator.WinTest</RootNamespace>
|
||||
<AssemblyName>Google.Authenticator.WinTest</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Form1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Form1.Designer.cs">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Google.Authenticator\Google.Authenticator.csproj">
|
||||
<Project>{3d92de47-0ab8-466f-9083-af65d865e4be}</Project>
|
||||
<Name>Google.Authenticator</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
22
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Program.cs
vendored
Normal file
22
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Program.cs
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Google.Authenticator.WinTest
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new Form1());
|
||||
}
|
||||
}
|
||||
}
|
36
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Properties/AssemblyInfo.cs
vendored
Normal file
36
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Properties/AssemblyInfo.cs
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Google.Authenticator.WinTest")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Google.Authenticator.WinTest")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("6d26d66d-66b3-43c4-b1bd-73e6594aec0d")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
63
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Properties/Resources.Designer.cs
generated
vendored
Normal file
63
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Properties/Resources.Designer.cs
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Google.Authenticator.WinTest.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Google.Authenticator.WinTest.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Properties/Resources.resx
vendored
Normal file
117
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Properties/Resources.resx
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
26
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Properties/Settings.Designer.cs
generated
vendored
Normal file
26
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Properties/Settings.Designer.cs
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Google.Authenticator.WinTest.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.1.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
7
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Properties/Settings.settings
vendored
Normal file
7
thirdparty/Google.Authenticator/Google.Authenticator.WinTest/Properties/Settings.settings
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
43
thirdparty/Google.Authenticator/Google.Authenticator.sln
vendored
Normal file
43
thirdparty/Google.Authenticator/Google.Authenticator.sln
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.1.32210.238
|
||||
MinimumVisualStudioVersion = 15.0
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Authenticator", "Google.Authenticator\Google.Authenticator.csproj", "{3D92DE47-0AB8-466F-9083-AF65D865E4BE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Authenticator.WinTest", "Google.Authenticator.WinTest\Google.Authenticator.WinTest.csproj", "{C2B44C17-B77B-4DA8-B924-96B28B50D198}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Authenticator.WebSample", "Google.Authenticator.WebSample\Google.Authenticator.WebSample.csproj", "{21A63F79-D85F-4FE7-AC74-5171FAC0DCBF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Authenticator.Tests", "Google.Authenticator.Tests\Google.Authenticator.Tests.csproj", "{5671E1C5-7CD0-4F42-8FFD-33879A9663DA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3D92DE47-0AB8-466F-9083-AF65D865E4BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3D92DE47-0AB8-466F-9083-AF65D865E4BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3D92DE47-0AB8-466F-9083-AF65D865E4BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3D92DE47-0AB8-466F-9083-AF65D865E4BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C2B44C17-B77B-4DA8-B924-96B28B50D198}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C2B44C17-B77B-4DA8-B924-96B28B50D198}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C2B44C17-B77B-4DA8-B924-96B28B50D198}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C2B44C17-B77B-4DA8-B924-96B28B50D198}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{21A63F79-D85F-4FE7-AC74-5171FAC0DCBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{21A63F79-D85F-4FE7-AC74-5171FAC0DCBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{21A63F79-D85F-4FE7-AC74-5171FAC0DCBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{21A63F79-D85F-4FE7-AC74-5171FAC0DCBF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5671E1C5-7CD0-4F42-8FFD-33879A9663DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5671E1C5-7CD0-4F42-8FFD-33879A9663DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5671E1C5-7CD0-4F42-8FFD-33879A9663DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5671E1C5-7CD0-4F42-8FFD-33879A9663DA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {F3028003-C1B6-40B2-B69C-68F45D3DDE88}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
140
thirdparty/Google.Authenticator/Google.Authenticator/Base32Encoding.cs
vendored
Normal file
140
thirdparty/Google.Authenticator/Google.Authenticator/Base32Encoding.cs
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
using System;
|
||||
|
||||
namespace Google.Authenticator
|
||||
{
|
||||
/// <summary>
|
||||
/// http://stackoverflow.com/questions/641361/base32-decoding
|
||||
/// </summary>
|
||||
public class Base32Encoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Base32 encoded string to byte[]
|
||||
/// </summary>
|
||||
/// <param name="input">Base32 encoded string</param>
|
||||
/// <returns>byte[]</returns>
|
||||
public static byte[] ToBytes(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(input));
|
||||
}
|
||||
|
||||
input = input.TrimEnd('='); //remove padding characters
|
||||
var byteCount = input.Length * 5 / 8; //this must be TRUNCATED
|
||||
var returnArray = new byte[byteCount];
|
||||
|
||||
byte curByte = 0, bitsRemaining = 8;
|
||||
int mask, arrayIndex = 0;
|
||||
|
||||
foreach (var c in input)
|
||||
{
|
||||
var cValue = CharToValue(c);
|
||||
|
||||
if (bitsRemaining > 5)
|
||||
{
|
||||
mask = cValue << (bitsRemaining - 5);
|
||||
curByte = (byte) (curByte | mask);
|
||||
bitsRemaining -= 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = cValue >> (5 - bitsRemaining);
|
||||
curByte = (byte) (curByte | mask);
|
||||
returnArray[arrayIndex++] = curByte;
|
||||
curByte = (byte) (cValue << (3 + bitsRemaining));
|
||||
bitsRemaining += 3;
|
||||
}
|
||||
}
|
||||
|
||||
//if we didn't end with a full byte
|
||||
if (arrayIndex != byteCount)
|
||||
returnArray[arrayIndex] = curByte;
|
||||
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// byte[] to Base32 string, if starting from an ordinary string use Encoding.UTF8.GetBytes() to convert it to a byte[]
|
||||
/// </summary>
|
||||
/// <param name="input">byte[] of data to be Base32 encoded</param>
|
||||
/// <returns>Base32 String</returns>
|
||||
public static string ToString(byte[] input)
|
||||
{
|
||||
if (input == null || input.Length == 0)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(input));
|
||||
}
|
||||
|
||||
var charCount = (int) Math.Ceiling(input.Length / 5d) * 8;
|
||||
var returnArray = new char[charCount];
|
||||
|
||||
byte nextChar = 0, bitsRemaining = 5;
|
||||
var arrayIndex = 0;
|
||||
|
||||
foreach (var b in input)
|
||||
{
|
||||
nextChar = (byte) (nextChar | (b >> (8 - bitsRemaining)));
|
||||
returnArray[arrayIndex++] = ValueToChar(nextChar);
|
||||
|
||||
if (bitsRemaining < 4)
|
||||
{
|
||||
nextChar = (byte) ((b >> (3 - bitsRemaining)) & 31);
|
||||
returnArray[arrayIndex++] = ValueToChar(nextChar);
|
||||
bitsRemaining += 5;
|
||||
}
|
||||
|
||||
bitsRemaining -= 3;
|
||||
nextChar = (byte) ((b << bitsRemaining) & 31);
|
||||
}
|
||||
|
||||
//if we didn't end with a full char
|
||||
if (arrayIndex != charCount)
|
||||
{
|
||||
returnArray[arrayIndex++] = ValueToChar(nextChar);
|
||||
while (arrayIndex != charCount) returnArray[arrayIndex++] = '='; //padding
|
||||
}
|
||||
|
||||
return new string(returnArray);
|
||||
}
|
||||
|
||||
private static int CharToValue(char c)
|
||||
{
|
||||
var value = (int) c;
|
||||
|
||||
//65-90 == uppercase letters
|
||||
if (value < 91 && value > 64)
|
||||
{
|
||||
return value - 65;
|
||||
}
|
||||
|
||||
//50-55 == numbers 2-7
|
||||
if (value < 56 && value > 49)
|
||||
{
|
||||
return value - 24;
|
||||
}
|
||||
|
||||
//97-122 == lowercase letters
|
||||
if (value < 123 && value > 96)
|
||||
{
|
||||
return value - 97;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Character is not a Base32 character.", nameof(c));
|
||||
}
|
||||
|
||||
private static char ValueToChar(byte b)
|
||||
{
|
||||
if (b < 26)
|
||||
{
|
||||
return (char) (b + 65);
|
||||
}
|
||||
|
||||
if (b < 32)
|
||||
{
|
||||
return (char) (b + 24);
|
||||
}
|
||||
|
||||
throw new ArgumentException("Byte is not a value Base32 value.", nameof(b));
|
||||
}
|
||||
}
|
||||
}
|
38
thirdparty/Google.Authenticator/Google.Authenticator/Google.Authenticator.csproj
vendored
Normal file
38
thirdparty/Google.Authenticator/Google.Authenticator/Google.Authenticator.csproj
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||
<Product>Google Authenticator Two-Factor</Product>
|
||||
<Title>Google Authenticator Two-Factor Authentication Library</Title>
|
||||
<Description>Google Authenticator Two-Factor Authentication Library (Not officially affiliated with Google.)</Description>
|
||||
<Authors>Brandon Potter</Authors>
|
||||
<Company>Brandon Potter</Company>
|
||||
<Version>2.4.1</Version>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://github.com/BrandonPotter/GoogleAuthenticator</PackageProjectUrl>
|
||||
<PackageId>GoogleAuthenticator</PackageId>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="QRCoder" Version="1.4.3" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||
<None Include="..\README.md" Pack="true" PackagePath="\"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net6'">
|
||||
<DefineConstants>NET6_0;NETCOREAPP</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
|
||||
</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<AssemblyVersion>2.0.1.1</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
15
thirdparty/Google.Authenticator/Google.Authenticator/MissingDependencyException.cs
vendored
Normal file
15
thirdparty/Google.Authenticator/Google.Authenticator/MissingDependencyException.cs
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Google.Authenticator
|
||||
{
|
||||
public class MissingDependencyException : Exception
|
||||
{
|
||||
public MissingDependencyException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public MissingDependencyException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
13
thirdparty/Google.Authenticator/Google.Authenticator/QRException.cs
vendored
Normal file
13
thirdparty/Google.Authenticator/Google.Authenticator/QRException.cs
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace Google.Authenticator
|
||||
{
|
||||
public class QRException : Exception
|
||||
{
|
||||
public QRException(string message) : base(message)
|
||||
{ }
|
||||
|
||||
public QRException(string message, Exception innerException) : base(message, innerException)
|
||||
{ }
|
||||
}
|
||||
}
|
21
thirdparty/Google.Authenticator/Google.Authenticator/SetupCode.cs
vendored
Normal file
21
thirdparty/Google.Authenticator/Google.Authenticator/SetupCode.cs
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
namespace Google.Authenticator
|
||||
{
|
||||
public class SetupCode
|
||||
{
|
||||
public string Account { get; internal set; }
|
||||
public string ManualEntryKey { get; internal set; }
|
||||
/// <summary>
|
||||
/// Base64-encoded PNG image
|
||||
/// </summary>
|
||||
public string QrCodeSetupImageUrl { get; internal set; }
|
||||
|
||||
public SetupCode() { }
|
||||
|
||||
public SetupCode(string account, string manualEntryKey, string qrCodeSetupImageUrl)
|
||||
{
|
||||
Account = account;
|
||||
ManualEntryKey = manualEntryKey;
|
||||
QrCodeSetupImageUrl = qrCodeSetupImageUrl;
|
||||
}
|
||||
}
|
||||
}
|
321
thirdparty/Google.Authenticator/Google.Authenticator/TwoFactorAuthenticator.cs
vendored
Normal file
321
thirdparty/Google.Authenticator/Google.Authenticator/TwoFactorAuthenticator.cs
vendored
Normal file
@ -0,0 +1,321 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
using QRCoder;
|
||||
|
||||
namespace Google.Authenticator
|
||||
{
|
||||
/// <summary>
|
||||
/// modified from
|
||||
/// http://brandonpotter.com/2014/09/07/implementing-free-two-factor-authentication-in-net-using-google-authenticator/
|
||||
/// https://github.com/brandonpotter/GoogleAuthenticator
|
||||
/// With elements borrowed from https://github.com/stephenlawuk/GoogleAuthenticator
|
||||
/// </summary>
|
||||
public class TwoFactorAuthenticator
|
||||
{
|
||||
private static readonly DateTime _epoch =
|
||||
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
private TimeSpan DefaultClockDriftTolerance { get; set; }
|
||||
|
||||
public TwoFactorAuthenticator() => DefaultClockDriftTolerance = TimeSpan.FromMinutes(5);
|
||||
|
||||
/// <summary>
|
||||
/// Generate a setup code for a Google Authenticator user to scan
|
||||
/// </summary>
|
||||
/// <param name="issuer">Issuer ID (the name of the system, i.e. 'MyApp'),
|
||||
/// can be omitted but not recommended https://github.com/google/google-authenticator/wiki/Key-Uri-Format
|
||||
/// </param>
|
||||
/// <param name="accountTitleNoSpaces">Account Title (no spaces)</param>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <param name="secretIsBase32">Flag saying if accountSecretKey is in Base32 format or original secret</param>
|
||||
/// <param name="qrPixelsPerModule">Number of pixels per QR Module (2 pixels give ~ 100x100px QRCode,
|
||||
/// should be 10 or less)</param>
|
||||
/// <returns>SetupCode object</returns>
|
||||
public SetupCode GenerateSetupCode(string issuer, string accountTitleNoSpaces, string accountSecretKey, bool secretIsBase32, int qrPixelsPerModule = 3) =>
|
||||
GenerateSetupCode(issuer, accountTitleNoSpaces, ConvertSecretToBytes(accountSecretKey, secretIsBase32), qrPixelsPerModule);
|
||||
|
||||
/// <summary>
|
||||
/// Generate a setup code for a Google Authenticator user to scan
|
||||
/// </summary>
|
||||
/// <param name="issuer">Issuer ID (the name of the system, i.e. 'MyApp'), can be omitted but not
|
||||
/// recommended https://github.com/google/google-authenticator/wiki/Key-Uri-Format </param>
|
||||
/// <param name="accountTitleNoSpaces">Account Title (no spaces)</param>
|
||||
/// <param name="accountSecretKey">Account Secret Key as byte[]</param>
|
||||
/// <param name="qrPixelsPerModule">Number of pixels per QR Module
|
||||
/// (2 = ~120x120px QRCode, should be 10 or less)</param>
|
||||
/// <param name="generateQrCode"></param>
|
||||
/// <returns>SetupCode object</returns>
|
||||
public SetupCode GenerateSetupCode(string issuer,
|
||||
string accountTitleNoSpaces,
|
||||
byte[] accountSecretKey,
|
||||
int qrPixelsPerModule = 3,
|
||||
bool generateQrCode = true)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(accountTitleNoSpaces))
|
||||
{
|
||||
throw new NullReferenceException("Account Title is null");
|
||||
}
|
||||
|
||||
accountTitleNoSpaces = RemoveWhitespace(Uri.EscapeUriString(accountTitleNoSpaces));
|
||||
var encodedSecretKey = Base32Encoding.ToString(accountSecretKey);
|
||||
|
||||
var provisionUrl = string.IsNullOrWhiteSpace(issuer)
|
||||
? $"otpauth://totp/{accountTitleNoSpaces}?secret={encodedSecretKey.Trim('=')}"
|
||||
// https://github.com/google/google-authenticator/wiki/Conflicting-Accounts
|
||||
// Added additional prefix to account otpauth://totp/Company:joe_example@gmail.com
|
||||
// for backwards compatibility
|
||||
: $"otpauth://totp/{UrlEncode(issuer)}:{accountTitleNoSpaces}?secret={encodedSecretKey.Trim('=')}&issuer={UrlEncode(issuer)}";
|
||||
|
||||
return new SetupCode(
|
||||
accountTitleNoSpaces,
|
||||
encodedSecretKey.Trim('='),
|
||||
generateQrCode ? GenerateQrCodeUrl(qrPixelsPerModule, provisionUrl) : "");
|
||||
}
|
||||
|
||||
private static string GenerateQrCodeUrl(int qrPixelsPerModule, string provisionUrl)
|
||||
{
|
||||
var qrCodeUrl = "";
|
||||
try
|
||||
{
|
||||
using (var qrGen = new QRCodeGenerator())
|
||||
using (var qrCode = qrGen.CreateQrCode(provisionUrl, QRCodeGenerator.ECCLevel.Q))
|
||||
using (var qrBmp = new BitmapByteQRCode(qrCode))
|
||||
{
|
||||
qrCodeUrl = $"data:image/png;base64,{Convert.ToBase64String(qrBmp.GetGraphic(qrPixelsPerModule))}";
|
||||
}
|
||||
}
|
||||
catch (TypeInitializationException e)
|
||||
{
|
||||
if (e.InnerException != null
|
||||
&& e.InnerException.GetType() == typeof(DllNotFoundException)
|
||||
&& e.InnerException.Message.Contains("libgdiplus"))
|
||||
{
|
||||
throw new MissingDependencyException(
|
||||
"It looks like libgdiplus has not been installed - see" +
|
||||
" https://github.com/codebude/QRCoder/issues/227",
|
||||
e);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (System.Runtime.InteropServices.ExternalException e)
|
||||
{
|
||||
if (e.Message.Contains("GDI+") && qrPixelsPerModule > 10)
|
||||
{
|
||||
throw new QRException(
|
||||
$"There was a problem generating a QR code. The value of {nameof(qrPixelsPerModule)}" +
|
||||
" should be set to a value of 10 or less for optimal results.",
|
||||
e);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return qrCodeUrl;
|
||||
}
|
||||
|
||||
private static string RemoveWhitespace(string str) =>
|
||||
new string(str.Where(c => !char.IsWhiteSpace(c)).ToArray());
|
||||
|
||||
private string UrlEncode(string value)
|
||||
{
|
||||
return Uri.EscapeDataString(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is generally called via <see cref="GoogleAuthenticator.GetCurrentPIN()" />/>
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">The acount secret key as a string</param>
|
||||
/// <param name="counter">The number of 30-second (by default) intervals since the unix epoch</param>
|
||||
/// <param name="digits">The desired length of the returned PIN</param>
|
||||
/// <param name="secretIsBase32">Flag saying if accountSecretKey is in Base32 format or original secret</param>
|
||||
/// <returns>A 'PIN' that is valid for the specified time interval</returns>
|
||||
public string GeneratePINAtInterval(string accountSecretKey, long counter, int digits = 6, bool secretIsBase32 = false) =>
|
||||
GeneratePINAtInterval(ConvertSecretToBytes(accountSecretKey, secretIsBase32), counter, digits);
|
||||
|
||||
/// <summary>
|
||||
/// This method is generally called via <see cref="GoogleAuthenticator.GetCurrentPIN()" />/>
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">The acount secret key as a byte array</param>
|
||||
/// <param name="counter">The number of 30-second (by default) intervals since the unix epoch</param>
|
||||
/// <param name="digits">The desired length of the returned PIN</param>
|
||||
/// <returns>A 'PIN' that is valid for the specified time interval</returns>
|
||||
public string GeneratePINAtInterval(byte[] accountSecretKey, long counter, int digits = 6) =>
|
||||
GenerateHashedCode(accountSecretKey, counter, digits);
|
||||
|
||||
private string GenerateHashedCode(byte[] key, long iterationNumber, int digits = 6)
|
||||
{
|
||||
var counter = BitConverter.GetBytes(iterationNumber);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(counter);
|
||||
|
||||
var hmac = new HMACSHA1(key);
|
||||
var hash = hmac.ComputeHash(counter);
|
||||
var offset = hash[hash.Length - 1] & 0xf;
|
||||
|
||||
// Convert the 4 bytes into an integer, ignoring the sign.
|
||||
var binary =
|
||||
((hash[offset] & 0x7f) << 24)
|
||||
| (hash[offset + 1] << 16)
|
||||
| (hash[offset + 2] << 8)
|
||||
| hash[offset + 3];
|
||||
|
||||
var password = binary % (int)Math.Pow(10, digits);
|
||||
return password.ToString(new string('0', digits));
|
||||
}
|
||||
|
||||
private long GetCurrentCounter() => GetCurrentCounter(DateTime.UtcNow, _epoch, 30);
|
||||
|
||||
private long GetCurrentCounter(DateTime now, DateTime epoch, int timeStep) =>
|
||||
(long)(now - epoch).TotalSeconds / timeStep;
|
||||
|
||||
/// <summary>
|
||||
/// Given a PIN from a client, check if it is valid at the current time.
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <param name="twoFactorCodeFromClient">The PIN from the client</param>
|
||||
/// <param name="secretIsBase32">Flag saying if accountSecretKey is in Base32 format or original secret</param>
|
||||
/// <returns>True if PIN is currently valid</returns>
|
||||
public bool ValidateTwoFactorPIN(string accountSecretKey, string twoFactorCodeFromClient, bool secretIsBase32 = false) =>
|
||||
ValidateTwoFactorPIN(accountSecretKey, twoFactorCodeFromClient, DefaultClockDriftTolerance, secretIsBase32);
|
||||
|
||||
/// <summary>
|
||||
/// Given a PIN from a client, check if it is valid at the current time.
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <param name="twoFactorCodeFromClient">The PIN from the client</param>
|
||||
/// <param name="timeTolerance">The time window within which to check to allow for clock drift between devices.</param>
|
||||
/// <param name="secretIsBase32">Flag saying if accountSecretKey is in Base32 format or original secret</param>
|
||||
/// <returns>True if PIN is currently valid</returns>
|
||||
public bool ValidateTwoFactorPIN(string accountSecretKey, string twoFactorCodeFromClient, TimeSpan timeTolerance, bool secretIsBase32 = false) =>
|
||||
ValidateTwoFactorPIN(ConvertSecretToBytes(accountSecretKey, secretIsBase32), twoFactorCodeFromClient, timeTolerance);
|
||||
|
||||
/// <summary>
|
||||
/// Given a PIN from a client, check if it is valid at the current time.
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <param name="twoFactorCodeFromClient">The PIN from the client</param>
|
||||
/// <returns>True if PIN is currently valid</returns>
|
||||
public bool ValidateTwoFactorPIN(byte[] accountSecretKey, string twoFactorCodeFromClient) =>
|
||||
ValidateTwoFactorPIN(accountSecretKey, twoFactorCodeFromClient, DefaultClockDriftTolerance);
|
||||
|
||||
/// <summary>
|
||||
/// Given a PIN from a client, check if it is valid at the current time.
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <param name="twoFactorCodeFromClient">The PIN from the client</param>
|
||||
/// <param name="timeTolerance">The time window within which to check to allow for clock drift between devices.</param>
|
||||
/// <returns>True if PIN is currently valid</returns>
|
||||
public bool ValidateTwoFactorPIN(byte[] accountSecretKey, string twoFactorCodeFromClient, TimeSpan timeTolerance)
|
||||
{
|
||||
return GetCurrentPINs(accountSecretKey, timeTolerance).Any(c => c == twoFactorCodeFromClient);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the PIN for current time; the same code that a 2FA app would generate for the current time.
|
||||
/// Do not validate directly against this as clockdrift may cause a a different PIN to be generated than one you did a second ago.
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <param name="secretIsBase32">Flag saying if accountSecretKey is in Base32 format or original secret</param>
|
||||
/// <returns>A 6-digit PIN</returns>
|
||||
public string GetCurrentPIN(string accountSecretKey, bool secretIsBase32 = false) =>
|
||||
GeneratePINAtInterval(accountSecretKey, GetCurrentCounter(), secretIsBase32: secretIsBase32);
|
||||
|
||||
/// <summary>
|
||||
/// Get the PIN for current time; the same code that a 2FA app would generate for the current time.
|
||||
/// Do not validate directly against this as clockdrift may cause a a different PIN to be generated than one you did a second ago.
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <param name="now">The time you wish to generate the pin for</param>
|
||||
/// <param name="secretIsBase32">Flag saying if accountSecretKey is in Base32 format or original secret</param>
|
||||
/// <returns>A 6-digit PIN</returns>
|
||||
public string GetCurrentPIN(string accountSecretKey, DateTime now, bool secretIsBase32 = false) =>
|
||||
GeneratePINAtInterval(accountSecretKey, GetCurrentCounter(now, _epoch, 30), secretIsBase32: secretIsBase32);
|
||||
|
||||
/// <summary>
|
||||
/// Get the PIN for current time; the same code that a 2FA app would generate for the current time.
|
||||
/// Do not validate directly against this as clockdrift may cause a a different PIN to be generated.
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <returns>A 6-digit PIN</returns>
|
||||
public string GetCurrentPIN(byte[] accountSecretKey) =>
|
||||
GeneratePINAtInterval(accountSecretKey, GetCurrentCounter());
|
||||
|
||||
/// <summary>
|
||||
/// Get the PIN for current time; the same code that a 2FA app would generate for the current time.
|
||||
/// Do not validate directly against this as clockdrift may cause a a different PIN to be generated.
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <param name="now">The time you wish to generate the pin for</param>
|
||||
/// <returns>A 6-digit PIN</returns>
|
||||
public string GetCurrentPIN(byte[] accountSecretKey, DateTime now) =>
|
||||
GeneratePINAtInterval(accountSecretKey, GetCurrentCounter(now, _epoch, 30));
|
||||
|
||||
/// <summary>
|
||||
/// Get all the PINs that would be valid within the time window allowed for by the default clock drift.
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <param name="secretIsBase32">Flag saying if accountSecretKey is in Base32 format or original secret</param>
|
||||
/// <returns></returns>
|
||||
public string[] GetCurrentPINs(string accountSecretKey, bool secretIsBase32 = false) =>
|
||||
GetCurrentPINs(accountSecretKey, DefaultClockDriftTolerance, secretIsBase32);
|
||||
|
||||
/// <summary>
|
||||
/// Get all the PINs that would be valid within the time window allowed for by the specified clock drift.
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <param name="timeTolerance">The clock drift size you want to generate PINs for</param>
|
||||
/// <param name="secretIsBase32">Flag saying if accountSecretKey is in Base32 format or original secret</param>
|
||||
/// <returns></returns>
|
||||
public string[] GetCurrentPINs(string accountSecretKey, TimeSpan timeTolerance, bool secretIsBase32 = false) =>
|
||||
GetCurrentPINs(ConvertSecretToBytes(accountSecretKey, secretIsBase32), timeTolerance);
|
||||
|
||||
/// <summary>
|
||||
/// Get all the PINs that would be valid within the time window allowed for by the default clock drift.
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <returns></returns>
|
||||
public string[] GetCurrentPINs(byte[] accountSecretKey) =>
|
||||
GetCurrentPINs(accountSecretKey, DefaultClockDriftTolerance);
|
||||
|
||||
/// <summary>
|
||||
/// Get all the PINs that would be valid within the time window allowed for by the specified clock drift.
|
||||
/// </summary>
|
||||
/// <param name="accountSecretKey">Account Secret Key</param>
|
||||
/// <param name="timeTolerance">The clock drift size you want to generate PINs for</param>
|
||||
/// <returns></returns>
|
||||
public string[] GetCurrentPINs(byte[] accountSecretKey, TimeSpan timeTolerance)
|
||||
{
|
||||
var codes = new List<string>();
|
||||
var iterationCounter = GetCurrentCounter();
|
||||
var iterationOffset = 0;
|
||||
|
||||
if (timeTolerance.TotalSeconds > 30)
|
||||
{
|
||||
iterationOffset = Convert.ToInt32(timeTolerance.TotalSeconds / 30.00);
|
||||
}
|
||||
|
||||
var iterationStart = iterationCounter - iterationOffset;
|
||||
var iterationEnd = iterationCounter + iterationOffset;
|
||||
|
||||
for (var counter = iterationStart; counter <= iterationEnd; counter++)
|
||||
{
|
||||
codes.Add(GeneratePINAtInterval(accountSecretKey, counter));
|
||||
}
|
||||
|
||||
return codes.ToArray();
|
||||
}
|
||||
|
||||
private static byte[] ConvertSecretToBytes(string secret, bool secretIsBase32) =>
|
||||
secretIsBase32 ? Base32Encoding.ToBytes(secret) : Encoding.UTF8.GetBytes(secret);
|
||||
}
|
||||
}
|
201
thirdparty/Google.Authenticator/LICENSE
vendored
Normal file
201
thirdparty/Google.Authenticator/LICENSE
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
43
thirdparty/Google.Authenticator/README.md
vendored
Normal file
43
thirdparty/Google.Authenticator/README.md
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
# GoogleAuthenticator
|
||||
Simple, easy to use server-side two-factor authentication library for .NET that works with Google Authenticator
|
||||
|
||||
[![Build Status](https://dev.azure.com/brandon-potter/GoogleAuthenticator/_apis/build/status/BrandonPotter.GoogleAuthenticator?branchName=master)](https://dev.azure.com/brandon-potter/GoogleAuthenticator/_build/latest?definitionId=1&branchName=master)
|
||||
[![NuGet Status](https://buildstats.info/nuget/GoogleAuthenticator)](https://www.nuget.org/packages/GoogleAuthenticator/)
|
||||
|
||||
[`Install-Package GoogleAuthenticator`](https://www.nuget.org/packages/GoogleAuthenticator)
|
||||
|
||||
## 1.x Usage
|
||||
See blog post for usage instructions *(1.x only)*:
|
||||
|
||||
https://csharprookie.wordpress.com/2015/03/17/implementing-free-two-factor-authentication-in-net-using-google-authenticator/
|
||||
|
||||
## 2.x Usage
|
||||
|
||||
*Additional examples at [Google.Authenticator.WinTest](https://github.com/BrandonPotter/GoogleAuthenticator/tree/master/Google.Authenticator.WinTest) and [Google.Authenticator.WebSample](https://github.com/BrandonPotter/GoogleAuthenticator/tree/master/Google.Authenticator.WebSample)*
|
||||
|
||||
```csharp
|
||||
using Google.Authenticator;
|
||||
|
||||
string key = Guid.NewGuid().ToString().Replace("-", "").Substring(0, 10);
|
||||
|
||||
TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
|
||||
SetupCode setupInfo = tfa.GenerateSetupCode("Test Two Factor", "user@example.com", key, false, 3);
|
||||
|
||||
string qrCodeImageUrl = setupInfo.QrCodeSetupImageUrl;
|
||||
string manualEntrySetupCode = setupInfo.ManualEntryKey;
|
||||
|
||||
imgQrCode.ImageUrl = qrCodeImageUrl;
|
||||
lblManualSetupCode.Text = manualEntrySetupCode;
|
||||
|
||||
// verify
|
||||
TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
|
||||
bool result = tfa.ValidateTwoFactorPIN(key, txtCode.Text)
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
* Old documentation indicated specifying width and height for the QR code, but changes in QR generation now uses pixels per module (QR "pixel") so using a value too high will result in a huge image that can overrun memory allocations
|
||||
* Don't use the secret key and `ManualEntryKey` interchangeably. `ManualEntryKey` is used to enter into the authenticator app when scanning a QR code is impossible and is derived from the secret key ([discussion example](https://github.com/BrandonPotter/GoogleAuthenticator/issues/54))
|
||||
|
||||
# Notes
|
||||
On linux, you need to ensure `libgdiplus` is installed if you want to generate QR Codes. See [https://github.com/codebude/QRCoder/issues/227](https://github.com/codebude/QRCoder/issues/227).
|
@ -211,7 +211,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="GoogleAuthenticator" Version="2.4.0" />
|
||||
<PackageReference Include="GoogleAuthenticator" Version="2.4.1" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.43.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
Loading…
Reference in New Issue
Block a user