Office 365 Rest API - 守护程序周身份验证 [英] Office 365 Rest API - Daemon week authentication

查看:33
本文介绍了Office 365 Rest API - 守护程序周身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个 Ruby 守护程序服务来访问 Office 365 rest API.最近可以通过 OAuth 'client_credentials' 流程执行此操作,如本博客文章中所述:https://docs.microsoft.com/en-us/archive/blogs/exchangedev/building-daemon-or-service-apps-with-office-365-mail-calendar-and-contacts-apis-oauth2-client-credential-flow

I am trying to build a Ruby Daemon service to access the Office 365 rest API. It was recently made possible to do this via the OAuth 'client_credentials' flow, as detailed in this blog post: https://docs.microsoft.com/en-us/archive/blogs/exchangedev/building-daemon-or-service-apps-with-office-365-mail-calendar-and-contacts-apis-oauth2-client-credential-flow

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

I am struggling to generate a valid access token. The token endpoint returns me a JWT however when using this token I received a 401 with this message:

访问令牌是使用太弱的身份验证方法获取的,该方法不允许此应用程序访问.提供的身份验证强度为 1,要求为 2

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

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

I understand that the client_credentials flow requires you to present a X.509 cert, unfortunately all the examples in the blog post are for C#.

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

I am using a generated self signed cert and private key to do a client assertion when requesting the token. I followed the steps in the blog post to generate the cert and update the manifest to use this cert.

这是参考的ruby代码:

This is the ruby code for reference:

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

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

Obviously I have removed certain bits of information for security. Even though it is ruby you can see I am using my cert to validate the client using an SSL connection.

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

Here's some more infomation on the error:

"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"

任何帮助将不胜感激.

编辑

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

For others looking to do something similar in Ruby here's a Gist of the code I use: https://gist.github.com/NGMarmaduke/a088943edbe4e703129d

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

The example uses a Rails environment but it should be fairly easy to strip out the Rails specific bits.

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

Remember to replace YOUR CLIENT ID, TENANT_ID and CERT_THUMBPRINT with the correct values and point the cert path and client key methods to the right file path.

然后你可以这样做:

mailbox = OfficeAPI.new("nick@test.com")
messages = mailbox.request_messages

推荐答案

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

Instead of a client_secret in your request body, you need a client_assertion. This is a bit more complex, but it's the reason you need that certificate.

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

Basically you need to build a JSON Web Token and sign it with your certificate using a SHA256 hash. The token is going to look something like this:

标题:

{ 
  "alg": "RS256",
  "x5t": "..." // THUMBPRINT of Cert
}

有效载荷:

{
  "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"
}

如果你还和我在一起,你现在需要对两部分进行 base64 编码(单独),然后用."将它们连接起来.所以现在你应该有:

If you're still with me, you now need to base64-encode both pieces (separately), then concatenate them with a '.'. So now you should have:

base64_header.base64_payload

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

Now you take that string and sign it with your certificate, using a SHA256 hash. Then base64-encode the result of that, url-encode it, then append to the string, so now you have:

base64_header.base64_payload.base64_signature

最后,将此作为 client_assertion 参数包含在您对令牌端点的 POST 中,并包含一个设置为urn:ietf:params:oauth:"的 client_assertion_type 参数:客户端断言类型:jwt-bearer":

Finally, include this in your POST to the token endpoint as the client_assertion parameter, and also include a client_assertion_type parameter set to "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'
  )

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

I hope that helps! This is all based on my research into how ADAL does it, and I haven't tested it myself in Ruby.

这篇关于Office 365 Rest API - 守护程序周身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