C# StateDataFormat.Unprotect()中的加密异常

C# StateDataFormat.Unprotect()中的加密异常,c#,asp.net,cryptography,openid-connect,azure-ad-b2c,C#,Asp.net,Cryptography,Openid Connect,Azure Ad B2c,我最近发布了一个问题,这个问题已经得到了回答,但导致了这个新问题。如果感兴趣,可在以下网址查看 介绍 我目前正在开发一个应用程序,使用AD-B2C作为我的身份提供商。在使用openid connect的AD B2C graph上,这是使用他们的指南集成到解决方案中的 我需要使用一种形式的电子邮件激活(在他们的注册策略之外),因此我需要能够从电子邮件中的URL传递一个值,通过B2C的注册过程,然后返回重定向URL 为此,我们使用状态参数 问题 在OnRedirectToIdentityProvid

我最近发布了一个问题,这个问题已经得到了回答,但导致了这个新问题。如果感兴趣,可在以下网址查看

介绍

我目前正在开发一个应用程序,使用AD-B2C作为我的身份提供商。在使用openid connect的AD B2C graph上,这是使用他们的指南集成到解决方案中的

我需要使用一种形式的电子邮件激活(在他们的注册策略之外),因此我需要能够从电子邮件中的URL传递一个值,通过B2C的注册过程,然后返回重定向URL

为此,我们使用状态参数

问题

在OnRedirectToIdentityProvider中,我加密状态

private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
    {
        var temp = notification.ProtocolMessage.State;
        // To be used later
        var mycustomparameter = notification.OwinContext.Get<string>("mycustomparameter");

        if (notification.ProtocolMessage.State != null)
        {
            var stateQueryString = notification.ProtocolMessage.State.Split('=');
            var protectedState = stateQueryString[1];
            var state = notification.Options.StateDataFormat.Unprotect(protectedState);
            state.Dictionary.Add("mycustomparameter", "testing");
            notification.ProtocolMessage.State = stateQueryString[0] + "=" + notification.Options.StateDataFormat.Protect(state);
        }
        return Task.FromResult(0);
    }
私有任务OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification)
{
var temp=notification.ProtocolMessage.State;
//待用
var mycustomparameter=notification.OwinContext.Get(“mycustomparameter”);
if(notification.ProtocolMessage.State!=null)
{
var stateQueryString=notification.ProtocolMessage.State.Split('=');
var protectedState=stateQueryString[1];
var state=notification.Options.StateDataFormat.Unprotect(protectedState);
state.Dictionary.Add(“mycustomparameter”、“testing”);
notification.ProtocolMessage.State=stateQueryString[0]+“=”+notification.Options.StateDataFormat.Protect(状态);
}
返回Task.FromResult(0);
}
据我所知,这是可行的

