外部 SSO 提供商但 discourse 日志显示 None 已过期(请帮助!)

我们使用 Firebase 作为外部单点登录(SSO)提供商。我们已按照 Discourse 的相关说明进行操作。

但在日志中我们遇到了如下错误:

详细 SSO 日志:SSO 流程已启动 add_groups: admin: moderator: avatar_force_update: avatar_url: bio: card_background_url: email: external_id: groups: locale: locale_force_update: logo

详细 SSO 日志:Nonce 已过期 add_groups: admin: moderator: avatar_force_update: avatar_url: bio: card_background_url: email: [真实邮箱]: external_id: [外部 ID]

此外,我们在 Discourse 日志中还看到:

详细 SSO 日志:SSO 流程已启动

add_groups: 
admin: 
moderator: 
avatar_force_update: 
avatar_url: 
bio: 
card_background_url: 
email: 
external_id: 
groups: 
locale: 
locale_force_update: 
logout: 
name: 
nonce: 773cb9d08db7007c9fb833e6c5e3a701
profile_background_url: 
remove_groups: 
require_activation: 
return_sso_url: https://discouse-site/session/sso_login
suppress_welcome_message: 
title: 
username: 
website: 
location: 

以及

详细 SSO 日志:Nonce 已过期

add_groups: 
admin: 
moderator: 
avatar_force_update: 
avatar_url: 
bio: 
card_background_url: 
email: [真实邮箱]
external_id: Be06ze0v0YO7I8SArWRoUVsxJ1k1
groups: 
locale: 
locale_force_update: 
logout: 
name: [真实邮箱]
nonce: Ym05dVkyVTlOV0kwTTJVeU1UTTVNamN6TnpNd01UbG1aVEJtWkRjMFlqTmtOV1U1TmpJbWNtVjBkWEp1WDNOemIxOTFjbXc5YUhSMGNITWxNMEVsTWtZbE1rWmpiMjF0ZFc1cGRIa3VZbTl2Wnk1aGNIQWxNa1p6WlhOemFXOXVKVEpHYzNOdlgyeHZaMmx1
profile_background_url: 
remove_groups: 
require_activation: 
return_sso_url: https://discouse-site/session/sso_login
suppress_welcome_message: 
title: 
username: [真实邮箱]
website: 
location:  

目前我们无法使用站点,非常希望 Discourse 团队能提供帮助。

James

我并非这方面的专家,但我的猜测是检查一下你的时钟是否准确。

感谢您的建议,但时钟似乎并非问题所在。Discourse 服务器与生成 nonce 的服务器时间是一致的。

我分享一下我们生成返回 URL 的方式,希望能进一步阐明这个问题:

public String generateSSORedirectURL(String nonce, String email, String uid) {

    // 生成返回载荷
    HashMap<String, String> params = new HashMap<String, String>();
    params.put("nonce", nonce);
    params.put("external_id", uid);
    params.put("email", email);
    params.put("username", email);
    params.put("require_activation", "false");
    params.put("name", email);
    params.put("return_sso_url", "https://discourse-site/session/sso_login");
    log.info("params {}", params);

    // 准备返回载荷
    String encodedParams = params.keySet().stream()
        .map(key -> key + "=" + encodeValue(params.get(key)))
        .collect(Collectors.joining("&"));
    log.info("encoded parameters {}", encodedParams);

    String returnPayload = Base64.getEncoder().encodeToString(encodedParams.getBytes());
    log.info("return Payload {}", returnPayload);

    // 计算载荷的 hmacSha256 签名
    byte[] hmacSha256 = calcHmacSha256(ssoSecret.getBytes(), returnPayload.getBytes());
    log.info("hmacSha256 sig {}", hmacSha256);
    
    String hmacSha265Hex = String.format("%x", new BigInteger(1, hmacSha256));
    log.info("hmacSha256, sig in Hex {}", String.format("%x", new BigInteger(1, hmacSha256)));

    HashMap<String, String> params2 = new HashMap<String, String>();
    params2.put("sig", hmacSha265Hex);
    params2.put("sso", returnPayload);
    log.info("params2 {}", params);

    String encodedParams2 = params2.keySet().stream()
        .map(key -> key + "=" + encodeValue(params2.get(key)))
        .collect(Collectors.joining("&"));
    log.info("encoded parameters {}", encodedParams2);

    // 构建并返回查询字符串
    String queryString = forumUrl + "session/sso_login?" + encodedParams2;
    log.info("queryString {}", queryString);

    return queryString;
}

你解决这个问题了吗?@James_Hope