Giter Site home page Giter Site logo

dazinator / aspnetcore.legacyauthcookiecompat Goto Github PK

View Code? Open in Web Editor NEW
73.0 10.0 18.0 86 KB

Provides classes to encrypt / decrypt asp.net 2 / 3.5 / 4 and 4.5 FormsAuthenticationTickets (cookies) without relying on system.web

License: MIT License

C# 99.84% Shell 0.16%

aspnetcore.legacyauthcookiecompat's Introduction

Build status

NuGet

AspNetCore.LegacyAuthCookieCompat

This library provides the ability to encrypt or decrypt a FormsAuthenticationTicket which are used for Forms Authentication cookies. The cookie will be compatible with ASP.NET 4.5 and lower web applications, that use FormsAuthentication, with SHA1, SHA256, SHA512 validations and AES. Both Framework20SP2 (ASP.NET 2.0 to 4.0 compatibility) and Framework45 (ASP.NET 4.5) compatibility modes are available.

This is useful if you are hoping to, for example, integrate OWIN / AspNet Core cookies middleware, with a legacy .NET 4.5 (or lower) web application, and want single sign on / off.

Usage

In order to encrypt / decrypt the auth cookie data, you need to provide the ValidationKey and DecryptionKey. These can usually be found in your existing asp.net websites web.config.

Web.config with SHA1 should like like below:

    <machineKey validation="SHA1" validationKey="XXXXX" decryption="AES" decryptionKey="XXXXX" />

Web.config with SHA256 should like like below:

    <machineKey validation="HMACSHA256" validationKey="XXXXX" decryption="AES" decryptionKey="XXXXX" />

Web.config with SHA512 should like like below:

    <machineKey validation="HMACSHA512" validationKey="XXXXX" decryption="AES" decryptionKey="XXXXX" />

Then, within your application that wishes to read the cookie (or produce one) - add the following NuGet package:

https://www.nuget.org/packages/AspNetCore.LegacyAuthCookieCompat/

