OWIN Self-Host CookieAuthentication & Legacy .NET 4.0 Application / FormsAuthenticationTicket

后端 未结 1 1931
离开以前
离开以前 2020-12-13 01:23

I have two bounded contexts:

  1. ASP.NET 4.0 MVC/WebForms Application
  2. OWIN Self-Hosted w/ ASP.NET Web API 2

The former is an existing well-

1条回答
  •  时光说笑
    2020-12-13 01:49

    There was some initial confusion on whether I could use the element within app.config. Further prototyping has shown that I can successfully share a single FormsAuthenticationTicket between both bounded contexts with the following code.

    Ideally, we will implement a proper authorization server to enable OpenID Connect, Forms, WS-Fed, etc and have both applications operate off bearer tokens. However, this is working nicely in the short-term. Hope this helps!

    I have tested and verified successful encryption/decryption with both applications, sliding of formsauthticket timeout. You should be mindful of your web.config formsAuthentication setting for ticketCompatibilityMode.


    appBuilder.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                CookieName = FormsAuthentication.FormsCookieName,
                CookieDomain = FormsAuthentication.CookieDomain,
                CookiePath = FormsAuthentication.FormsCookiePath,
                CookieSecure = CookieSecureOption.SameAsRequest,
                AuthenticationMode = AuthenticationMode.Active,
                ExpireTimeSpan = FormsAuthentication.Timeout,
                SlidingExpiration = true,
                AuthenticationType = "Forms",
                TicketDataFormat = new SecureDataFormat(
                    new FormsAuthenticationTicketSerializer(), 
                    new FormsAuthenticationTicketDataProtector(), 
                    new HexEncoder())
            });
    

    
    
      
    
    
    

    public class HexEncoder : ITextEncoder
    {
        public String Encode(Byte[] data)
        {
            return data.ToHexadecimal();
        }
    
        public Byte[] Decode(String text)
        {
            return text.ToBytesFromHexadecimal();
        }
    }
    

    public class FormsAuthenticationTicketDataProtector : IDataProtector
    {
        public Byte[] Protect(Byte[] userData)
        {
            FormsAuthenticationTicket ticket;
            using (var memoryStream = new MemoryStream(userData))
            {
                var binaryFormatter = new BinaryFormatter();
                ticket = binaryFormatter.Deserialize(memoryStream) as FormsAuthenticationTicket;
            }
    
            if (ticket == null)
            {
                return null;
            }
    
            try
            {
                var encryptedTicket = FormsAuthentication.Encrypt(ticket);
    
                return encryptedTicket.ToBytesFromHexadecimal();
            }
            catch
            {
                return null;
            }
        }
    
        public Byte[] Unprotect(Byte[] protectedData)
        {
            FormsAuthenticationTicket ticket;
            try
            {
                ticket = FormsAuthentication.Decrypt(protectedData.ToHexadecimal());
            }
            catch
            {
                return null;
            }
    
            if (ticket == null)
            {
                return null;
            }
    
            using (var memoryStream = new MemoryStream())
            {
                var binaryFormatter = new BinaryFormatter();
                binaryFormatter.Serialize(memoryStream, ticket);
    
                return memoryStream.ToArray();
            }
        }
    }
    

    public class FormsAuthenticationTicketSerializer : IDataSerializer
    {
        public Byte[] Serialize(AuthenticationTicket model)
        {
            var userTicket = new FormsAuthenticationTicket(
                2,
                model.Identity.GetClaimValue(CustomClaim.UserName),
                new DateTime(model.Properties.IssuedUtc.Value.UtcDateTime.Ticks, DateTimeKind.Utc),
                new DateTime(model.Properties.ExpiresUtc.Value.UtcDateTime.Ticks, DateTimeKind.Utc),
                model.Properties.IsPersistent,
                String.Format(
                    "AuthenticationType={0};SiteId={1};SiteKey={2};UserId={3}",
                    model.Identity.AuthenticationType,
                    model.Identity.GetClaimValue(CustomClaim.SiteId),
                    model.Identity.GetClaimValue(CustomClaim.SiteKey),
                    model.Identity.GetClaimValue(CustomClaim.UserId)),
                FormsAuthentication.FormsCookiePath);
    
            using (var dataStream = new MemoryStream())
            {
                var binaryFormatter = new BinaryFormatter();
                binaryFormatter.Serialize(dataStream, userTicket);
    
                return dataStream.ToArray();
            }
        }
    
        public AuthenticationTicket Deserialize(Byte[] data)
        {
            using (var dataStream = new MemoryStream(data))
            {
                var binaryFormatter = new BinaryFormatter();
                var ticket = binaryFormatter.Deserialize(dataStream) as FormsAuthenticationTicket;
                if (ticket == null)
                {
                    return null;
                }
    
                var userData = ticket.UserData.ToNameValueCollection(';', '=');
                var authenticationType = userData["AuthenticationType"];
                var siteId = userData["SiteId"];
                var siteKey = userData["SiteKey"];
                var userId = userData["UserId"];
    
                var claims = new[]
                {
                    CreateClaim(CustomClaim.UserName, ticket.Name),
                    CreateClaim(CustomClaim.UserId, userId),
                    CreateClaim(CustomClaim.AuthenticationMethod, authenticationType),
                    CreateClaim(CustomClaim.SiteId, siteId),
                    CreateClaim(CustomClaim.SiteKey, siteKey)
                };
    
                var authTicket = new AuthenticationTicket(new UserIdentity(claims, authenticationType), new AuthenticationProperties());
                authTicket.Properties.IssuedUtc = new DateTimeOffset(ticket.IssueDate);
                authTicket.Properties.ExpiresUtc = new DateTimeOffset(ticket.Expiration);
                authTicket.Properties.IsPersistent = ticket.IsPersistent;
    
                return authTicket;
            }
        }
    
        private Claim CreateClaim(String type, String value)
        {
            return new Claim(type, value, ClaimValueTypes.String, CustomClaim.Issuer);
        }
    }
    

    0 讨论(0)
提交回复
热议问题