如何为开放ID连接生成众所周知的配置文件?

时间:2019-01-08 10:24:04

标签: php jwt openid-connect jwk

我们有一个openid connect的实现,该实现返回一个编码的id令牌,这个方法运行良好并且已经运行了一段时间。但是,我们尝试在aws中使用cognito连接到它,经过一番尝试和错误之后,我们发现我们缺少一个.well-known / openid-configuration文件。

此文件旨在包含有关对我们拥有的openid-connect服务器的调用的信息,包括JWK密钥。

我不了解JWK密钥,这意味着: 1.如何生成它们 2.一旦产生了对它们的处理? 3.我们用于openid-connect的现有代码是否需要更改和使用JWK密钥? 4.有什么方法可以验证openid-connect配置吗?

我前段时间曾问过类似的问题,但没有回头。

谢谢 凯文

我已经尝试过的方法: 曾在这里:https://mkjwk.org/,然后单击“新密钥”,它返回了我认为是Web密钥的信息。但是不知道我要用它做什么或其他选项卡的含义。

预期结果: 希望AWS Cognito能够继续并允许其连接到我们的开放ID Connect实现。目前,关于丢失的众所周知的配置文件,您只会得到一个错误。

2 个答案:

答案 0 :(得分:1)

您拥有的openid连接服务器生成的ID令牌为JWS。 这些令牌使用私钥(EC,RSA或OKP)签名。

众所周知的/ openid-configuration应该包含一个JSON对象,该对象指示使用什么算法来对令牌进行签名,以及url以获取与用于对令牌进行签名的私钥相关联的公钥。

例如,Google Account server configuration表示可以在https://www.googleapis.com/oauth2/v3/certsjwks_uri参数)处找到公钥。

在此URL上,您将找到以JWK(JSON Web密钥)格式设置的密钥(JWKSet)列表。这些格式(JWK和JWKSet)是JWT上下文中使用的密钥和密钥集的标准表示(请参见RFC7517)。

  
      
  1. 如何生成它们
  2.   

通常,您已经至少有一个私钥来对令牌进行签名,因此您不必生成新的私钥。

  
      
  1. 一旦产生了对它们的处理?
  2.   

您拥有的私钥应该是PEM(以------ PRIVATE RSA KEY -----或类似开头)或DER密钥。 您只需要将此密钥转换为JWK。

我创建了a small PHAR application (PHP),它将有助于转换您的密钥。该应用是Web Token Framework的一部分,但可以作为独立应用安装。确保已安装PHP 7.1,OpenSSL和JSON扩展。 安装该应用程序后,您可以执行以下命令:

jose key:convert:public $(jose key:load:key PATH_TO_YOUR_KEY)

此命令会将私钥转换为JWK,然后将其从私钥转换为公共。 可以通过jwks_uri端点共享结果。

  
      
  1. 我们为openid-connect提供的现有代码是否需要更改并使用JWK密钥?
  2.   

不。构建令牌的方式并不意味着您必须进行任何更改。

  
      
  1. 有什么方法可以验证openid-connect配置?
  2.   

据我所知,没有工具可以验证配置对象。您必须参考OpenID Connect规范。

答案 1 :(得分:0)

尽管Florent回答了公钥的用法,但我想向您指出定义JWK内容和特定实现细节的规范。

OpenID Connect discovery 定义发现文档。在那里,您找到jwks_uri URL作为元数据的一部分,它指向JSON Web Key Set

3. OpenID Provider Metadata

  

wks_uri

     

必填。 OP的JSON Web密钥集[JWK]文档的URL。这个   包含RP用于验证签名的签名密钥   OP

现在,这指向RFC7517 - JSON Web Key (JWK)。您可以在此处找到JSON有效负载每个字段的确切详细信息。请参阅其样本和附录部分以查看样本内容。并且您的实现必须遵循由此定义的规范要求。

对于编码,如果您使用的是JAVA,建议您使用 Nimbus JOSE + JWT库。可以从此link中找到示例。

例如,如果您已经加载X509Certificate,则以下是生成JWK的简约代码。它被嵌入到Servlet [Full source]中。

import Common.CertificateLoader;
import Common.Exceptions.FrameworkUncheckedException;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.jwk.JWK;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.cert.X509Certificate;

@WebServlet(urlPatterns = "/openid-configuration/jwks_uri")
public class JWKDocument extends HttpServlet {


@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    // NOTE - LOAD YOUR CERTIFICATE HERE
    final X509Certificate certificate = CertificateLoader.getCertificateLoader().getX509Certificate();

    final JWK jwk;

    try {
        jwk = JWK.parse(certificate);
    } catch (JOSEException e) {
        throw new FrameworkUncheckedException("Error while loading to JWK", e);
    }

    resp.getOutputStream().print(jwk.toJSONString());
  }
}