Office 365 Rest API - 守护程序周身份验证

Nic*_*her 9 ruby rest ssl exchangewebservices office365

我正在尝试构建一个Ruby Daemon服务来访问Office 365 rest API.最近通过OAuth'client_credentials'流程实现了这一点,详见本博客文章:http://blogs.msdn.com/b/exchangedev/archive/2015/01/22/building-demon-or -服务-应用程序-与办公-365-邮件日历和联系人的API-的oauth2客户端-凭据flow.aspx

我正在努力生成有效的访问令牌.令牌端点返回给我一个JWT但是当使用这个令牌时,我收到了一条带有此消息的401:

使用身份验证方法获取访问令牌,该身份验证方法太弱而无法访问此应用程序.提出的auth强度为1,要求为2

我知道client_credentials流程要求您提供X.509证书,不幸的是,博客文章中的所有示例都是针对C#的.

我在请求令牌时使用生成的自签名证书和私钥来执行客户端断言.我按照博客文章中的步骤生成证书并更新清单以使用此证书.

这是红宝石代码供参考:

def request_token
  uri = URI.parse("https://login.windows.net/== TENANT-ID ==/oauth2/token?api-version=1.0")
  https = Net::HTTP.new(uri.host, uri.port)

  req = Net::HTTP::Post.new(uri.request_uri)
  req.set_form_data(
    :grant_type    => 'client_credentials',
    :redirect_uri  => 'http://spready.dev',
    :resource      => 'https://outlook.office365.com/',
    :client_id     => '== Client ID ==',
    :client_secret => '== Client secret =='
  )

  https.use_ssl = true
  https.cert = client_cert
  https.key = client_key
  https.verify_mode = OpenSSL::SSL::VERIFY_PEER

  resp = https.start { |cx| cx.request(req) }

  @access_token = JSON.parse(resp.body)
end
Run Code Online (Sandbox Code Playgroud)

显然,为了安全起见,我删除了一些信息.即使它是ruby,您也可以看到我正在使用我的证书来验证使用SSL连接的客户端.

以下是有关错误的更多信息:

"x-ms-diagnostics" => "2000010;
    reason=\"The access token is acquired using an authentication method that is too weak to allow access for this application. Presented auth strength was 1, required is 2.\";
    error_category=\"insufficient_auth_strength\"", 
"x-diaginfo"=>"AM3PR01MB0662", 
"x-beserver"=>"AM3PR01MB0662"
Run Code Online (Sandbox Code Playgroud)

任何帮助将是欣赏.


编辑

对于其他想在Ruby中做类似事情的人来说,这是我使用的代码的要点:https://gist.github.com/NGMarmaduke/a088943edbe4e703129d

该示例使用Rails环境,但删除Rails特定位应该相当容易.

请记住使用正确的值替换您的CLIENT ID,TENANT_ID和CERT_THUMBPRINT,并将证书路径和客户端密钥方法指向正确的文件路径.

然后你可以做这样的事情:

mailbox = OfficeAPI.new("nick@test.com")
messages = mailbox.request_messages
Run Code Online (Sandbox Code Playgroud)

Jas*_*ton 10

而不是client_secret在您的请求正文中,您需要一个client_assertion.这有点复杂,但这是您需要该证书的原因.

基本上,您需要构建一个JSON Web令牌,并使用SHA256哈希对您的证书进行签名.令牌看起来像这样:

标题:

{ 
  "alg": "RS256",
  "x5t": "..." // THUMBPRINT of Cert
}
Run Code Online (Sandbox Code Playgroud)

有效载荷:

{
  "aud": "https:\\/\\/login.windows.net\\/<The logged in user's tenant ID>\\/oauth2\\/token",
  "exp": 1423168488,
  "iss": "YOUR CLIENT ID",
  "jti": "SOME GUID YOU ASSIGN",
  "nbf": 1423167888,
  "sub": "YOUR CLIENT ID"
}
Run Code Online (Sandbox Code Playgroud)

如果你还在我身边,你现在需要对两个部分进行base64编码(单独编写),然后用'.'连接它们.所以现在你应该:

base64_header.base64_payload
Run Code Online (Sandbox Code Playgroud)

现在,您使用SHA256哈希来获取该字符串并使用您的证书对其进行签名.然后base64编码结果,对其进行url-encode,然后追加到字符串,所以现在你有:

base64_header.base64_payload.base64_signature
Run Code Online (Sandbox Code Playgroud)

最后,在POST中将此作为client_assertion参数包含在令牌端点的POST中,并且还包括一个client_assertion_type参数设置为"urn:ietf:params:oauth:client-assertion-type:jwt-bearer":

req.set_form_data(
    :grant_type    => 'client_credentials',
    :redirect_uri  => 'http://spready.dev',
    :resource      => 'https://outlook.office365.com/',
    :client_id     => '== Client ID ==',
    :client_assertion_type => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
    :client_assertion => 'base64_header.base64_payload.base64_signature'
  )
Run Code Online (Sandbox Code Playgroud)

我希望有所帮助!这完全基于我对ADAL如何做到这一点的研究,我没有在Ruby中自己测试过.

  • 完美,再次感谢杰森.对于没有使用ADAL进行开发的人来说,这是一个好主意.可能会在此处更新Azure AD客户端凭据文档:https://msdn.microsoft.com/en-us/library/azure/dn645543.aspx (4认同)

And*_*tin 5

我只是设法让这个工作,所以我想我会再提出一条建议。那里的所有说明文章都说您应该将证书添加到清单文件中。我遇到了麻烦,但这是我所做的最终使它起作用的方法:

  • 在 Azure 中,转到设置 > 管理证书
  • 将公钥上传为.cer文件(如果您不知道如何转换,请在谷歌周围搜索)。这应该是一个二进制文件,您的文本编辑器会在其上显示。
  • 现在它已上传,Microsoft 将为您提供指纹。它位于“指纹”列中。但是,它是十六进制的,而不是 base64。所以,像这样转换它:

    # Hint: use your actual thumbprint, not this fake one
    echo '5292850026FADB09700E7D6C1BCB1CD1F3270BCC' | xxd -r -p | base64
    
    Run Code Online (Sandbox Code Playgroud)
  • 最后,使用这个 base64 编码的指纹作为x5tJSON 标头中的值。