Some informations about LinkedIn for you:
LinkedIn no longer supports the JavaScript SDK. The recommended approach is to use OAuth 2.0 and LinkedIn's Auth APIs.
And:
LinkedIn does not support TLS 1.0. Support for TLS 1.1 has been marked for deprecation starting 02/01/2020. Please use TLS 1.2 when calling LinkedIn APIs. All API requests to api.linkedin.com must be made over HTTPS. Calls made over HTTP will fail.
Step 1
: Add Jquery for Javascript library, run command:
$ yarn add jquery
Then, set content of config/webpack/environment.js:
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
environment.plugins.prepend('Provide',
new webpack.ProvidePlugin({
$: 'jquery/src/jquery',
jQuery: 'jquery/src/jquery'
})
)
module.exports = environment
Step 2
: Create ssl connection by add thin
gem
gem 'thin'
$ bundle install
Edit config/application.rb
and add:
config.force_ssl = true
In project command line, type:
$ openssl genrsa 2048 > host.key
$ chmod 400 host.key
$ openssl req -new -x509 -nodes -sha256 -days 365 -key host.key -out host.cert
After these commands will create two file: host.key
and host.cert
. Then run:
$ thin start --ssl --ssl-key-file=./host.key --ssl-cert-file=./host.cert
It will run project in default address: https://0.0.0.0:3000. If you want to run on https://localhost:3000, just type:
$ thin start -a localhost --ssl --ssl-key-file=./host.key --ssl-cert-file=./host.cert
Step 3
: Create Linkedin oauth2 app.
Go to link: https://www.linkedin.com/developers/
Click the button Create app
, then fill the informations to App name, LinkedIn Page (have to finish it by a custom page), App logo, Terms tick box. Then click to Create app to register your app.
At Settings tab, set the domain of your app, I run with localhost so I will set https://localhost:3000
.
At Auth tab, save the Client ID and Client Secret to config/application.yml
(remember to run commands $ bundle exec figaro install
before this) like these:
LINKEDIN_APP_ID: 86g3...sfjm
LINKEDIN_APP_SECRET: OKnb...jzSL
Then edit, type and save to part Authorized redirect URLs for your app:
https://localhost:3000/auth/linkedin/callback
Check available scopes to use in this page! Mine is r_emailaddress r_liteprofile
.
At Products tab, select Sign In with LinkedIn
, status will change to Review in progress
. All is ok if this status disappear after refresh F5 by a while!
Step 4
: Set all codes like mine. With simple config/routes.rb
:
Rails.application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => "omniauth_callbacks" }
get '/auth/linkedin/callback', to: "linkedin#callback"
post '/auth/linkedin/url', to: "linkedin#popup"
post '/auth/linkedin/token', to: "linkedin#get_token"
post '/auth/linkedin/info', to: "linkedin#get_info"
post '/auth/linkedin/out', to: "linkedin#stop"
root to: "linkedin#home"
end
Create app/controllers/linkedin_controller.rb
with content:
class LinkedinController < ApplicationController
# Lib to get token
require "uri"
require "net/http"
# Data variables set/get
attr_accessor :client_id, :client_secret, :redirect_uri, :scope, :raise_error
# Class variable with 2@
@@token = ""
# Return view linkedins/home page
def home
render 'linkedins/home'
end
# Call back from popup login window of LinkedIn site
def callback
Rails.logger.debug "Callback called! Params:"
Rails.logger.debug params
@code = params[:code]
@state = params[:state]
@redirect = '/auth/linkedin/callback'
# Get token
url = URI("https://www.linkedin.com/oauth/v2/accessToken")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/x-www-form-urlencoded"
host_uri = ENV['HOST']+@redirect
request.body = "grant_type=authorization_code&code=#{@code}&client_id=#{ENV['LINKEDIN_APP_ID']}&client_secret=#{ENV['LINKEDIN_APP_SECRET']}&redirect_uri=#{host_uri}"
response = https.request(request)
Rails.logger.debug "response.read_body:"
# Rails.logger.debug response.read_body
r = JSON.parse(response.read_body)
Rails.logger.debug r["access_token"]
@@token = r["access_token"]
render 'linkedins/callback'
end
# Config init values
def start
@client_id = ENV['LINKEDIN_APP_ID']
@client_secret = ENV['LINKEDIN_APP_SECRET']
@raise_error = 'true'
@redirect = '/auth/linkedin/callback'
@redirect_uri = ENV['HOST']+@redirect
@scope = 'r_emailaddress r_liteprofile'
@state = generate_csrf_token
end
# Return popup url for sign in by LinkedIn, method = POST
def popup
self.start
@url = "https://www.linkedin.com/uas/oauth2/authorization?client_id=#{@client_id}&raise_errors=#{@raise_error}&redirect_uri=#{@redirect_uri}&response_type=code&scope=#{@scope}&state=#{@state}"
# return @url
render json: { status: 'Success', message: 'Load url for popup finished!', link: @url},status: :ok
end
# Get token of current account Linkedin logged
def get_token
Rails.logger.debug 'From get_token, @@token cache:'
Rails.logger.debug @@token
render json: { status: 'Success', message: 'Load token finished!', token: @@token},status: :ok
end
# Get basic info
def get_info
Rails.logger.debug 'From get_info!'
# Create custom api linking
fields = ['id', 'firstName', 'lastName', 'profilePicture']
link = "https://api.linkedin.com/v2/me?projection=(#{ fields.join(',') })"
url = URI(link)
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = "Bearer #{@@token}"
response = https.request(request)
Rails.logger.debug "From get_info, variable response:"
Rails.logger.debug response
r = JSON.parse(response.read_body)
# r = JSON.parse(response.body)
first_name = r['firstName']['localized']['en_US'].to_s
last_name = r['lastName']['localized']['en_US'].to_s
full_name = first_name + " " + last_name
render json: { status: 'Success',message: 'Load link basic info finished!', name: full_name},status: :ok
end
# For logout LinkedIn, by method revoke
def stop
link = 'https://www.linkedin.com/oauth/v2/revoke'
url = URI(link)
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/x-www-form-urlencoded"
request.body = "client_id=#{ENV['LINKEDIN_APP_ID']}&client_secret=#{ENV['LINKEDIN_APP_SECRET']}&token=#{@@token}"
response = https.request(request)
Rails.logger.debug "Test logout linkedin!"
render json: { status: 'Success',message: 'Log out finished!'},status: :ok
end
# Genereate random state
def generate_csrf_token
SecureRandom.base64(32)
end
end
Note to install these gems, and we don't need any oauth2 linkedin libs:
gem 'uri'
gem 'net-http'
$ bundle install
We will exit popup LinkedIn login by this callback view app/views/linkedins/callback.html.erb
:
<script>
// Close this popup show from LinkedIn window open
close();
</script>
Create this main view app/views/linkedins/home.html.erb
:
<p>Linkedin Login Home page</p>
<button id="linkedin-login" type="button">Login</button>
<p id="linkedin-informations">Token here!</p>
<button id="linkedin-logout" type="button">Logout</button>
<p id="linkedin-results">Results here!</p>
<script>
$('#linkedin-login').on('click', function(e){
// e.preventDefault()
var url_popup = ""
var ltoken = ""
var lurl = ""
$.post('/auth/linkedin/url', function(json) {
console.log(json)
url_popup = json.link
if (url_popup != "") {
console.log('Successful to load url popup!')
const w = 600
const h = 600
const top = (screen.height - h) / 4, left = (screen.width - w) / 2
var child = window.open(url_popup, "popupWindow", `width=${w}, height=${h}, top=${top}, left=${left}, scrollbars=yes`)
function checkChild() {
if (child.closed) {
clearInterval(timer);
$.post('/auth/linkedin/token', function(json) {
console.log('Load token link successful!')
$('#linkedin-informations').html('Token is comming ...')
ltoken = json.token
console.log(json.token)
$('#linkedin-informations').html(json.token)
})
$.post('/auth/linkedin/info', function(json) {
console.log('Load info link successful!')
$('#linkedin-results').html('Information is comming ...')
console.log(json)
$('#linkedin-results').html(`Your login account: ${json.name}`)
})
}
}
var timer = setInterval(checkChild, 500);
}
})
})
$('#linkedin-logout').on('click', function(e){
e.preventDefault()
$.post('/auth/linkedin/out', function(json) {
console.log('Log out successful!')
$('#linkedin-results').html(`You logged out!`)
})
})
</script>
Successful screen: