How to fetch account email using Outlook REST API? - ruby-on-rails

There is outdated tutorial in Ruby - https://dev.outlook.com/restapi/tutorial/ruby
( search for get_email_from_id_token in the .\o365-tutorial\app\helpers\auth_helper.rb file )
First of all - I tried it and it does not work.
I tried to make request for profile:
conn = Faraday.new(url: 'https://outlook.office.com') do |faraday|
# Outputs to the console
faraday.response :logger
# Uses the default Net::HTTP adapter
faraday.adapter Faraday.default_adapter
end
response = conn.get do |request|
# Get events from the calendar
request.url '/api/v2.0/Me'
request.headers['Authorization'] = "Bearer #{token}"
request.headers['Accept'] = 'application/json'
end
JSON.parse(response.body)
It returns user profile data, but email field is blank. It is strange.
Did anyone face/solve this problem ?

Related

Rails: cannot find '*_path'

I'm trying to get a html button to redirect to my Azure login page from the homepage.
If I put in my browser localhost/3000/authentication/login it goes to the Azure web app.
This is what I'm trying to achieve with this:
<%= button_to 'Login', authentication_login_path, method: :get %>
My routes file is:
Rails.application.routes.draw do
root 'application#home'
get 'application/home'
get 'authentication/login', to: 'authentication#index'
resources :authentication
end
The Application and Home controllers just have blank functions at the moment.
I've tried rake | grep authentication and it contains the correct path:
authentication_login GET /authentication/login(.:format) authentication#index
Therefore, I'm not sure what doing authentication_login_path is not recognized in my home.html.erg file.
This is the Authentication_Controller. I'm trying to execute the index method as this will begin the authentication process.
require 'oauth2'
class AuthenticationController < ApplicationController
# You need to configure a tenant at Azure Active Directory(AAD) to register web app and web service app
# You will need two entries for these app at the AAD portal
# You will put clientid and clientsecret for your web app here
# ResourceId is the webservice that you registered
# RedirectUri is registered for your web app
CLIENT_ID = '56938f79-a23e-4f3f-a033-d23546d9056f'
CLIENT_SECRET = '5j8Hv8U1x_l-t047OZq9~LmK~kMdobV3rm'
AUTHORITY = 'https://login.windows.net/'
AUTHORIZE_URL = "https://beautytruth.b2clogin.com/beautytruth.onmicrosoft.com/B2C_1_btSignInSignOut/oauth2/v2.0/authorize"
TOKEN_URL = "https://beautytruth.b2clogin.com/beautytruth.onmicrosoft.com/B2C_1_btSignInSignOut/oauth2/v2.0/token"
RESOURCE_ID = '/subscriptions/eb589fa5-ed57-4e10-81c9-32e4284af10c/resourceGroups/btAdvertisingNetwork' #ResourceId or ResourceURI that you registered at Azure Active Directory
REDIRECT_URI = 'http://localhost:3000/welcome/callback'
def index
update_token
if session['access_token']
puts "Auth has been checked"
# show main page and use token
redirect_to
else
# start authorization
client = get_client
a = client.auth_code.authorize_url(:client_id => CLIENT_ID, :resource => RESOURCE_ID, :redirect_uri => REDIRECT_URI)
redirect_to(a)
end
end
def callback
begin
#code = params[:code]
client = get_client
# post token to mobile service api
#token = client.auth_code.get_token(CGI.escape(#code), :redirect_uri => REDIRECT_URI)
# id_token token.params["id_token"]
#multi resource token token.params["resource"]
token = client.auth_code.get_token(#code, :redirect_uri => REDIRECT_URI, )
session['access_token'] = token.token
session['refresh_token'] = token.refresh_token
session['expire_at'] = token.expire_at
session['instance_url'] = token.params['instance_url']
redirect '/'
rescue => exception
output = '<html><body><p>'
output += "Exception: #{exception.message}<br/>"+exception.backtrace.join('<br/>')
output += '</p></body></html>'
end
end
def update_token
puts "update token inside"
token = session['access_token']
refresh_token = session['refresh_token']
expire_at = session['expire_at']
#access_token = OAuth2::AccessToken.from_hash(get_client, { :access_token => token, :refresh_token => refresh_token, :expire_at => expire_at, :header_format => 'Bearer %s' } )
if #access_token.expired?
puts "refresh token"
#access_token = #access_token.refresh!
session['access_token'] = #access_token.token
session['refresh_token'] = #access_token.refresh_token
session['expire_at'] = #access_token.expire_at
session['instance_url'] = #access_token.params['instance_url']
end
end
# send post request to webservice to send token and create a post request
def use_token
# we got the token and now it will posted to the web service in the header
# you can specify additional headers as well
# token is included by default
update_token
conn = Faraday.new(:url => 'https://btadvertisingplatform.azurewebsites.net/') do |faraday|
faraday.request :url_encoded # form-encode POST params
faraday.response :logger # log requests to STDOUT
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
end
response = conn.get do |req|
req.url '/api/WorkItem'
req.headers['Content-Type'] = 'application/json'
req.headers['Authorization'] = 'Bearer '+#access_token.token
end
#out = response.body
end
def get_client
client = OAuth2::Client.new(CLIENT_ID, CLIENT_SECRET, :site => AUTHORITY, :authorize_url => AUTHORIZE_URL, :token_url => TOKEN_URL )
client
end
end
As you already have resource :authentication you can use the following.
<%= button_to 'Login', authentication_index_path, method: :get %>
You don't need an additional route. You can remove the following route
get 'authentication/login', to: 'authentication#index'

HTTP request works in Postman but not in Ruby (502 error)

I'm quite new to Ruby but have to debug a Ruby code that I did not write.
In the Ruby code, an HTTP request is made. After a bit of logging, I found out that the response object shows a 502 error. When I try the exact same request in Postman, I get the expected successful response :
I even tried to literally copy/past Postman's generated Ruby snippet, and it still gives me a 502 error when fired from the Ruby code.
Here is the part responsible for the query (the request method, post part) :
class PatentApi
# Patent analysis API wrapper
require 'uri'
require 'net/http'
DEFAULT_ENDPOINT = configatron.patent_api.endpoint.freeze
# POST /api/v1/graph
def post_complete_patent_graph(data)
response = post('graph', data.to_json)
response
end
# Send as POST request
def post(path, options = {})
request(:post, path, options)
end
# Build the request and return response
def request(method, path, options)
url = URI.parse(DEFAULT_ENDPOINT + path)
Rails.logger.info (url.inspect) # The url looks ok in the logs !
params = options # After logging, this value is ok
case method
when :get
url.query = URI.encode_www_form(params)
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url.request_uri)
request["Accept"] = 'application/json'
request["Content-Type"] = 'application/json'
response = http.request(request)
return response
when :post
request = Net::HTTP::Post.new(url, 'Content-Type' => 'application/json')
request.body = params
response = Net::HTTP.start(url.host, url.port, :read_timeout => 320) do |http|
http.request(request)
end
Rails.logger.info 'RESPONSE'
Rails.logger.info (response.code) # 502 ! :(
Rails.logger.info (response.message)
Rails.logger.info 'END RESPONSE'
return response
end
end
end
Would you try to include the Content-Type header like
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/json"

