OAuth authorization in ruby on rails - ruby-on-rails

I'm trying to authorize in OAuth. I have to open url in browser. That url redirects me to my application sending auth code.
When I open link in browser everything works fine and I receive the code. When I'm sending get (or post) request from code to that link nothing happens. How can I solve this problem.
Logic: I receive response from OAuth in controller and then send it to service.
Method in controller:
def auth_code
MyService.code(params)
render json: params
end
Method in service:
def self.code(params)
##code = params['code']
end
Sending Request from code (Using Httparty [I tried both post and get] ):
code_request = HTTParty.get(code_url)
Sending Request from code:
code_request = Net::HTTP.get(URI(code_url))
P.S. I don't wanna use OAuth gems

Related

Rails API 422 Unprocessable Entity: No verification key available, heroku

I created a Rails API with a JWT authentication system and deployed it to Heroku. When I request the endpoints locally, all seems to be working fine but when I make requests to the live endpoints (i.e the Heroku deployed app) I get a: 422 Unprocessable Entity server error and the response body looks like this:
{
"message": "No verification key available"
}
The class responsible for encoding and decoding the auth token is defined as follows:
class JsonWebToken
# secret to encode and decode token
HMAC_SECRET = Rails.application.secrets.secret_key_base
def self.encode(payload, exp = 24.hours.from_now)
# set expiry to 24 hours from the creation time.
payload[:exp] = exp.to_i
# sign token with application secret
JWT.encode(payload, HMAC_SECRET)
end
def self.decode(token)
# get payload, first index in decoded Array
body = JWT.decode(token, HMAC_SECRET)[0]
HashWithIndifferentAccess.new body
# rescue from all decode errors
rescue JWT::DecodeError => e
# raise custom error to be handled by custom handler
raise ExceptionHandler::InvalidToken, e.message
end
end
I have an endpoint /signup where I can make a POST request to register a new user and POST /todos which is accessible and available only to registered users. Making a registration request works perfectly fine, but when I try to make the POST request to the /todos endpoint it raises an error.
The association between user and suit is 1:m respectively.
Please if you have any idea on how I can fix this, I'll be very grateful, thanks : ).
I finally figured a way out by altering the Rails.application.secrets.secret_key_base to Rails.application.secret_key_base. For a more detailed review on this please check out this link. Hopefully, this will help someone facing a similar issue.
This was also my problem. After checking out my json_web_token.rb file, I figured out that I had written the following line:
HMAC_SECRET = Rails.application.secrets.secret_key_base
There is an extra secrets reference, which is causing the problem. It should be:
HMAC_SECRET = Rails.application.secret_key_base
But as far as I'm concerned, you managed to figure it out yourself!

Error in Access-Control-Allow-Origin when Angular request to Rails

