2017-03-31 75 views
0

当我试图接收访问令牌时应该将其包含在来自外部Api的JSON响应中,我遇到了rails和法拉第的问题。JSON请求问题 - rails /法拉第

我想要做的是基于外部API的用户认证。 我假设用户已经有有效的凭据(在这种情况下,电子邮件作为用户名和密码)。

现在,当他连接到我的Api,我发送JSON请求到外部Api以验证此用户是否有效并等待访问令牌。

一旦访问令牌是在响应中发送,用户身份验证是成功的,我有机会到其他端点

这是我的控制器

module Api 
    class AuthenticationController < ApplicationController 
    def create 
     client = XXX::AuthClient.new 

     response = client.authenticate(
     email: params[:email], 
     password: params[:password] 
    ) 

     api_client = XXX::Client.new(response[:access_token]) 

     if response[:access_token] 
     api_user = api_client.get_user() 

     if api_user["id"] 
      db_user = User.create(xxx_id: api_user["id"], xxx_access_token: response[:access_token]) 
     end 
     end 

     render json: { access_token: db_user.access_token } 
    end 
    end 
end 

这是我AuthClient服务

class AuthClient 
    def initialize 
     @http_client = Faraday.new('https://auth.xxx.com/') 
    end 

    def authenticate(email:, password:) 
     headers = { 
     'Content-Type': 'application/json' 
     }.to_json 

     body = { 
     grant_type: "password", 
     username: email, 
     password: password, 
     client_id: "particularclientid", 
     client_secret: "particularclientsecret" 
     }.to_json 

     api_response = http_client.post("/oauth2/token", body) 
     response = JSON.parse(api_response.body) 

     if response["access_token"] 
     { access_token: access_token } 
     else 
     { error: "autentication error" } 
     end 

    end 

    private 

    attr_reader :http_client 
    end 
end 

我所知道的是,以下格式的卷曲是正确的,我可以看到用户的访问令牌,刷新令牌等。

curl -X POST -H "Content-Type: application/json" -d '{ 
"grant_type": "password", 
"username": "[email protected]", 
"password": "examplepassword", 
"client_id": "particularclientid", 
"client_secret": "particularclientsecret" 
}' "https://auth.xxx.com/oauth2/token" 

但是当我跑我的卷曲

curl -X POST -d '[email protected]&password=examplepassword' "http://localhost:3000/api/auth" 

我看到,我的要求是不正确的。但我不知道问题在哪里,因为标题和正文被格式化为JSON(我已输入puts headers,puts bodyputs response来验证)。

Started POST "/api/auth" for 127.0.0.1 at 2017-03-31 16:42:26 +0200 
Processing by Api::AuthenticationController#create as */* 
    Parameters: {"email"=>"test [email protected]", "password"=>"[FILTERED]"} 
{"Content-Type":"application/json"} 
{"grant_type":"password","username":"test [email protected]","password":"examplepassword","client_id":"particularclientid","client_secret":"particularclientsecret"} 
{"error"=>"invalid_request", "error_description"=>"The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed."} 
Completed 500 Internal Server Error in 610ms (ActiveRecord: 0.0ms) 


NoMethodError (undefined method `access_token' for nil:NilClass): 

app/controllers/api/authentication_controller.rb:21:in `create' 

是我的要求不正确或问题的其他地方存在? 我没有经验的开发人员。只是试图学习足够的初级RoR。我试图找到堆栈和不同网站上的解决方案,但我被困住了。即使法拉第文档也没有多大帮助

回答

0

好的。 我刚刚发现一个问题,当我开始阅读我的文章了。

我的控制器无法识别用户名字段中的加号,并且它被替换为空格。 在我卷曲我送curl -X POST -d '[email protected]&... 而在控制器我看到"username":"test [email protected]"

但这并没有解决我的问题。

0

当URI被转义时,+被用作空白的替换。因此,当您的控制器不转义URI时,+会变回空格。如果您想发送空间,请改用%2B

对于您的第一个问题,错误消息指示当您尝试执行db_user.access_token时,db_user为零。因此,要么response[:access_token]为零,api_user["id"]为零,或者User.create失败。

您需要进行一些调试以找出问题所在。

+0

'我,[2017-04-01T00:50:34.680829#23770]信息 - :post https:// auth.xxx.com/oauth2/token' 'D,[2017-04-01T00:50 :请求:User-Agent:“Faraday v0.11.0”' 'D,[2017-04-01T00:50:34.681299#23770] DEBUG - request:{“grant_type”:“password “,”username“:”test [email protected]“,”password“:”examplepassword“,”client_id“:”particularclientid“,”client_secret“:”particularclientsecret“} – Hubert

+0

嗯,它看起来像我的标题不甚至发送给客户。 – Hubert

0

我已经调试我的控制器和我看到,当我在控制台

response = client.authenticate(
    email: params[:email], 
    password: params[:password] 
) 

puts response 

打印响应我收到{:error=>"autentication error"}。 那么就意味着我收到一个错误,而不是访问令牌,当我把我的请求,客户端的API

if response["access_token"] 
    { access_token: access_token } 
else 
    { error: "autentication error" } 
end 

因此,这可能是错误的在这种情况下,唯一的事情是我的请求,这是格式不正确(应为JSON )或者在标题或正文中缺少某些内容。

def authenticate(email:, password:) 
    headers = { 
    'Content-Type': 'application/json' 
    }.to_json 

    body = { 
    grant_type: GRANT_TYPE, 
    username: email, 
    password: password, 
    client_id: CLIENT_ID, 
    client_secret: CLIENT_SECRET 
    }.to_json 

    api_response = http_client.post("/oauth2/token", body) 
    response = JSON.parse(api_response.body) 

是否可以通过某种方式验证此处发送的内容? api_response = http_client.post("/oauth2/token", body)我已经尝试在该代码下面插入提示,并且在控制台中看不到任何内容。

+0

请注意,所有正文值都是正确的,所以授予类型,用户名,密码,客户端ID和客户端密码都可以。是否有可能我的标题或正文不是以JSON格式发送的?或者,即我的标题未被发送,因此我的请求每次都会失败。 – Hubert