How to check if HTTP request status is 200 OK in Rails

I want to do something like this post but in the actual Rails app, not the testing.
I want to see if the HTTP request was successful or not. If it's not successful (aka 404 Not Found), then I want to render a different HTML. But I can't figure out the syntax to compare.
Currently, I have:
def videos
# get current_user's wistia_project_id & authorization token
#current_user = current_user
project_id = #current_user.wistia_project_id
auth_token = "blah"
request = "https://api.wistia.com/v1/projects/#{project_id}.json?api_password=#{auth_token}"
#response = HTTP.get(request).body
puts HTTP.get(request).status
# handle errors: not 200 OK
if !HTTP.get(request).status:
render "/errors.html.erb/"
end
# get embed code for each video using the hashed_id, put in list
#video_iframe_urls = JSON.parse(#response)['medias'].map do |p|
"https://fast.wistia.com/embed/iframe/#{p["hashed_id"]}?version=v1&controlsVisibleOnLoad=true&playerColor=aae3d8"
end
end
require 'net/http'
uri = URI("https://api.wistia.com/v1/projects/#{project_id}.json?api_password=#{auth_token}")
res = Net::HTTP.get_response(uri)
# Status
puts res.code # => '200'
puts res.message # => 'OK'
puts res.class.name # => 'HTTPOK'
# Body
puts res.body if res.response_body_permitted?

