使用C#開發LineBot(17) – 使用新版Line Login v2.1

Line在去年以OAuth規格推出了Line Login機制,試圖與各家大廠一起角逐身分驗證與單一登入SSO(Single-Sign-On)的一席之地,相關的概念與使用方式我們在06年底曾經介紹過

而關於SSO與OAuth相關的技術與概念,我們也曾經在這邊有過分享。

今年(2017)底,Line又更新了Line Login相關的API,來到了v2以及v2.1,在這一版更新當中,Line Login可以跟Line bot做連結和整合,以便於讓你得知用戶更多的訊息並與用戶互動。除了功能比較多之外,還有一個你不得不升級的原因,因為舊版v1的API,依照公告,將於2018年三月底停用:

https://developers.line.me/en/news/2017/12/05/

因此我們的LineBotSDK也更著做了升級,我們後續將分幾篇貼文來介紹新版的Line Login API,這篇我們先來看基本SSO的部分,首先,由於申請畫面跟舊版有些許不同,我們也一併整理一下。

申請新版Line Login服務時,請先從 https://developers.line.me/en/ 的官方管理站台登入,登入後請點選主畫面的『Start Using Line Login』:

接著出現底下畫面,請依序輸入相關資料,其實本質上跟我們介紹v1時候的做法差不多,由於我們待會要做的是Web Site的SSO,下圖畫面請務必勾選Use Web:

輸入完成後按下 Confirm,最後會出現底下畫面,基本上一個服務就建立完成了。但相關資訊我們還要接著輸入,因此,待會請點選底下畫面中我們新建立好的這個Line Login服務圖示 :

進入後你會看到底下畫面:

其中大部分的資訊都是我們剛才自己輸入的,少部分是系統產生的,其中就包含了上圖畫面中標示A、B的部分,如果你熟悉OAuth flow就應該不陌生,上圖中的ID與secret就是我們要做SSO時的client_id與client_secret,不過新版Line Login底下多了一個Bot linked…的部分(標示C)我們後面再來談。

請留意畫面左上方有一個App Settings:

點選後會出現底下畫面:

我們待會按下上圖右方的筆,來修改這個callback URL。在此之前,我們當然得先產生出一個Callback URL才行。

如果你熟悉SSO與OAuth相關的技術與概念(不熟悉的話請先看這邊),你就會知道要與Line Login做整合,你的網站必須至少有兩個頁面,一個頁面是導入Line Login用戶登入的引導頁,另一個頁面則是Line Login將用戶導回我們網站時,接收Line伺服器所傳回的code的Callback頁面,上圖中所需要輸入的callback URL指的就是該頁面的位置。

因此,我們待會要透過Visual Studio以asp.net建立一個web site,其中包含兩個頁面index.html與callback.aspx,我們先透過VS建立一個空的網站,並且在網站中加上index.html以及callback.aspx這兩個頁面。

建立好之後,我們在index.html頁面中,撰寫如下的程式碼,這段程式碼的目的就是將用戶引導至Line Login的登入驗證畫面:

請留意6-12行,是組出引導入Line Login登入畫面的URL,其中與v1版本相比,比較不同的除了endpoint(7行)之外,最主要的是scope的支援範圍變廣了,寫法也不同,變成『openid profile』,這符合OAuth2的最新標準規範。

而其中第10行的localhost:58155我們之所以知道port no,當然是因為我們已經用VS透過IIS Express運行後的結果,這個callback.aspx頁面待會就是在用戶輸入完帳密,要被Line伺服器導回我們的網站時的code接收頁面,用來接收將會傳回來的code。

別忘了,我們也要同時把這個頁面的網址填入剛才在申請Line Login時的AppSettings項目下的Callback URL:

這樣Line伺服器才知道用戶輸入帳密驗證身分成功之後,要導回哪個頁面。

我們在該頁面中,也需要撰寫程式碼來接收將會從網址列傳回來的code參數。為了達成此目的,請將專案引入(或升級)至LineBotSDK 0.6.4-beta3 以上版本:

然後可以接著在callback.aspx頁面的Page_Load方法中,撰寫底下程式碼:

請留意我們用到的isRock.LineLoginV21.Utility.GetTokenFromCode()方法,必須在升級到LineBotSDK 0.6.4-beta3版本以上才有。

在上面的程式碼當中,我們首先在第4行抓取Line伺服器在callback回來時應當回帶入的URL QueryString參數code,如果該參數不存在,則顯示錯誤(7,8行)。

抓取到之後,我們可以透過GetTokenFromCode()方法取得token,注意第14,15,16三行分別要傳入你剛才在申請Line Login時候取得的Channel ID, Channel Secret,以及你自己設定的callback url,如果一切正確,運行後會得到一個回傳的token物件。