I'm using Angular 2 to make an API(rails) request. When I make the http request through angular, I get the following error:
XMLHttpRequest cannot load https://api-url. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 404.
However, if I try to make a request through Postman or the browser itself, I don't get any error. The data is displayed normally
angular code:
makeRequest() {
let user = {"user": "user", "password": "password"};
let headers: Headers = new Headers();
headers.append('Authorization', 'Basic ' + btoa(user.user + ':'+user.password));
headers.append('Content-Type', 'application/vn.api+json')
let this.http.get(api-url, {headers: headers}).map(res => res.json()).subscribe(data => {
this.data = data;
})
}
In my rails server i using the gem 'jsonapi-resources'to open AP. In my api controller, i have this code to authenticate and set headers to requests:
module Api
class ApiController < JSONAPI::ResourceController
prepend_before_action :set_headers, :authenticate
def context
{ current_station: #user }
end
private
def authenticate
authenticate_or_request_with_http_basic do |token, _|
#user = User.where(api_key: token).first
end
end
def set_headers
response.headers["Access-Control-Allow-Origin"] = "*"
end
end
end
When i make request in browser or using postaman, the header appears normally, but in Angular i have the error.
This is because of CORS. Long story short, browsers forbid by default one domain (http://localhost:4200) to make AJAX requests to another one (http://api-url). It works in "postman" because this is an extension and then, the CORS does not apply. If you want to fix this issue, you have to configure your server to returns certain header saying to the client that it allows the CORS connection.
In fact, when a website is trying to make an AJAX request to another domain, it first send an OPTION request to ask what are the domain allowed. This list is returned by the server via the header Access-Control-Allow-Origin. For example, it could contain a star ("*") to indicate that anyone could make AJAX call to this server. If this header allows your client to make AJAX call, your actual request will be executed, otherwise, you'll get an error (probably the one you currently get)

Rails - Slack API OAuth Access - invalid_client_id

I'm building Slack integration for my Ruby on Rails application and I'm trying to get an access_token from the Slack API for my Slack App when a user clicks the Add to Slack button.
From Postman, I can successfully post the following:
https://slack.com/api/oauth.access?client_id=idgoes.here&client_secret=secretgoeshere&code=12345&pretty=1
However, within Rails I always get a response with invalid_client_id, regardless of the way I call the API. I have checked my ID is correct (a lot) and tried regenerating it, but I don't think that is the issue due to the postman success.
Within my get_oauth_access_token method I have tried the following implementations:
1.
rc = JSON.parse(HTTP.post('https://slack.com/api/oauth.access',
params: {
client_id: 'idgoes.here',
client_secret: 'secretgoeshere',
code: '12345'
}))
2.
response = Excon.post('https://slack.com/api/oauth.access',
headers: { 'Content-Type' => 'application/json; charset=utf-8' },
user: client_id, password: client_secret,
body: oauth_request_body.to_json)
Any implementation I try always ends up getting a invalid_client_id response.
I'm aware it may be something to do with environment config, but I'm not sure what would be helpful to debug, so please let me know what other information I can share. I'm running on localhost.
Update:
I just found out that many (maybe all) of the Slack APIs do not accept a JSON format body (which seems crazy seeing as they send a response in JSON.
Make sure to use x-www-form-urlencoded format body on your request or it will not work properly.
"Content-Type" => "application/x-www-form-urlencoded"
I use oauth2 gem to authorize. So I was able to get this to work by reading the slack documentation and using oauth2 in my controller:
class OauthController < ApplicationController
def authorize
options = {
site: 'https://slack.com/oauth/authorize'
}
client ||= OAuth2::Client.new(
'client-id',
'client-secret',
options
)
params = {
scope: 'incoming-webhook, commands',
redirect_uri: 'https://localhost:3000/oauth/callback'
}
redirect_to client.auth_code.authorize_url(params)
end
def authorize_callback
puts params["code"]
redirect_to root_url
end
end
Routes file:
get '/authorize', to: 'oauth#authorize'
get '/oauth/callback', to: 'oauth#authorize_callback'
Don't forget to set your callback url at Oauth settings on api.slack.com, I used localhost for testing purposes as you can see.

Issues sending a POST via Net::HTTP to a Battle.Net Community API End-Point (OAuth 2)

Versions:
Ruby 2.2.4
Rails 4.2
Omniauth-oauth2 1.3.1
Omniauth-bnet 1.1.0
Issue:
Trying to complete the authorization and token request process to Blizzard's Battle Net Community API. While I can get the authorization_code returned, when I attempt to construct a POST back to the token endpoint it keeps telling me that its an invalid request/internal server error or just returns back the following object: <Net::HTTPFound 302 Found readbody=true> which has a blank string for a response body. Details for how Blizzard recommends handling the OAuth 2 process are located here: Battle.net OAuth 2 Guide. The omniauth-bnet gem is the one Blizzard suggested but doesn't seem to handle the entire OAuth authorization and token process but I'll freely admit I'm brand new when it comes to anything OAuth related so I could be wrong.
Any help you all can provide would be very welcome!
Controller Code:
def index
client_id = ENV[BNET_CLIENT_ID]
client_secret = ENV[BNECT_CLIENT_SECRET]
uri = URI('https://us.battle.net/auth/token?
redirect_uri=https%3A%2F%2f127%2f0%2f0%2f1%3A3001%2Fauth%2Fbnet%2Fcallback
&grant_type=authorization_code
&code=' + params["code"])
req = Net::HTTP::Post.new(uri)
req.basic_auth(client_id, client_secret)
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') {|http| http.request(req)}
#bnet_response = res.body
end
Process:
Click link on index.html page which triggers the authorization process to start by sending a GET request to https://us.battle.net/oauth/authorize?client_id=&client_secret=&redirect_uri=&response_type=code
BNet API accepts the request and redirects user to Battle.Net Login screen
User authorizes app and is redirected (via redirect_uri) back to the index page with query parameters for the authorization_code
My app SHOULD make a POST request using the controller code above and the response should contain the actual access token.
This is just some hastily cobbled together code while I'm trying to get this working. I'll clean it up once I get over this little speed bump. I wouldn't hardcode the URI and such normally, just getting frustrated with things.
Things I've tried:
Using Rest-Client : There's a callback redirect that it can't handle apparently
Testing Postman : When using their OAuth 2 Authorization it works just fine, also works fine if I use Postman to get the authorization code (GET) and token (POST), so I'm assuming things work on the Blizz side and my code just sucks.
config/routes.rb
Rails.application.routes.draw do
root to: 'pages#index'
get '/auth/:provider/callback', to: 'pages#index'
end
I'm not familiar with the Battle.net API, however reading your process it seems you are getting an authorization code back from the redirect in the form of a query parameter (accessed by params[:code]) correct?
You also mention that this works using Postman indicating the flaw must be somewhere in the code.
I would suggest using the following snippet and let me know if it works. I would encourage using puts url after url = ... code to ensure the URI looks exactly as you want it (and has the correct code, client id, secret, redirect_uri).
require 'uri'
require 'net/http'
# Remember to change the redirect uri to match yours
redirect_uri = 'https://my-domain-name.com/auth/bnet/callback'
# Double check the environment variable names for BNET ID / Secret
url = URI("https://us.battle.net/oauth/token?redirect_uri=#{redirect_uri}&code=#{params[:code]}" \
"&grant_type=authorization_code&scope=wow.profile&client_id=#{ENV['BNET_CLIENT_ID']}" \
"&client_secret=#{ENV['BNET_CLIENT_SECRET']}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_body
Ensure your domain is accessible over https as this seems to be required.

Google Calendar Data API Integration

We're using Oauth to grab Calendar event data. I have successfully authorized the token and exchange it for an access token. When I perform a get request to the API endpoint I get a page that says "Moved Temporarily" with a link to something like https://www.google.com/calendar/feeds/default?gsessionid=xxxxxxxxxxxx
I'd like to interpret the response, whether it's json or xml but I can't get beyond the redirect it's throwing out. Any idea how to follow this?
Here's my call to the feed:
access_token = current_user.google.client
response = access_token.get(ConsumerToken::GOOGLE_URL).body
Yep, just dealt with this myself. It says "Moved Temporarily" because it's a redirect, which the oauth gem unfortunately doesn't follow automatically. You can do something like this:
calendar_response = client.get "http://www.google.com/calendar/feeds/default"
if calendar_response.kind_of? Net::HTTPFound # a.k.a. 302 redirect
calendar_response = client.get(calendar_response['location'])
end
This might be worthy of a patch to oauth...

Resources