Skip to main content

7個小時與Linkedin OAuth的戰鬥

Opass
A life well lived

最近接了一個case,case的其中一項目標是要實踐使用Facebook, Gogle, Linkedin來登入網站。

上網查了一下,有朋友推薦使用 oauth.io 這個服務。號稱可以幫你整合Facebook, Google, Linkedin, Yahoo, Twitter.....所有你想得到的OAuth Provider,於是就很開心的申請一個帳號來用。free版一個月可以接受1000次不同帳號的OAuth API操作,對一個小網站來說應該是很夠用了。因此就不假思索的開始研究。

不得不說,OAuth.io 很簡單,照著官方網站的操作把Facebook, Google, Linkedin的Private key和Domain指到OAuth.io,最後利用OAuth.io的javascript Library取得access_token。就可以向Service Provider取得資料授權。

花了15分鐘把Facebook搞定,花了另外15分鐘把Google搞定,確定可以取得access_token,But……人生很多問題就出在這個But啊

設定Linkedin授權給OAuth.io後,熊熊發現,為什麼Linkedin的access_token長得和別人不一樣?

oauth.io for linkedin

是的,沒有為什麼,那是因為,明明Linkedin已經使用了OAuth2.0,但是OAuth.io並只支援到OAuth1.0啊。

接下來就是悲劇的開始,現在眼前面臨了兩個選擇 1. 研究OAuth1.0,利用OAuth1.0來完成授權 2. 放棄OAuth.io for linkedin,手動利用OAuth2.0授權

為了要維持程式的一致性,所以很自然的選擇了第一種作法,但是,萬萬沒想到這個決定,竟然會讓開發者,在接下來的四個小時,跌入了痛苦的深淵(盛竹如口吻)。

相較於OAuth2.0,OAuth1.0是非常討厭的東西……看了Slideshare的這份投影片,你就會理解我在說什麼

OAuth相較於OAuth2.0的簡單取得access_token,再利用private key向Service Provider伺服器驗證並交換user data,OAuth1.0必須要在開發者這邊先做好資料簽章,方法是使用HMAC,簽章的對象是你想要取得資料的網址。你可以去 Linkedin 的 Test Conosle 玩耍一下,大概會知道我在說什麼。

讓我們直接跳過一連串的廢話,重點是: 「OAuth1.0非常麻煩」,但不論再怎麼麻煩,總是會有範例的啊,問題是,Linkedin for python user 提供的範例 是使用python2,官方建議的套件可以在這裡找到。

天殺的python2啊~~~林北使用的是最新最潮的python3啦,稍微找了一下,發現其他支援的套件操作方式都沒有Linkedin官方提供的簡單,於是我又下了一個錯誤的決定:

「手動把套件轉成Python3 support!!」

於是又稍微研究了一下怎麼把python2的檔轉換成支援python3,看起來是簡單的下 2to3 就好了,然後稍微檢查一下import library支援性的問題。費盡一番心血把這些問題處理好後,把程式碼安插到我的專案,開始測試到底有沒有辦法從Linkedin那邊抓到資料。

卻發現,Linkedin有回應(淚),但是授權錯誤根本抓不到。

然後又是一連串研究到底是哪裡設定錯了,看起來根本沒錯啊,於是重新比較Linkedin的test console,讓我懷疑,該Library對Linkedin的簽章方法過時,可能Miss掉一些東西,導致簽章一直過不了。

看到最後我也不想去改Source code了……那本身就是一個悲劇。在悲劇上花費心力對你的人生一點幫助都沒有。

於是,我放棄OAuth1.0,放棄OAuth.io對Linkedin的support,開始手動寫OAuth2.0的code。

相較於折騰人的OAuth1.0,OAuth2.0好多了,但是有幾點小細節要注意,因為Linkedin的官方文件真的很容易誤導人,像是我卡在這邊浪費一個多小時

你可以在Linkedin官方OAuth2.0 step by step教學中看到這段話

linkedin oauth2.0

是的,你要對Linkedin使用https,這個我有注意到,然後要使用POST,嗯,這個我也注意到

但是請「千萬要記得」,正確的作法是對**整個網址POST!!!**而 不是把grant_type, code, redirect_url等東西包起來當成資料對以前的網址做POST啊

如果你的作法和我或是這個國外網友一樣愚蠢的話,會收到這樣的錯誤訊息

{"error":"invalid_request","error_description":"missing required parameters, includes an invalid parameter value, parameter more then once. : Unable to retrieve access token : appId or redirect uri does not match authorization code or authorization code expired"}

他馬的誰會這樣做啦(崩潰)沒事對這種東西做POST幹嘛……為什麼要把參數都寫在網址上再用POST,這不是理所當然要用GET嗎(已哭)

突破這一關後,你還有最後一個難關。

接下來,Linkedin會一直授權失敗,

查詢問題後發現問題在於如果你有使用Linkedin OAuth1.0過,那OAuth2.0會一直過不了。有國外網友很神奇的解決了這個問題,那就是到Linkedin的設定頁面

Selection_012

按下Revoke,撤銷API key 和 Secret Key,之後重新設定新的API key和Sercret Key,一切才大功告成。

謹以本文,奉獻給未來踏上Linkedin的朋友誠摯的建議

  1. for Linkedin,不要用OAuth1.0。
  2. 用OAuth2.0如果發生問題或錯誤,請服用本文解決,人類的知識來自於眾人的分享與累積,不要讓我的七個小時白白浪費掉啊。