To encrypt a FormsAuthenticationTicket do the following: (We'd usually then write the encrypted data as an auth cookie)

string validationKey = "30101052676849B0B494466B7A99656346328E8964748448E422D7344467A45777D972414947271744423422851D6742C9A09A65212C276C7F839157501291C6";
string decryptionKey = "AC7387D7E54B156377D81930CF237888854B5B5B515CF2D6356541255E696144";

// Arrange
var issueDate = DateTime.Now;
var expiryDate = issueDate.AddHours(1);
var formsAuthenticationTicket = new FormsAuthenticationTicket(2, "[email protected]", issueDate, expiryDate, false, "custom data", "/");

byte[] decryptionKeyBytes = HexUtils.HexToBinary(decryptionKey);
byte[] validationKeyBytes = HexUtils.HexToBinary(validationKey);

// Default compatibility mode is Framework20SP2. This supports ASP.NET 2.0 applications as well as higher version with compatibilityMode="Framework20SP1" on the machineKey config.
var legacyFormsAuthenticationTicketEncryptor = new LegacyFormsAuthenticationTicketEncryptor(decryptionKeyBytes, validationKeyBytes, ShaVersion.Sha1);
// For ASP.NET 4.5 applications without compatibilityMode="Framework20SP1", use Framework45 compatibility mode
// var legacyFormsAuthenticationTicketEncryptor = new LegacyFormsAuthenticationTicketEncryptor(decryptionKeyBytes, validationKeyBytes, ShaVersion.Sha1, CompatibilityMode.Framework45);

// Act
// We encrypt the forms auth cookie.
var encryptedText = legacyFormsAuthenticationTicketEncryptor.Encrypt(formsAuthenticationTicket);

To Decrypt: (We'd usually read the encrypted text from the auth cookie)

FormsAuthenticationTicket decryptedTicket = legacyFormsAuthenticationTicketEncryptor.DecryptCookie(encryptedText);

License

See the LICENSE file for license rights and limitations (MIT).

aspnetcore.legacyauthcookiecompat's People

Contributors

ausernamedtom avatar dazinator avatar dependabot-preview[bot] avatar jonathantower avatar kugushev avatar lemoinem avatar stnoa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aspnetcore.legacyauthcookiecompat's Issues

Not compatible with netcoreapp1.0

This looks perfect for my usage, but I'm unable to install it from nuget, I get:

Package AspNetCore.LegacyAuthCookieCompat 1.0.1 is not compatible with netcoreapp1.0 (.NETCoreApp,Version=v1.0). Package AspNetCore.LegacyAuthCookieCompat 1.0.1 supports: net45 (.NETFramework,Version=v4.5)

Example of implementation in .NET Core app?

Hello,

Could you add an example of how to actually use this library within a .NET Core app? I'm confused as to what to do next after decrypting the legacy FormsAuth ticket to let .NET Core then use it correctly to set the authenticated User principal.

Add FormsProtectionEnum support

I wanted to say thank you for adding backwards compatibility support to FormAuthentication! It helped me recreate the cookie to support the other old apps.

I have a feature request to add in FormsProtectionEnum, I am currently using Validation protection.
For example, here is the old configuration of the security settings:
<authentication mode="Forms"> <forms name=".ASPXFORMSDEMO" requireSSL="true" protection="Validation" loginUrl="/" timeout="120" slidingExpiration="true" /> </authentication>

In the asp.net FormsAuthentication it only encrypts the cookie if the Protection is not Validation: https://github.com/microsoft/referencesource/blob/master/System.Web/Security/FormsAuthentication.cs#L276

License?

Could you please clarify what license this package is available under? I couldn't find any license information in either the source code or the NuGet package metadata.

Can I integrate with AspNet FedAuth Cookie?

Hi,
We had a authserver which serves FedAuth token for existing .Net framework projects.
Now We are .net core web project for Integrate auth server.Is there any solution for that ?

Regards,

Validation other than SHA1

I'm trying to interact with a Framework system using HMACSHA256 as a validation algorithm in its machinekey. I need to implement single-sign-on between that Framework system and a new .NET Core 2 system.
I have full access to the config of the Framework system, but don't want to change its existing machine key as I need to avoid logging out existing users on that system.

Any advice on how best to approach this?

dotnet core webapi integration examples

Is there any examples of integration with dotnet core webapi (or mvc)?

If I understand things right we may:

  1. User CookieAuthentication with custom events handler
  2. Write own auth middleware
  3. something else...

There is way to many approaches to choose from, maybe someone may share their experience?

In our case we wish to have JWT based auth in our API but still auth users coming from legacy app by cookie

Error decrypting cookie

I'm trying to get an older ASP.NET 4.x cookie decrypted in my ASP.NET Core 2.0 application but I get a System.Exception when I try and decrypt.

My older ASP.NET 4.x application is configured as:

<machineKey
  validationKey=""
  decryptionKey=""
  validation="SHA1"
  decryption="AES" />
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(new FormsAuthenticationTicket
    (
        1,
        user.Username,
        DateTime.Now,
        DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes),
        false,
        JsonConvert.SerializeObject(userContext, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore })
    )));

My ASP.NET Core 2.0 code looks like this:

string cookie;
if (!Context.Request.Cookies.TryGetValue(Options.Name, out cookie))
{
    // No cookie was provided
    return Task.FromResult(AuthenticateResult.NoResult());
}

var decryptionKey = HexUtils.HexToBinary(Options.DecryptionKey);
var validationKey = HexUtils.HexToBinary(Options.ValidationKey);
var legacyFormsAuthenticationTicketEncryptor = new LegacyFormsAuthenticationTicketEncryptor(decryptionKey, validationKey);
var ticket = legacyFormsAuthenticationTicketEncryptor.DecryptCookie(cookie);

I've made sure the validation and decryption keys match and I've also tried changing my legacy application to use compatibilityMode="Framework20SP2" but I get an exception every time I try to decrypt. The value I'm passing to DecryptCookie is the plain cookie value, no prefix or suffix.