Ruby on Rails 4: How to authenticate to Azure AD from Rails Application?

I am developing a Rails 4 web application and i am planning to authenticate a user from my Windows Azure AD.
For that i have subscribed to Windows Azure and created Active Directory. I then created an application inside AD to get Client and Secret ID to access API exposed by windows Azure from my Rails web application.
For this i am planning to use Devise gem . Is this the right solution or is there any other libraries available to achieve this.
Any help is appreciated.
Not sure if you're still looking for anything, but this Gist has the requisite request code using the OAuth2 gem. If you were ultimately able to get things working with another means (Devise, etc.), I'd also be interested to know what you did.
Here's the code from the Gist as packaged into a controller by omercs:
require 'oauth2'
class WelcomeController < ApplicationController
# You need to configure a tenant at Azure Active Directory(AAD) to register web app and web service app
# You will need two entries for these app at the AAD portal
# You will put clientid and clientsecret for your web app here
# ResourceId is the webservice that you registered
# RedirectUri is registered for your web app
CLIENT_ID = 'b6a42...'
CLIENT_SECRET = 'TSbx..'
AUTHORITY = 'https://login.windows.net/'
AUTHORIZE_URL = "/yourtenant.onmicrosoft.com/oauth2/authorize"
TOKEN_URL = "/yourtenant.onmicrosoft.com/oauth2/token"
RESOURCE_ID = 'https://yourtenant.onmicrosoft.com/AllHandsTry' #ResourceId or ResourceURI that you registered at Azure Active Directory
REDIRECT_URI = 'http://localhost:3000/welcome/callback'
def index
update_token
if session['access_token']
# show main page and use token
redirect_to welcome_use_token_path
else
# start authorization
client = get_client
a = client.auth_code.authorize_url(:client_id => CLIENT_ID, :resource => RESOURCE_ID, :redirect_uri => REDIRECT_URI)
redirect_to(a)
end
end
def callback
begin
#code = params[:code]
client = get_client
# post token to mobile service api
#token = client.auth_code.get_token(CGI.escape(#code), :redirect_uri => REDIRECT_URI)
# id_token token.params["id_token"]
#multi resource token token.params["resource"]
token = client.auth_code.get_token(#code, :redirect_uri => REDIRECT_URI, )
session['access_token'] = token.token
session['refresh_token'] = token.refresh_token
session['expire_at'] = token.expire_at
session['instance_url'] = token.params['instance_url']
redirect '/'
rescue => exception
output = '<html><body><p>'
output += "Exception: #{exception.message}<br/>"+exception.backtrace.join('<br/>')
output += '</p></body></html>'
end
end
def update_token
puts "update token inside"
token = session['access_token']
refresh_token = session['refresh_token']
expire_at = session['expire_at']
#access_token = OAuth2::AccessToken.from_hash(get_client, { :access_token => token, :refresh_token => refresh_token, :expire_at => expire_at, :header_format => 'Bearer %s' } )
if #access_token.expired?
puts "refresh token"
#access_token = #access_token.refresh!;
session['access_token'] = #access_token.token
session['refresh_token'] = #access_token.refresh_token
session['expire_at'] = #access_token.expire_at
session['instance_url'] = #access_token.params['instance_url']
end
end
# send post request to webservice to send token and create a post request
def use_token
# we got the token and now it will posted to the web service in the header
# you can specify additional headers as well
# token is included by default
update_token
conn = Faraday.new(:url => 'https://yoursite.azurewebsites.net/') do |faraday|
faraday.request :url_encoded # form-encode POST params
faraday.response :logger # log requests to STDOUT
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
end
response = conn.get do |req|
req.url '/api/WorkItem'
req.headers['Content-Type'] = 'application/json'
req.headers['Authorization'] = 'Bearer '+#access_token.token
end
#out = response.body
end
def get_client
client = OAuth2::Client.new(CLIENT_ID, CLIENT_SECRET, :site => AUTHORITY, :authorize_url => AUTHORIZE_URL, :token_url => TOKEN_URL )
client
end
end

Getting 401 response when connecting to Google via OAuth2, Ruby

I'm trying to access all the contacts from Google Contacts for invite purposes from my site.
So I'm using OAuth2 but when I first request I get a 401 error with access_token. :(
Keep in mind I'm working local!!
Here's my code.
def authenticate
# initiate authentication w/ gmail
# create url with url-encoded params to initiate connection with contacts api
# next - The URL of the page that Google should redirect the user to after authentication.
# scope - Indicates that the application is requesting a token to access contacts feeds.
# secure - Indicates whether the client is requesting a secure token.
# session - Indicates whether the token returned can be exchanged for a multi-use (session) token.
next_param = "http://localhost:3000/import/authorise"
scope_param = "https://www.google.com/m8/feeds/"
#session_param = "1"
state="profile"
client_id="535946964206.apps.googleusercontent.com"
root_url = "https://accounts.google.com/o/oauth2/auth"
response_type="token"
#TO FIND MORE ABOUT THESE PARAMETERS AND THERE MEANING SEE GOOGLE API DOCS.
query_string = "?scope=#{scope_param}&state=#{state}&redirect_uri=#{next_param}&response_type=#{response_type}&client_id=#{client_id}"
#render :text=> root_url + query_string and return
# redirect_to "https://accounts.google.com/o/oauth2/auth?
#scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&
#state=%2Fprofile&
#redirect_uri=http://localhost:3000/import/authorise&
#response_type=token&
#client_id=535946964206.apps.googleusercontent.com
#"
redirect_to root_url + query_string
end
this is for authentication now i get response with access token
http://localhost:3000/import/authorise#state=profile&access_token=ya29.1.AADtN_WPohnlKYBH16kFrqEcYUTZ558WDICpqCqiz1mwBKESFr5PTiJFA5vsyoc&token_type=Bearer&expires_in=3600
Now next it will redirected to here,this is where i get above error
# YOU WILL BE REDIRECTED TO THIS ACTION AFTER COMPLETION OF AUTHENTICATION PROCESS WITH TEMPORARY SINGLE USE AUTH TOKEN.
def authorise
#FIRST SINGEL USE TOKEN WILL BE RECEIVED HERE..
token = params[:token]
#PREPAIRING FOR SECOND REQUEST WITH AUTH TOKEN IN HEADER.. WHICH WILL BE EXCHANED FOR PERMANENT AUTH TOKEN.
uri = URI.parse("https://www.google.com")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
path = '/accounts/AuthSubSessionToken'
headers = {'Authorization' => "AuthSub token=#{token}"}
render :text=> http.get(path, headers) and return
#GET REQUEST ON URI WITH SPECIFIED PATH...
resp, data = http.get(path, headers)
#ender :text=> data and return
resp.code="200"
#SPLIT OUT TOKEN FROM RESPONSE DATA.
if resp.code == "200"
token = ''
data.split.each do |str|
if not(str =~ /Token=/).nil?
token = str.gsub(/Token=/, '')
end
end
return redirect_to(:action => 'import', :token => token)
else
redirect_to root_url , :notice => "fail"
end
end
here at above function when it requests resp, data = http.get(path, headers) the responce resp.code is 401 . i dont know what's wrong i'm following https://gist.github.com/miketucker/852849 example which uses AuthSub which is now not in use so i'm adapting oauth2 .
i already have made app at clode console and given return url and other info.
any help or point me to other working example,thanks you!!!
thank you.

Resources