现在,用户被传递到广告B2C上的登录,并在登录后重定向回触发OnMessageReceived的位置

 private Task OnMessageReceived(MessageReceivedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
    {
        string mycustomparameter;
        var protectedState = notification.ProtocolMessage.State.Split('=')[1];

        var state = notification.Options.StateDataFormat.Unprotect(protectedState);
        state.Dictionary.TryGetValue("mycustomparameter", out mycustomparameter);
        return Task.FromResult(0);
    }
MessageReceived上的私有任务(MessageReceivedNotification通知)
{
字符串mycustomparameter;
var protectedState=notification.ProtocolMessage.State.Split('=')[1];
var state=notification.Options.StateDataFormat.Unprotect(protectedState);
state.Dictionary.TryGetValue(“mycustomparameter”,out mycustomparameter);
返回Task.FromResult(0);
}
这就是它断裂的地方。在…StateDataFormat.Unprotect(protectedState)中

它抛出一个错误System.Security.Cryptography.CryptographyException,消息为“加密操作期间出错”

编辑:堆栈跟踪:

System.Web.dll!System.Web.Security.Cryptography.同质化CryptoServiceWrapper.同质化错误(System.Func Func,byte[]输入)未知
System.Web.dll!System.Web.Security.Cryptography.UniformingCryptoServiceWrapper.Unprotect(字节[]protectedData)未知
System.Web.dll!System.Web.Security.MachineKey.Unprotect(System.Web.Security.cryptoServiceProvider cryptoServiceProvider cryptoServiceProvider,字节[]protectedData,字符串[]用途)未知
System.Web.dll!System.Web.Security.MachineKey.Unprotect(字节[]protectedData,字符串[]用途)未知
Microsoft.Owin.Host.SystemWeb.dll!Microsoft.Owin.Host.SystemWeb.DataProtection.MachineKeyDataProtector.Unprotect(字节[]protectedData)未知
Microsoft.Owin.Security.dll!Microsoft.Owin.Security.DataProtection.AppBuilderExtensions.CallDataProtectionProvider.CallDataProtection.Unprotect(字节[]protectedData)未知
Microsoft.Owin.Security.dll!Microsoft.Owin.Security.DataHandler.SecureDataFormat.Unprotect(字符串protectedText)未知
IntellifyPortal.dll!IntellifyPortal.Startup.OnMessageReceived(Microsoft.Owin.Security.Notifications.MessageReceivedNotification)第171 C行#

我的尝试

我已尝试在Web.config中指定机器密钥

我尝试过在OpenIdConnectAuthenticationOptions中处理“CallbackPath属性,但没有成功

我尝试了很多不同的调整,但我似乎不明白为什么我不能“取消”入站状态的保护

感谢您的帮助

致以最良好的祝愿

更新:解决方案

我已经决定使用另一种方法,我发现它很有效(希望它对其他人有用):

私有任务OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification)
{
var policy=notification.OwinContext.Get(“策略”);
如果(!string.IsNullOrEmpty(策略)和&!policy.Equals(DefaultPolicy))
{
notification.ProtocolMessage.Scope=OpenIdConnectScopes.OpenId;
notification.ProtocolMessage.ResponseType=OpenIDConnectResponseType.IdToken;
notification.ProtocolMessage.IssuerAddress=notification.ProtocolMessage.IssuerAddress.ToLower().Replace(DefaultPolicy.ToLower(),policy.ToLower());
}
//接受邀请电子邮件
字符串testValue=notification.OwinContext.Get(“testValue”);
字符串testValue2=notification.OwinContext.Get(“testValue2”);
如果(!string.IsNullOrEmpty(testValue)和&!string.IsNullOrEmpty(testValue2))
{
var stateQueryString=notification.ProtocolMessage.State.Split('=');
var protectedState=stateQueryString[1];
var state=notification.Options.StateDataFormat.Unprotect(protectedState);
state.Dictionary.Add(“testValue”,testValue);
state.Dictionary.Add(“testValue2”,testValue2);
notification.ProtocolMessage.State=stateQueryString[0]+“=”+notification.Options.StateDataFormat.Protect(状态);
}
返回Task.FromResult(0);
}
AuthorizationCodeReceived上的专用异步任务(AuthorizationCodeReceivedNotification通知)
{
//从响应通知中提取代码
var代码=notification.code;
string SignedUserId=notification.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache=新MSALSessionCache(SignedUserId,notification.owIncote)
System.Web.dll!System.Web.Security.Cryptography.HomogenizingCryptoServiceWrapper.HomogenizeErrors(System.Func<byte[], byte[]> func, byte[] input)   Unknown
System.Web.dll!System.Web.Security.Cryptography.HomogenizingCryptoServiceWrapper.Unprotect(byte[] protectedData)    Unknown
System.Web.dll!System.Web.Security.MachineKey.Unprotect(System.Web.Security.Cryptography.ICryptoServiceProvider cryptoServiceProvider, byte[] protectedData, string[] purposes) Unknown
System.Web.dll!System.Web.Security.MachineKey.Unprotect(byte[] protectedData, string[] purposes)    Unknown
Microsoft.Owin.Host.SystemWeb.dll!Microsoft.Owin.Host.SystemWeb.DataProtection.MachineKeyDataProtector.Unprotect(byte[] protectedData)  Unknown
Microsoft.Owin.Security.dll!Microsoft.Owin.Security.DataProtection.AppBuilderExtensions.CallDataProtectionProvider.CallDataProtection.Unprotect(byte[] protectedData)   Unknown
Microsoft.Owin.Security.dll!Microsoft.Owin.Security.DataHandler.SecureDataFormat<Microsoft.Owin.Security.AuthenticationProperties>.Unprotect(string protectedText)  Unknown
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
    {
        var policy = notification.OwinContext.Get<string>("Policy");

        if (!string.IsNullOrEmpty(policy) && !policy.Equals(DefaultPolicy))
        {
            notification.ProtocolMessage.Scope = OpenIdConnectScopes.OpenId;
            notification.ProtocolMessage.ResponseType = OpenIdConnectResponseTypes.IdToken;
            notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.ToLower().Replace(DefaultPolicy.ToLower(), policy.ToLower());
        }

        // Accept Invitation Email
        string testValue= notification.OwinContext.Get<string>("testValue");
        string testValue2= notification.OwinContext.Get<string>("testValue2");

        if (!string.IsNullOrEmpty(testValue) && !string.IsNullOrEmpty(testValue2))
        {
            var stateQueryString = notification.ProtocolMessage.State.Split('=');
            var protectedState = stateQueryString[1];
            var state = notification.Options.StateDataFormat.Unprotect(protectedState);
            state.Dictionary.Add("testValue", testValue);
            state.Dictionary.Add("testValue2", testValue2);
            notification.ProtocolMessage.State = stateQueryString[0] + "=" + notification.Options.StateDataFormat.Protect(state);
        }
        return Task.FromResult(0);
    }

private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
    {
        // Extract the code from the response notification
        var code = notification.Code;

        string signedInUserID = notification.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
        TokenCache userTokenCache = new MSALSessionCache(signedInUserID, notification.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance();
        ConfidentialClientApplication cca = new ConfidentialClientApplication(ClientId, Authority, RedirectUri, new ClientCredential(ClientSecret), userTokenCache, null);
        try
        {
            AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, Scopes);

            // Look for acceptInvitation
            string testValue;
            string testValue2;

            var protectedState = notification.ProtocolMessage.State.Split('=')[1];
            var state = notification.Options.StateDataFormat.Unprotect(protectedState);
            state.Dictionary.TryGetValue("testValue", out testValue);
            state.Dictionary.TryGetValue("testValue2", out testValue2);

            // InvitationAccept / store values
            if(!string.IsNullOrEmpty(testValue) && !string.IsNullOrEmpty(testValue2))
            {
                // How can I pass values to the redirect controller?
                // Can I somehow transfer it from here to that destination
            }
        }
        catch (Exception ex)
        {
            //TODO: Handle
            throw;
        }
    }