使用IRequiresSessionState, IReadOnlySessionState打破oauth2,但需要设置

本文关键字:设置 打破 IRequiresSessionState IReadOnlySessionState 使用 oauth2 | 更新日期: 2023-09-27 18:08:01

我有一个用c#编写的通用处理程序-这被称为OAuth2过程的一部分,通过Google验证用户。

一旦确定了正确的用户,我需要设置一个cookie,以便网站的其他部分可以识别该用户。

问题是为了设置会话变量的处理程序需要实现IRequiresSessionState -当我这样做-然后OAuth 2进程失败与以下错误。

收到的回调和客户端状态不匹配的OAuth授权响应异常

所以我可以实现OAuth或写一个会话变量,但不能两者都做。我可以让OAuth调用第一个页面,但随后可以在URL中看到代码(我宁愿不这样做-因为它为任何邪恶的人提供了破坏安全性的线索)。我可以得到一个页面调用处理程序,返回JSON来识别用户,并有页面本身设置会话变量,然后转到第一页-但这个页面将没有内容,以及需要两个跳转-所以你怎么能有一个HTML页面,本质上是空的,或者设置会话没有IRequiresSessionState打破会话。

OAuth处理程序的代码如下:

   public void ProcessRequest(HttpContext context)
    {
        NetworkParameters networkParameters     = null;
        NetworkParameter networkParameter       = null;
        WebServerClient consumer                = null;
        AuthorizationServerDescription server   = null;
        IAuthorizationState grantedAccess       = null;
        LoginResult loginResult                 = null;
        String code                             = String.Empty;
        String result                           = String.Empty;
        String consumerSecret                   = String.Empty;
        String consumerKey                      = String.Empty;
        String securityCookieVal                = String.Empty;
        Uri tokenEndpoint                       = null;
        Uri authorizationEndpoint               = null;
        Profile profile                         = null;
        Profile profile2                        = null;
        Profiles profiles                       = null;
        NetworkAuthorizations authorizations    = null;
        NetworkAuthorization na                 = null;
        try
        {
            loginResult             = new LoginResult();
            tokenEndpoint           = new Uri("https://accounts.google.com/o/oauth2/token");
            authorizationEndpoint   = new Uri("https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=auto");
            // retrieve network parameters
            networkParameters       = new NetworkParameters(Properties.Settings.Default.DatabaseConnection);
            authorizations          = new NetworkAuthorizations(Properties.Settings.Default.DatabaseConnection);
            networkParameter        = networkParameters.Select("GOOGLE");
            code                    = context.Request["code"];
            consumerKey             = networkParameter.ClientId;
            consumerSecret          = networkParameter.ClientSecret;
            // set up request
            server                          = new AuthorizationServerDescription();
            server.AuthorizationEndpoint    = authorizationEndpoint;
            server.TokenEndpoint            = tokenEndpoint;
            server.ProtocolVersion          = ProtocolVersion.V20;
            // initialise webserver client
            consumer = new WebServerClient(server, consumerKey, consumerSecret);
            consumer.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(consumerSecret);
            // retrieve access
            grantedAccess = consumer.ProcessUserAuthorization();
            profile  = GoogleServices.GetProfile(grantedAccess.AccessToken);
            profiles = new Profiles(Properties.Settings.Default.DatabaseConnection);
            profile2 = profiles.SelectByNetworkId(profile.Network, profile.NetworkId);
            if (profile2 == null)
            {
                na = new NetworkAuthorization()
                {
                    Id              = Guid.NewGuid().ToString(),
                    AccessToken     = grantedAccess.AccessToken,
                    ExpirationDate  = (DateTime)grantedAccess.AccessTokenExpirationUtc,
                    IssueDate       = (DateTime)grantedAccess.AccessTokenIssueDateUtc,
                    RefreshToken    = grantedAccess.RefreshToken,
                    Network         = profile.Network,
                    NetworkId       = profile.NetworkId
                };
                authorizations.Insert(na); 
                profiles.Insert(profile);
            }
            loginResult.UserId = profile.NetworkId;
        }
        catch (System.Exception e)
        {
            loginResult.Status.Status   = "ERROR";
            loginResult.Status.Message  = e.Message;
        }
        finally
        { 
            context.Response.ContentType = "application/json";
            context.Response.Write(JsonConvert.SerializeObject(loginResult));
        }
    }

使用IRequiresSessionState, IReadOnlySessionState打破oauth2,但需要设置

不是真正的答案-但我通过将随机生成的id传递给网站的第一页来解决这个问题,并将其存储在用户- cookie在第一页被调用时设置。

在查询字符串中发送这样的信息并不安全,但在原型中就足够了-最终的计划是使用Node.js,这将不会是一个问题。