Session 处理OAuth响应&;会议

Session 处理OAuth响应&;会议,session,cookies,oauth,go,Session,Cookies,Oauth,Go,在OAuth2令牌交换结束时,我[通常]只剩下一个JSON用户数据数组,我已将其解编组到一个结构(比如GoogleUser)中,其中包含我关心的字段 将数据记录到数据库中的合理方式是什么?只需从回调处理程序调用CreateUser函数,在检查用户在数据库中不存在后,传递结构并保存它(对我来说这是显而易见的方式) 我假设我应该在回调处理程序中创建一个会话令牌(即,session.Values[“authenticated”]==true),将其存储在cookie中(具有合理的到期日期),然后只需在

在OAuth2令牌交换结束时,我[通常]只剩下一个JSON用户数据数组,我已将其解编组到一个结构(比如GoogleUser)中,其中包含我关心的字段

将数据记录到数据库中的合理方式是什么?只需从回调处理程序调用
CreateUser
函数,在检查用户在数据库中不存在后,传递结构并保存它(对我来说这是显而易见的方式)

我假设我应该在回调处理程序中创建一个会话令牌(即,
session.Values[“authenticated”]==true
),将其存储在cookie中(具有合理的到期日期),然后只需在预期登录用户的任何处理程序函数上检查
if authenticated==true
?或者,对于管理员处理程序:
如果admin\u user==true
这里有什么风险(如果有)假设我是通过HTTPS和使用安全cookie进行讨论的


对基本问题表示歉意:只是想掌握一下在w/OAuth中登录用户的“最佳实践”方法。

OAuth标准中的
访问令牌
已经过期。它通常由授权服务器决定。在您的情况下,我假设您在授权服务器端

例如,阅读:

通常,承载令牌作为anOAuth 2.0[RFC6749]访问令牌响应的一部分返回给客户端。此类响应的一个例子是:

另请阅读以下内容中的
访问令牌的概念:

访问令牌提供了一个抽象层,替换了不同的 使用单个 资源服务器可以理解令牌。这种抽象使 颁发比授权授予更严格的访问令牌 用于获取它们,以及删除资源服务器的需要 了解广泛的身份验证方法

因此,在您的情况下,我认为不需要“cookie”或“管理处理程序”。您只需为每个登录的用户生成
访问令牌
&
刷新令牌
,就像
OAuth
规范所说的那样,并存储其到期日。您还可以提供与
访问令牌
相关的哈希方法,以确保它是合法请求。例如,用户使用其访问令牌通过哈希和salt方法生成签名,将访问令牌和签名发送到服务器进行验证。阅读更多细节


此外,您不需要将这些令牌保存到数据库中,因为它们都是临时资源。您还可以将所有用户信息保存在内存中,并实现一个缓存层,定期将这些真正重要的信息保存到数据库中(我现在正在使用),以降低数据库压力。

关于您的第一个问题,通常建议在单个事务中执行检查和插入。这取决于您使用的数据库,但这些通常被称为
UPSERT
语句。在PLSQL中,它看起来有点像这样(根据口味进行修改):

关于你的第二个问题,通常HTTPS上的
Secure
cookies就足够了。我设置了
HttpOnly
选项,通常还设置了
Path
选项


HttpOnly
意味着JS无法访问cookie(仅HTTP或HTTPS),而
Path
选项允许您指定cookie的有效路径(在URL中)。

我的问题可能不清楚:我正在实现OAuth2客户端,我正在尝试确定处理来自Google | GitHub |等的响应的“最佳实践”方法。一旦我获得一个包含用户数据(姓名、电子邮件、id、头像等)的JSON数组。我还试图确定当用户试图访问“私有”页面时对其进行身份验证的最佳方式;使用会话cookies似乎最适合这里;非常感谢。我正在使用RejectDB,它确实支持upserts(只是没有SQL语法):。谢谢你回答我的第二个问题:我的理解是,我真正使用cookie的唯一风险是重播攻击,但我计划有一个合理的到期日(7天)来限制这一风险。只要用户不能冒充管理员或其他用户,我就不会过分担心。我认为管理员用户的有效期短至30-60分钟可能是个好主意。他们可以造成更多的伤害!所以我得到赏金了吗?:-)如果你想等待一个更好的答案或更多的信息,这是很酷的。(我不得不等了12个小时才发布)
 HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
 Cache-Control: no-store
 Pragma: no-cache

 {
   "access_token":"mF_9.B5f-4.1JqM",
   "token_type":"Bearer",
   "expires_in":3600,
   "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA"
 }
CREATE FUNCTION upsert_user(emailv character varying, saltv character varying, hashv character varying, date_createdv timestamp without time zone) RETURNS void
    LANGUAGE plpgsql
AS $$;
BEGIN
    LOOP
        -- first try to update the key
        UPDATE users SET (salt, hash) = (saltv, hashv) WHERE email = emailv;
        IF found THEN
            RETURN;
        END IF;
        -- not there, so try to insert the key
        -- if someone else inserts the same key concurrently,
        -- we could get a unique-key failure
        BEGIN
            INSERT INTO users(email, salt, hash, date_created) VALUES (emailv, saltv, hashv, date_createdv);
            RETURN;
        EXCEPTION WHEN unique_violation THEN
            -- do nothing, and loop to try the UPDATE again
        END;
    END LOOP;
END;
$$;