Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support to .NET Standard #62

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[Oo]bj/
[Bb]in/
packages/
packages/
.vs
62 changes: 20 additions & 42 deletions Microsoft.AspNet.Identity.sln
Original file line number Diff line number Diff line change
@@ -1,57 +1,27 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30408.0
# Visual Studio Version 17
VisualStudioVersion = 17.9.34616.47
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Identity.Core", "src\Microsoft.AspNet.Identity.Core\Microsoft.AspNet.Identity.Core.csproj", "{D2F24972-0F56-4C18-BD65-C26A320A0C68}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNet.Identity.Core", "src\Microsoft.AspNet.Identity.Core\Microsoft.AspNet.Identity.Core.csproj", "{D2F24972-0F56-4C18-BD65-C26A320A0C68}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0C1D4BD7-0771-4899-AF55-43D8791660A0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Identity.EntityFramework", "src\Microsoft.AspNet.Identity.EntityFramework\Microsoft.AspNet.Identity.EntityFramework.csproj", "{D7298DAD-AB04-4502-9567-0461D0AD059E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNet.Identity.EntityFramework", "src\Microsoft.AspNet.Identity.EntityFramework\Microsoft.AspNet.Identity.EntityFramework.csproj", "{D7298DAD-AB04-4502-9567-0461D0AD059E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{FD5D1AFD-204F-4504-B8F3-74C2E1EEC848}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8883A4C2-A8DF-4F24-ADF7-DAEBFBEFD21B}"
ProjectSection(SolutionItems) = preProject
License.txt = License.txt
unittest.testsettings = unittest.testsettings
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Identity.Owin", "src\Microsoft.AspNet.Identity.Owin\Microsoft.AspNet.Identity.Owin.csproj", "{943170EB-F4E7-4A6D-989E-2CF6C681DD89}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity.Test", "test\Identity.Test\Identity.Test.csproj", "{A7082BDD-985B-47B9-915B-7FA4CF541B5E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Identity.Test", "test\Identity.Test\Identity.Test.csproj", "{A7082BDD-985B-47B9-915B-7FA4CF541B5E}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Identity.Owin", "src\Microsoft.AspNet.Identity.Owin\Microsoft.AspNet.Identity.Owin.csproj", "{943170EB-F4E7-4A6D-989E-2CF6C681DD89}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{99DB175F-B1B4-4C9B-9D4A-C21F1ED2FB86}"
ProjectSection(SolutionItems) = preProject
.nuget\NuGet.Config = .nuget\NuGet.Config
.nuget\NuGet.exe = .nuget\NuGet.exe
.nuget\NuGet.targets = .nuget\NuGet.targets
.nuget\packages.config = .nuget\packages.config
EndProjectSection
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNet.Identity.AspNetCore", "src\Microsoft.AspNet.Identity.AspNetCore\Microsoft.AspNet.Identity.AspNetCore.csproj", "{5DEFA76C-346F-4C97-A7D6-FAD6E19F6B7F}"
EndProject
Global
GlobalSection(TeamFoundationVersionControl) = preSolution
SccNumberOfProjects = 5
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs18
SccLocalPath0 = .
SccProjectUniqueName1 = src\\Microsoft.AspNet.Identity.Core\\Microsoft.AspNet.Identity.Core.csproj
SccProjectTopLevelParentUniqueName1 = Microsoft.AspNet.Identity.sln
SccProjectName1 = src/Microsoft.AspNet.Identity.Core
SccLocalPath1 = src\\Microsoft.AspNet.Identity.Core
SccProjectUniqueName2 = src\\Microsoft.AspNet.Identity.EntityFramework\\Microsoft.AspNet.Identity.EntityFramework.csproj
SccProjectTopLevelParentUniqueName2 = Microsoft.AspNet.Identity.sln
SccProjectName2 = src/Microsoft.AspNet.Identity.EntityFramework
SccLocalPath2 = src\\Microsoft.AspNet.Identity.EntityFramework
SccProjectUniqueName3 = src\\Microsoft.AspNet.Identity.Owin\\Microsoft.AspNet.Identity.Owin.csproj
SccProjectTopLevelParentUniqueName3 = Microsoft.AspNet.Identity.sln
SccProjectName3 = src/Microsoft.AspNet.Identity.Owin
SccLocalPath3 = src\\Microsoft.AspNet.Identity.Owin
SccProjectUniqueName4 = test\\Identity.Test\\Identity.Test.csproj
SccProjectTopLevelParentUniqueName4 = Microsoft.AspNet.Identity.sln
SccProjectName4 = test/Identity.Test
SccLocalPath4 = test\\Identity.Test
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Expand All @@ -65,23 +35,31 @@ Global
{D7298DAD-AB04-4502-9567-0461D0AD059E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D7298DAD-AB04-4502-9567-0461D0AD059E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D7298DAD-AB04-4502-9567-0461D0AD059E}.Release|Any CPU.Build.0 = Release|Any CPU
{943170EB-F4E7-4A6D-989E-2CF6C681DD89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{943170EB-F4E7-4A6D-989E-2CF6C681DD89}.Debug|Any CPU.Build.0 = Debug|Any CPU
{943170EB-F4E7-4A6D-989E-2CF6C681DD89}.Release|Any CPU.ActiveCfg = Release|Any CPU
{943170EB-F4E7-4A6D-989E-2CF6C681DD89}.Release|Any CPU.Build.0 = Release|Any CPU
{A7082BDD-985B-47B9-915B-7FA4CF541B5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7082BDD-985B-47B9-915B-7FA4CF541B5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7082BDD-985B-47B9-915B-7FA4CF541B5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7082BDD-985B-47B9-915B-7FA4CF541B5E}.Release|Any CPU.Build.0 = Release|Any CPU
{943170EB-F4E7-4A6D-989E-2CF6C681DD89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{943170EB-F4E7-4A6D-989E-2CF6C681DD89}.Debug|Any CPU.Build.0 = Debug|Any CPU
{943170EB-F4E7-4A6D-989E-2CF6C681DD89}.Release|Any CPU.ActiveCfg = Release|Any CPU
{943170EB-F4E7-4A6D-989E-2CF6C681DD89}.Release|Any CPU.Build.0 = Release|Any CPU
{5DEFA76C-346F-4C97-A7D6-FAD6E19F6B7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5DEFA76C-346F-4C97-A7D6-FAD6E19F6B7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5DEFA76C-346F-4C97-A7D6-FAD6E19F6B7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5DEFA76C-346F-4C97-A7D6-FAD6E19F6B7F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{D2F24972-0F56-4C18-BD65-C26A320A0C68} = {0C1D4BD7-0771-4899-AF55-43D8791660A0}
{D7298DAD-AB04-4502-9567-0461D0AD059E} = {0C1D4BD7-0771-4899-AF55-43D8791660A0}
{943170EB-F4E7-4A6D-989E-2CF6C681DD89} = {0C1D4BD7-0771-4899-AF55-43D8791660A0}
{A7082BDD-985B-47B9-915B-7FA4CF541B5E} = {FD5D1AFD-204F-4504-B8F3-74C2E1EEC848}
{943170EB-F4E7-4A6D-989E-2CF6C681DD89} = {0C1D4BD7-0771-4899-AF55-43D8791660A0}
{5DEFA76C-346F-4C97-A7D6-FAD6E19F6B7F} = {0C1D4BD7-0771-4899-AF55-43D8791660A0}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {18A616DC-B136-4FD9-B3BC-DCE7D07D0693}
EndGlobalSection
GlobalSection(TestCaseManagementSettings) = postSolution
CategoryFile = Microsoft.AspNet.Identity.vsmdi
Expand Down
Binary file not shown.
192 changes: 192 additions & 0 deletions src/Microsoft.AspNet.Identity.AspNetCore/DataProtectorTokenProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// Copyright (c) Microsoft Corporation, Inc. All rights reserved.
// Licensed under the MIT License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.DataProtection;

namespace Microsoft.AspNet.Identity.AspNetCore
{
/// <summary>
/// Token provider that uses an IDataProtector to generate encrypted tokens based off of the security stamp
/// </summary>
public class DataProtectorTokenProvider<TUser> : DataProtectorTokenProvider<TUser, string>
where TUser : class, IUser<string>
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="protector"></param>
public DataProtectorTokenProvider(IDataProtector protector) : base(protector)
{
}
}

/// <summary>
/// Token provider that uses an IDataProtector to generate encrypted tokens based off of the security stamp
/// </summary>
public class DataProtectorTokenProvider<TUser, TKey> : IUserTokenProvider<TUser, TKey>
where TUser : class, IUser<TKey> where TKey : IEquatable<TKey>
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="protector"></param>
public DataProtectorTokenProvider(IDataProtector protector)
{
if (protector == null)
{
throw new ArgumentNullException("protector");
}
Protector = protector;
TokenLifespan = TimeSpan.FromDays(1);
}

/// <summary>
/// IDataProtector for the token
/// </summary>
public IDataProtector Protector { get; private set; }

/// <summary>
/// Lifespan after which the token is considered expired
/// </summary>
public TimeSpan TokenLifespan { get; set; }

/// <summary>
/// Generate a protected string for a user
/// </summary>
/// <param name="purpose"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
public async Task<string> GenerateAsync(string purpose, UserManager<TUser, TKey> manager, TUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
var ms = new MemoryStream();
using (var writer = ms.CreateWriter())
{
writer.Write(DateTimeOffset.UtcNow);
writer.Write(Convert.ToString(user.Id, CultureInfo.InvariantCulture));
writer.Write(purpose ?? "");
string stamp = null;
if (manager.SupportsUserSecurityStamp)
{
stamp = await manager.GetSecurityStampAsync(user.Id).WithCurrentCulture();
}
writer.Write(stamp ?? "");
}
var protectedBytes = Protector.Protect(ms.ToArray());
return Convert.ToBase64String(protectedBytes);
}

/// <summary>
/// Return false if the token is not valid
/// </summary>
/// <param name="purpose"></param>
/// <param name="token"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
public async Task<bool> ValidateAsync(string purpose, string token, UserManager<TUser, TKey> manager, TUser user)
{
try
{
var unprotectedData = Protector.Unprotect(Convert.FromBase64String(token));
var ms = new MemoryStream(unprotectedData);
using (var reader = ms.CreateReader())
{
var creationTime = reader.ReadDateTimeOffset();
var expirationTime = creationTime + TokenLifespan;
if (expirationTime < DateTimeOffset.UtcNow)
{
return false;
}

var userId = reader.ReadString();
if (!String.Equals(userId, Convert.ToString(user.Id, CultureInfo.InvariantCulture)))
{
return false;
}
var purp = reader.ReadString();
if (!String.Equals(purp, purpose))
{
return false;
}
var stamp = reader.ReadString();
if (reader.PeekChar() != -1)
{
return false;
}

if (manager.SupportsUserSecurityStamp)
{
var expectedStamp = await manager.GetSecurityStampAsync(user.Id).WithCurrentCulture();
return stamp == expectedStamp;
}
return stamp == "";
}
}
// ReSharper disable once EmptyGeneralCatchClause
catch
{
// Do not leak exception
}
return false;
}

/// <summary>
/// Returns true if the provider can be used to generate tokens for this user
/// </summary>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
public Task<bool> IsValidProviderForUserAsync(UserManager<TUser, TKey> manager, TUser user)
{
return Task.FromResult(true);
}

/// <summary>
/// This provider no-ops by default when asked to notify a user
/// </summary>
/// <param name="token"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
public Task NotifyAsync(string token, UserManager<TUser, TKey> manager, TUser user)
{
return Task.FromResult(0);
}
}

// Based on Levi's authentication sample
internal static class StreamExtensions
{
internal static readonly Encoding DefaultEncoding = new UTF8Encoding(false, true);

public static BinaryReader CreateReader(this Stream stream)
{
return new BinaryReader(stream, DefaultEncoding, true);
}

public static BinaryWriter CreateWriter(this Stream stream)
{
return new BinaryWriter(stream, DefaultEncoding, true);
}

public static DateTimeOffset ReadDateTimeOffset(this BinaryReader reader)
{
return new DateTimeOffset(reader.ReadInt64(), TimeSpan.Zero);
}

public static void Write(this BinaryWriter writer, DateTimeOffset value)
{
writer.Write(value.UtcTicks);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation, Inc. All rights reserved.
// Licensed under the MIT License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.AspNetCore;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;

namespace Microsoft.AspNetCore
{
/// <summary>
/// Extensions methods on IAuthenticationManager that add methods for using the default Application and External
/// authentication type constants
/// </summary>
internal static class AuthenticationManagerExtensions
{
/// <summary>
/// Returns true if there is a TwoFactorRememberBrowser cookie for a user
/// </summary>
/// <param name="manager"></param>
/// <param name="userId"></param>
/// <returns></returns>
internal static async Task<bool> TwoFactorBrowserRememberedAsync(this HttpContext manager,
string userId)
{
if (manager == null)
{
throw new ArgumentNullException("manager");
}
var result =
await manager.AuthenticateAsync(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie).WithCurrentCulture();
return (result?.Principal?.Identity is ClaimsIdentity claimsIdentity && claimsIdentity.GetUserId() == userId);
}

/// <summary>
/// Creates a TwoFactorRememberBrowser cookie for a user
/// </summary>
/// <param name="manager"></param>
/// <param name="userId"></param>
/// <returns></returns>
internal static ClaimsIdentity CreateTwoFactorRememberBrowserIdentity(this HttpContext manager,
string userId)
{
if (manager == null)
{
throw new ArgumentNullException("manager");
}
var rememberBrowserIdentity = new ClaimsIdentity(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
rememberBrowserIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userId));
return rememberBrowserIdentity;
}
}
}
Loading