該物件中會有一個access_token屬性,透過該屬性,你可以輕鬆的以GetUserProfile()方法取得用戶身分資訊(第21行),我們在第22行將其顯示出來。

網站撰寫好之後,我們可以試著運行看看,首先運行index.html,按下底下的Button:

它會觸發我們在index.html頁面中所撰寫的javascript,將網頁引導至Line Login的登入頁面:

如果用戶不曾登入過,會出現上面這樣的頁面,讓用戶輸入他自己的Line帳號密碼,請留意該頁面並非我們做的網頁,而是Line自己做的登入頁,因此用戶的帳密我們無法得知,也能確保資訊安全。

倘若用戶曾經登入過,新版API會出現底下畫面,讓用戶選擇是否要切換身分:

用戶可以選擇上圖標示A的登入鈕,以該帳號直接登入(無須再次輸入帳密),或是點選上圖標示B的位置,以其他帳號登入。

用戶登入之後,將會看到底下這個畫面,圖中標示A、B的位置,顯示的是您剛才申請的Line Login服務的名稱、與說明:

而上圖標示C的部分很重要,這是舊版沒有的,也就是存取範圍(scope)的部分,由於先前我們指定的scopt為『profile openid』,因此會帶出上面標示C所顯示的這兩項『個人資料、用戶識別碼』,倘若用戶同意我們的網站可以存取該資訊,按下『同意』鈕之後,網站就會被Line伺服器導回我們撰寫好的callback.aspx頁面,並且跟著頁面傳來一個非常重要的code:

請留意導回的網址,你會發現網址列有傳給我們的code與state,跟Line Notify一樣,state是我們原先在index.html頁面中自行傳入的參數,它會被原封不動的回傳回來,便於我們做身分或交易識別用,而我們的主角是Line傳給我們的網址列參數code。

請參考我們剛才看到的callback.aspx中的程式碼,透過這個code,我們搭配client_id, client_secret與callback url作為參數,就可以用GetTokenFromCode()這個method取得我們想要的access_token(下圖標示A的位置):

取得access_token後,我們要抓取用戶身分也很容易了,可以參考上圖標示B的位置,我們傳入access_token,即可用GetUserProfile()方法來取得用戶的個人資料囉。

至此,我們的網站想要透過Line Login的方式,來進行SSO(Single-Sign-On,單一登入)也就不是什麼問題了。

後面我們再繼續談Line Login的相關功能與應用。

------------------
相關課程:http://www.studyhost.tw/NewCourses/LineBot
電子書:http://studyhost.blogspot.tw/2017/12/line-bot.html
LineBotSDK:https://www.nuget.org/packages/LineBotSDK
如果需要即時取得更多相關訊息,可按這裡加入FB專頁。若這篇文章對您有所幫助,請幫我們分享出去,謝謝您的支持。

留言

Unknown寫道…
作者已經移除這則留言。
Unknown寫道…
David老師,您好,可以幫我看一下我callback.php哪裡有誤嗎,謝謝您,我已經成功得到codestate(如以下網址)
https://example.com/callback.php?code=qHPq6vQ19BbRk0Y3MUGn&state=abcde

我得到的錯誤代碼:
Warning: file_get_contents(https://api.line.me/oauth2/v2.1/token): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request in /example.com.tw/callback.php on line 28
bool(false)

我的程式如下:
$client_id = '{CHANNEL_ID}';//client_id
$client_secret = '{CHANNEL_SECRET}'; //client_secret
$redirect_uri= "https://example.com/callback.php";//callback url
$code = $_GET['code'];
$state = $_GET['state'];

if(!$code){
die('串連失敗');
}

$url = 'https://api.line.me/oauth2/v2.1/token';//Line token網址
$data = array(
'grant_type' => 'authorization_code',
'client_id' => $client_id,
'client_secret' => $client_secret,
'code' => $code,
'redirect_uri' => $redirect_uri,
);
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded",
'method' => 'POST',
'content' => json_encode($data),
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);//第28行
var_dump($result);
俺不是王子.寫道…
建議除了userid和displayname再加上email比較好

//
// Summary:
// 呼叫GetUserProfile後的回傳結果
public class Profile
{
public Profile();

public string displayName { get; set; }
public string userId { get; set; }
public string pictureUrl { get; set; }
public string statusMessage { get; set; }
public string Email{get;set;}
}
Major寫道…
您好,請問要用MVC架構,那callback的頁面要怎麼做呢?
isDavid寫道…
已加上 MVC 範例:
https://github.com/isdaviddong/Line_Login_Example

這個網誌中的熱門文章

使用 Airtable 在小型需求上取代傳統資料庫

使用Semantic Kernel 建立自然語言請假系統

精彩(且驚人)的Semantic Kernel入門範例

在 LINE Bot 開發中使用Semantic Kernel建立自然語言請假系統

專業的價值...