【问题标题】:Authentication using Resource Owner Password Credentials in Rails在 Rails 中使用资源所有者密码凭据进行身份验证
【发布时间】:2017-03-17 17:18:57
【问题描述】:

我对 OAuth 身份验证方案相当陌生。目前对我造成的问题是从 Rails 应用程序中的服务器获取 access_token。

到目前为止,我阅读了几篇关于 OAuth 2.0 中与资源所有者密码凭据相关的方法的文章,但它仍然让我一无所获。 仅举几例Official documentation regarding ROPC / Introduction to OAuth2 / Description of OAuth2 gem from Intridea

我要连接的服务器允许密码授予。它是由第 3 方部署的,所以我认为一切正常。在手册页上,他们定义了如下授权示例:

curl -X POST -d
'grant_type=password&username=USER_EMAIL&password=YOUR_PASSWORD&client_id=CLIENT_ID&client_secret=CLIENT_SECRET'
'https://auth.example.com/oauth2/token'

我拥有上面提到的所有数据。顺便说一句,client_id 和 client_secret 是包含在文档中的通用值。服务器使用 Doorkeeper gem 来实现 OAuth2。

要从服务器检索 access_token,我只需将 Doorkeeper 的 wiki 代码建议放入我的一个控制器中。 Testing ROPC for Doorkeeper

我在 Rails API 应用程序中的代码使用来自 Intridea 的 OAuth2 gem

 def test
    client = OAuth2::Client.new(CLIENT_ID, CLIENT_SECRET,
     site: 'https://auth.example.com/oauth2/token')

    access_token = client.password.get_token(username, password)
    Rails.logger.info access_token.token
  end

访问 localhost/test 后我得到的是 Completed 500 Internal Server Error with OAuth2::Error 说我要查找的页面不存在。

当尝试从命令行使用 curl 和相应的数据时,我收到:

WWW-Authenticate: Bearer realm="Doorkeeper", error="invalid_grant", error_description="The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client."

请告知这些设置中可能导致问题的原因。

【问题讨论】:

  • 那么 CLIENT_ID 和 CLIENT_SECRET 是你的环境变量吗?你在哪里设置环境变量?该网站是错误的。如果你想在开发中测试这个站点应该是site: 'https://127.0.0.1:3000' 3000 如果你的服务器使用端口 3000。如果你使用端口 8080,你还需要有client.auth_code.authorize_url(:redirect_uri => 'http://127.0.0.1:8080/oauth2/callback'。那么你是按照页面上的说明操作还是我只是完全错了吗?我从未使用过这个,但我配置了 Devise 和 Omniauth-Facebook,它们非常相似 github.com/intridea/oauth2
  • 我的代码中的 CLIENT_ID 和 CLIENT_SECRET 被替换为实际数据,我只是不想在 SO 上透露它。我想连接的服务器不是我开发的,我只有应该允许验证然后使用他们的 api 的数据。据我所知,设置回调在这里并不适用,因为它是通过密码授权进行身份验证的。
  • 你说得对!
  • 看了很多讨论,有人建议不要传client_id和client_secret,刷新令牌需要的参数是grant_typerefresh_tokenstackoverflow.com/questions/24548977/…stackoverflow.com/questions/39689168/…
  • 感谢您的评论。请考虑到我想获得 access_token 而不是 refresh_token。您的第一个链接说我们不应该在网络浏览器应用程序上使用 client_id / client_secret,我的是在服务器端。没错,现在 client_id / client_secret 可能是不必要的开销。我也看到了这种建议,在我上面的实现中,我使用了 Intridea oauth2 gem,它强制在构造函数中使用这些数据。 #initialize

标签: ruby-on-rails oauth oauth-2.0


【解决方案1】:

我似乎忽略了一件重要的事情,我们应该明确声明与site 地址相关的token_url,而不是将site 参数视为整个路径。

所以为了请求access_token,我的方法应该是这样的:

def test
  client = OAuth2::Client.new(client_id,
                                client_secret,
                                token_url: "/oauth2/token",
                                site: "https://www.example.com/" )

  access_token = client.password.get_token(username, password)
  Rails.logger.info access_token.token
end

Here你可以找到和我类似的问题。

如果有人想使用简单的 http 方法获取带有密码凭据的访问令牌,这里是如何处理这个事情的示例:

def test
  param = {
          :client_id => client_id,
          :client_secret => client_secret,
          :grant_type => 'password',
          :username => username,
          :password => password
        }

  uri = URI.parse(service_url)
  http = Net::HTTP.new(uri.host, uri.port)
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  http.use_ssl = true
  request = Net::HTTP::Post.new(uri.request_uri)
  request.body = param.to_query
  response = http.request(request)

  Rails.logger.info response.body()
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-06
    • 2015-08-23
    • 2017-10-08
    • 1970-01-01
    • 2013-11-23
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    相关资源
    最近更新 更多