What am I doing wrong?

AppVeyor CI build

Need to setup an AppVeyor CI build that will

  1. Use GitVersion for version number stamping.
  2. Publish CI builds of master to NuGet.org

No `machineKey` node in Web.config

How do I find the required cryptographic values if the machineKey node is not present in Web.config.

In fact, I can't seem to find any source of cryptographic values used by FormsAuthentication in my existing APS.NET application.

P.S. thank you for your suggestion to use your library over at dotnet/systemweb-adapters#228.

Convert to NETSTANDARD library

Convert the library to a netstandard library so it can be used by a broader range of platforms.

It looks like the lowest I can target is .netstandard 1.3 because that's when the RandomNumberGenerator class lights up: https://apisof.net/catalog/System.Security.Cryptography.RandomNumberGenerator`

This means this library can be used by any application running on a platform that support netstandard1.3 and above.
https://docs.microsoft.com/en-us/dotnet/articles/standard/library

2FA with TOTP

Can we use google authenticator to introduce 2FA with the current system which uses Forms Authentication cookies?

Thanks

HashProvider constructor breaks other HashProviders

I would like to be able to instantiate two LegacyFormsAuthenticationTicketEncryptor with different algorithms, to support legacy cookies and newer cookies going forward. Suggestions for a workaround would be very welcome! (If there is something in Core that does a similar job of asymmetric + symmetric, path keys simply passed in as byte[]/strings, that would be better)

from the source, here is the problem:

public abstract class HashProvider
    {
        private **static** int _HashSize;
...
        protected HashProvider(byte[] validationKey, int hashSize, int keySize)
        {
            **_HashSize = hashSize;**

reproduce in practise w/ this failing unit test:

            var ticket = new FormsAuthenticationTicket(2, "hi", DateTime.Now, DateTime.Now, true, "asdf", "123");
            var decryptionKey = HexUtils.HexToBinary("000000000000000000000000000000000000000000000000");
            var validationKey = HexUtils.HexToBinary("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
            var encryptorSha256 = new LegacyFormsAuthenticationTicketEncryptor(decryptionKey, validationKey, ShaVersion.Sha256, CompatibilityMode.Framework20SP2);
            // static _HashSize is now 32
            var encryptorSha1 = new LegacyFormsAuthenticationTicketEncryptor(decryptionKey, validationKey, ShaVersion.Sha1, CompatibilityMode.Framework20SP2);
            // static _HashSize is now 20
            var encrypted = encryptorSha256.Encrypt(ticket);
            encryptorSha256.DecryptCookie(encrypted); // fails, expecting hash size of 20 (sha1) not 32 (sha256)

suggested fix: just make HashProvider._HashSize and HashProvider._KeySize instance variables

UTC vs LocalTime in FormsAuthenticationTicket

The code to serialize and deserialize the FormsAuthenticationTicket assumes the data in FormsAuthenticationTicket for issue and expiration dates to be local DateTimes.

In ASP.Net old code:
https://github.com/microsoft/referencesource/blob/master/System.Web/Security/FormsAuthenticationTicketSerializer.cs:

Serialize has code ticketWriter.Write(ticket.IssueDateUtc.Ticks); and ticketWriter.Write(ticket.ExpirationUtc.Ticks);
Deserialize calls FormsAuthenticationTicket.FromUtc

In AspNetCore.LegacyAuthCookieCompat (class FormsAuthenticationTicketHelper):

Serialize has code ticketWriter.Write(ticket.IssueDate.ToUniversalTime().Ticks); and ticketWriter.Write(ticket.Expiration.ToUniversalTime().Ticks);
Deserialize calls FormsAuthenticationTicketHelper.FromUtc

Moreover, in old ASP.Net code, FormsAuthenticationTicket.FromUtc converts the issueDateUtc and expirationUtc to local time with .ToLocalTime() (https://github.com/microsoft/referencesource/blob/master/System.Web/Security/FormsAuthenticationTicket.cs#L228-L229)

This last step isn't done in AspNetCore.LegacyAuthCookieCompat (See https://github.com/dazinator/AspNetCore.LegacyAuthCookieCompat/blob/master/src/AspNetCore.LegacyAuthCookieCompat/FormsAuthenticationTicketHelper.cs#L129-L131).

Because of this, the issue date and expiration date of deserialized tickets is never the correct one, as it will always be UTC.

Tests didn't catch that because they incorrectly create FormsAuthenticationTicket with UTC DateTime instead of local ones and didn't double check the date from the tickets deserialized from legacy ASP.Net serialization.

This is a major issue as tickets will have an extended or shortened lifetime depending on which side of UTC we are.

I will be preparing a pull request fixing these issues.

would like to have encryptions options to support 3Des and etc

HI,

I'm trying to solve my issue on legacy cookie which is encrypted using method different than AES, may I know where I can find document on the original MS source code on for other methods? I would rewrite it to support additional method if possible.

asp.net 4.5

Hi - I am using this package to generate a encrypted cookie value and match the value created in ASP.NET 4.5. Is ASP.NET 4.5 is supported by this library ? Please advice.

Signature verification failed

Hello,

I receive the following exception when trying to decrypt a cookie using the default generated keys from IIS Manager: "Signature verification failed"

From the UI of IIS Manager, the selected validation method is SHA1, and the encryption method is Auto. below is the generated web.config:

<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.web> <machineKey decryptionKey="00C96CD92F741B6E4C402F6BEFC682546DE43DC837EBDCA9" validationKey="2FF8E2B905FC0D8B47F99B3B719817112F35078669ADB20075B4F4039AAE89BF7F44F2F3477A2F099174893914A3D6437D2E1F3D09C84B0059BD4421410E276A" /> </system.web> </configuration>

I'm using the following parameters to decrypt a cookie:
var decryptor = new LegacyFormsAuthenticationTicketEncryptor( HexUtils.HexToBinary("00C96CD92F741B6E4C402F6BEFC682546DE43DC837EBDCA9"), HexUtils.HexToBinary("2FF8E2B905FC0D8B47F99B3B719817112F35078669ADB20075B4F4039AAE89BF7F44F2F3477A2F099174893914A3D6437D2E1F3D09C84B0059BD4421410E276A"), ShaVersion.Sha1 );

Is there anything wrong from my end to get that exception?

Trouble decrypting cookie

I very much like your approach and would like to use your nuget package, but I'm trying to decrypt a formsauth cookie generated from an existing application and getting an error with the SHA1 validation here:

if (isHashAppended)
{
	// need to check the hash signature, and strip it off the end of the byte array.
	cookieBlob = hasher.CheckHashAndRemove(cookieBlob);
	if (cookieBlob == null)
	{
		// signature verification failed
		throw new Exception();
	}
}

I'm using the code below to attempt the decryption:

string validationKey = "aaaaa";
string decryptionKey = "bb";
byte[] decryptionKeyBytes = HexUtils.HexToBinary(decryptionKey);
byte[] validationKeyBytes = HexUtils.HexToBinary(validationKey);

var legacyFormsAuthenticationTicketEncryptor = 
	new LegacyFormsAuthenticationTicketEncryptor(decryptionKeyBytes, validationKeyBytes);

FormsAuthenticationTicket decryptedFormsAuthenticationTicket =
	legacyFormsAuthenticationTicketEncryptor.DecryptCookie("value from the right of .ASPXAUTH= in the cookie");

And grabbed the validation key (aaaaa) and decryption key (bb) from the existing app's web.config:

<machineKey validationKey="aaaaa" decryptionKey="bb" validation="SHA1" decryption="AES" />
    <authentication mode="Forms">

The exisiting app is create the cookie like this:

FormsAuthentication.SetAuthCookie("username", false);

Any thoughts?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.