heroku adddon rails how to call endpoint of authentificatation - ruby-on-rails

When a heroku creates resources:
a) Make a call to the endpoint of authentication:
POST https://app.starving.cloud.io/v1/profile/users/email/{email}/sign-in
with the body
(Content-Type: application / json)
{
"password": "{password}"
}
The endpoint returns the token as json:
{
"token": "{token}"
}
Please help me. how to create this is? Or what i should to read about it. Thanks very much.

If this is an API you need to consume (hit, etc), you can use an HTTP Client library like typhoeus to write code that does the POST request and allows you to read the token from the response's body:
email = 'foo#example.com'
password = 'password' # Never use this password!
response = Typhoeus.post("https://app.starving.cloud.io/v1/profile/users/email/#{email}/sign-in",
headers: { 'Content-Type'=> 'application/json' },
body: { password: password }.to_json)
token = JSON.parse(response.body)['token']
Please read the gem's documentation to build the best version of this code, but this should give you an idea and a starting point.

Related

Send body with type x-www-form-urlencoded, in Active resource

Using Active Resource I have to send the authentication with the type x-www-form-urlencoded, however it is sending it with the json format:
In my model base
self.site = 'http://url.ngrok.io/api'
En rails console
login = Namespace::Login
login.create username: "username", password: "password"
Response
ActiveResource::UnauthorizedAccess: Failed. Response code = 401
In the request continue sending in json format
{"username": "username", "password": "password"}"
It should be sent this way
username=username&password=password
Guide me from this tutorial to make a post http://tutorials.jumpstartlab.com/topics/web_services/active_resource.html
Thank you very much for your help...

devise token auth doesn't return access-token with React

I am moving an application from using devise to devise token auth. I have added the gem, set up everything, etc. My issue lies in the fact that when I make a request from React (using axios) to the backend it returns the user (as it should), but doesn't return the access-token headers. All, I get is:
cache-control: "max-age=0, private, must-revalidate"
content-type:"application/json; charset=utf-8"
I do get the user object from the backend though so I know it is a valid sign in. I also see tokens being added to the database:
UPDATE users SET tokens = '
Here is my call via axios:
export const userLogin = (options) => ((dispatch) => {
return axios.post(`${process.env.DOMAIN}/auth/sign_in`, {email:
options.username, password: options.password})
.then((response) => {
console.log("response is: ", response);
dispatch(setUser(response))
dispatch(loginError('', false))
})
.catch((response) => {
dispatch(loginError('Username or Password is incorrect, please try again',
true))
})
})
I have done quite a bit of research on this and tried reverting to an older version of active_model_serializers for example and this hasn't helped. The console.log above shows quite a bit of info:
config
data
headers
request
status
statusText
The response is a 200 OK.

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.

Rails 4 - Google One Time Code Flow with omniauth-google-oauth2, keep getting "Invalid code"

I have a Rails app in which I want users to be able to sign in / up with Google. I'm using the following gem:
#gemfile
gem 'omniauth-google-oauth2'
I've almost got it to work (I actually received the access token once, not sure why) - but before getting the access_token I constantly get the following error:
"error"=>"invalid_grant", "error_description"=>"Invalid code."
I have checked so that the code is unique for each request and that it isn't nil. The relevant parts of the method where I try to get the access_token after I've received the one time authorisation code looks like this:
def google_authentication
respond_to do |format|
# authorisation code
code = params[:code]
unless code.blank?
client_id = ENV["GOOGLE_CLIENT_ID"]
client_secret = ENV["GOOGLE_CLIENT_SECRET"]
redirect_uri = 'postmessage'
grant_type = 'authorization_code'
load = {client_id: client_id, client_secret: client_secret, redirect_uri: redirect_uri, grant_type: grant_type, code: code}
payload = load.to_json
url = "https://www.googleapis.com/oauth2/v3/token"
response = HTTParty.post(url, :query => load)
json = JSON.parse(response.body)
unless json.nil?
unless json[:error].present?
# TODO: Handle data
format.json { render :json => {:message => "Success"} }
else
# ERROR "Invalid code" always happen
end
end
end
end
end
In Google's developer console I have the following credentials:
Client ID [CLient ID]
Email address [Email]
Client secret [Secret]
Redirect URIs http://127.0.0.1:3000/
JavaScript origins http://127.0.0.1:3000
Would be thankful for any ideas or tips.
Update for completion
This is how I set up omniauth-google-oauth2:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"], ENV["GOOGLE_CLIENT_SECRET"],
{
:scope => "email, profile",
:prompt => "select_account",
:provider_ignores_state => true
}
end
Update 2
As mentioned above I once managed to get the access token once, I managed to reproduce it again. I did it by clicking my sign in button three times.The first time I got:
"error"=>"invalid_grant", "error_description"=>"Invalid code."
The second click resulted in:
"error"=>"invalid_grant", "error_description"=>"Code was already redeemed."
And the third time I successfully got the access_token. I find it really strange that I sometimes get the access_token, but most of the time get:
"error"=>"invalid_grant", "error_description"=>"Invalid code."
And the success / error "rate" isn't 100% consistent. Sometimes it takes more than three clicks. I find it quite strange that it sometimes works and that I sometimes get different error responses without changing anything in my code.
Could it be related to time / expiration date of the code?
Update 3
For additional completion. This is how my Javascript (or CoffeeScript) looks like when the user clicks the Google Sign in button:
$(document).ready ->
$.ajax
url: 'https://apis.google.com/js/client:plus.js?onload=gpAsyncInit'
dataType: 'script'
cache: true
window.gpAsyncInit = ->
$('.googleplus-login').click (e) ->
e.preventDefault()
gapi.auth.authorize {
immediate: false
response_type: 'code'
cookie_policy: 'single_host_origin'
client_id: '[id]'
scope: 'email profile'
}, (response) ->
if response and !response.error
jQuery.ajax
type: 'POST'
url: '/auth/google_oauth2/callback'
dataType: 'json'
data: response
success: (json) ->
# response from server
console.log "JSON: " + json
return
else
# google authentication failed
So ...as it is wrote:
Authorized redirect
URIs One URI per line. Needs to have a protocol,
no URL fragments, and no relative paths. Can't be a public IP Address.
Your setting:
Redirect URIs http://127.0.0.1:3000/
JavaScript origins http://127.0.0.1:3000/
...is wrong.
It should be:
Redirect URIs: http://my.true.domain/users/auth/google/callback
and
provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"], ENV["GOOGLE_CLIENT_SECRET"],
{
:scope => "email, profile",
:name => "google",
...
I hope it help!
I cant help with the ruby part but I may be able to help you figure out what's wrong.
There are in fact 3 codes returned by Google's authentication server. Authorization code, Access token, and refresh token.
Authorization code can only be used once to get the first refresh token.
Access Token used to access data on the apis, expires after an hour.
Refresh Token used to get a new access token when it expires. good until the user removes access.
Authorization code
This is the code that gets returned when the user hits accept to your application.
Example:
Change the client id, secret, and scope in this URI to the ones you are using. then paste it into a browser location bar.
https://accounts.google.com/o/oauth2/auth?client_id={clientid}.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope={scope}&response_type=code
It will prompt you for authentication. If you click except you get another window with a long code in it looking something like this.
That is the Authentication code, its only purpose in life is for you to use it to get an access token and a refresh token. It can only be used once, and its probably short lived though I have never tested how long they are good for.
In the uri above Note: the response type code.
Exchange:
Once you have that authentication code you need to exchange it for an access token and a refresh token. this is a HTTP POST so cant be placed in a browser window.
https://accounts.google.com/o/oauth2/token
code=4/X9lG6uWd8-MMJPElWggHZRzyFKtp.QubAT_P-GEwePvB8fYmgkJzntDnaiAI&client_id={ClientId}.apps.googleusercontent.com&client_secret={ClientSecret}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code
Note: grant_type=authorization_code this tells the server you are sending it an authorization code.
response
{
"access_token" : "ya29.1.AADtN_VSBMC2Ga2lhxsTKjVQ_ROco8VbD6h01aj4PcKHLm6qvHbNtn-_BIzXMw",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/J-3zPA8XR1o_cXebV9sDKn_f5MTqaFhKFxH-3PUPiJ4"
}
You now have an access token that can be used to access the Google APIs, it is short live lasts only 3600 seconds or 1 hour. After that you must use the refresh token to get access again.
Use refreshtoken
https://accounts.google.com/o/oauth2/token
client_id={ClientId}.apps.googleusercontent.com&client_secret={ClientSecret}&refresh_token=1/ffYmfI0sjR54Ft9oupubLzrJhD1hZS5tWQcyAvNECCA&grant_type=refresh_token
response
{
"access_token" : "ya29.1.AADtN_XK16As2ZHlScqOxGtntIlevNcasMSPwGiE3pe5ANZfrmJTcsI3ZtAjv4sDrPDRnQ",
"token_type" : "Bearer",
"expires_in" : 3600
}
Now that you understand all of that
"error"=>"invalid_grant", "error_description"=>"Code was already redeemed."
means that you are sending the authorization code again you can only use it once you should be sending the refresh token again. There is something up with your authentication flow. Again sorry I cant help with the ruby part.
code ripped from Google 3 legged oauth2 flow

Neo4j simple authentication

I can log in using username and password here http://localhost:7474/ by typing server: connect and logging in. I can view data from there by executing queries.
Then I immediately switch to a new tab, or in the same tab, and go to: http://localhost:7474/db/data/, and I get:
{
"errors" : [ {
"message" : "No authorization header supplied.",
"code" : "Neo.ClientError.Security.AuthorizationFailed"
} ]
}
And I cannot connect using py2Neo or any NEO4J libraries either using the same password; they return the exact same error.
What am I doing wrong?
add this to your http-headers request:
Authorization: "Basic xxxx"
xxxx = base64(username:password)
All REST API requests must now include the Authorization header. To quote the REST API Authentication and Authorization page of the neo4j manual:
Requests should include an Authorization header, with a value of Basic
<payload>, where "payload" is a base64 encoded string of
"username:password".
That page contains some examples.
Note: you can also disable authentication -- but you should only do this on your personal machine, for development purposes. You do this by setting to false the dbms.security.auth_enabled property in <neo4j-install-dir>/conf/neo4j-server.properties, and then restarting the server.
[UPDATED]
By the way, since your question mentioned py2neo, you should know that its Graph class supports "authorisation".
The request json should look like: (XXX being the Base64 encoding of the user:password string - the string to encode contains the column):
{
method: "POST",
headers: {
"content-type": "application/json",
"Authorization": "Basic XXX"
},
body: {
statements:[
{
statement: query,
parameters: params
}
]
}
}
This has been tested in Javascript (axios) and in Deno.land (fetch API). ES Javascript contains a built in base64 encoding function: btoa()

Resources