[Laravel] Tích hợp Line login vào project Laravel
![[Laravel] Tích hợp Line login vào project Laravel](/content/images/size/w1200/2021/07/line-login-starter-app-login.182f8863.png)
Line là một ứng dụng rất phổ biến ở Nhật Bản, số lượng người dùng Line hơn 50 triệu người và chiếm tầm 40% dân số.
Là một ứng dụng sns phổ biến nên việc tích hợp Line vào các dự án (users: Japanese) sẽ giúp web, app có trải nghiệm tốt hơn, tận dụng được các thông tin người dùng được cung cấp từ Line. Trong bài viết này mình sẽ hướng dẫn tích hợp chức năng login dựa theo document của Line.
Lưu ý: Line hiện tại hỗ trợ 2 phiên bản API là v2.0 và v2.1. Trong bài viết này mình sẽ sử dụng phiên bản v2.1
Giải thích về luồng xử lý Line Login

Luồng xử lý login của Line được dựa trên luồng xử lý của OAuth 2.0 authorization code flow
Để tích hợp được chức năng login chúng ta phải thực hiện đẩy đủ các bước trong flow phía trên. Mình sẽ giải thích sơ qua về flow trên để các bạn hình dung được logic xử lý.
- Người dùng lựa chọn chức năng Login with Line ở phía Webapp
- Webapp chuyển hướng sang trang đăng nhập của phía Line thông qua 1 authorization url
- Phía Line hiển thị màn hình Login
- Người dùng nhập các thông tin email và password
- Phía Line hiển thị màn hình lựa chọn cung cấp quyền cho phép truy cập thông tin
- Người dùng lựa chọn các quyền và accept
- Phía Line trả về
code
vàstate
cho phía Webapp. Ở bước này có thể kiểm trastate
gửi đi vàstate
trả về có khớp nhau không để đảm bảo tính bảo mật - Phía Webapp dùng
code
vừa nhận được để lấyaccess_token
- Phía Line trả về
access_token
- Sử dụng
access_token
để lấy thông tin profile của người dùng từ phía Line
Tích hợp vào project laravel
1. View
Tạo file view cho chức năng login và thêm button Login with Line. Khi click vào button/thẻ a thì sẽ chuyển hướng đến Line Plaform thông qua authorization url ở bước 2 (Link này mình sẽ sinh ra ở controller và đưa nó vào href ở thẻ a)
<div class="col-sm-12">
<a href="{{$authUrl}}" class="social-button" id="line">
<span class="badge">
<img src="{{asset('/images/social-network/line-logo.png')}}" alt="">
</span>
<span> LINEでログイン</span>
</a>
</div>
.social-button {
background-position: 25px 0;
box-sizing: border-box;
color: rgb(255, 255, 255);
cursor: pointer;
display: inline-block;
height: 50px;
line-height: 50px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
vertical-align: middle;
width: 100%;
border-radius: 5px;
margin: 10px auto;
}
#line {
background: #00C300;
}
#line span {
box-sizing: border-box;
color: #ffffff;
cursor: pointer;
text-align: center;
}
.badge {
display: inline-block;
float: left;
width: 60px;
height: 60px;
line-height: 60px;
overflow: hidden;
text-align: center;
font-size: 2.6rem;
border-right: #fff 1px solid;
margin-right: 0.7em;
font-weight: normal;
}
Download logo của LINE tại đây
Mở màn hình trong login và chúng ta sẽ có kết quả như sau:

2. Route
Tạo 2 route cho phần login này. Một route trả về view và một route xử lý dữ liệu do Line trả về (Callback Url).
// Login Line
Route::get('line/login', 'LoginController@redirectToLine')->name('login.line');
// Callback url
Route::get('line/login/callback', 'LoginController@handleLineCallback')->name('login.line.callback');
3. Config
Trong thư mục /config
tạo file line.php
để định nghĩa các api của Line mà mình sử dụng.
<?php
return [
'line_profile_uri' => 'https://api.line.me/v2/profile',
'line_token_uri' => 'https://api.line.me/oauth2/v2.1/token',
'line_authorize_uri' => 'https://access.line.me/oauth2/v2.1/authorize',
'line_verify_uri' => 'https://api.line.me/oauth2/v2.1/verify'
];
Trong đó:
line_profile_uri
API để lấy thông tin Profile người dùngline_token_uri
API để lấy access_token từ like sau khi đăng nhậpline_authorize_uri
API chuyển hướng đăng nhập Lineline_verify_uri
API để xác minh ID_token trả về từ Line và lấy thông tin Profile (Chỉ sử dụng cho v2.1)
Đăng nhập tài khoản Line Developer và cài đặt Line Login
Sau khi tạo xong Provider và thêm Line Login trên tài khoản developer, lấy các thông tin (Channel ID và Channel Secret) thêm vào .env
của Laravel
LINE_LOGIN_CHANNEL_ID = '****'
LINE_LOGIN_CHANNEL_SECRET = '*****'
Ngoài ra, bạn cần thêm callback URL vào Line Login. Phía line sẽ kiểm tra redirect_url trong authorization_url với callback URL đã thêm ở phía Line có khớp với nhau không.
Callback URL trong trường hợp này (là route thứ 2 phía trên) có dạng như:
- Local: http://127.0.0.1:8000/line/login/callback
- Serve: https://domain.com/line/login/callback

4. Service
Để tách xử lý logic ra khỏi controller, mình sẽ tạo 1 service chỉ xử lý các logic liên quan đến Line.
<?php
namespace App\Services;
use GuzzleHttp\Client;
use Illuminate\Support\Carbon;
class LineService
{
public function getLoginBaseUrl()
{
$currentTime = Carbon::now()->getTimestamp();
$url = config('line.line_authorize_uri') . '?';
$url .= 'response_type=code';
$url .= '&client_id=' . env('LINE_LOGIN_CHANNEL_ID');
$url .= '&redirect_uri=' . route('login.line.callback');
$url .= '&state=' . $currentTime;
$url .= '&scope=openid%20profile%20real_name%20gender%20birthdate%20phone%20address%20email';
return $url;
}
public function getLineToken($code)
{
$client = new Client();
$response = $client->post(config("line.line_token_uri"), [
'form_params' => [
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => route('login.line.callback'),
'client_id' => env('LINE_LOGIN_CHANNEL_ID'),
'client_secret' => env('LINE_LOGIN_CHANNEL_SECRET')
]
]);
return json_decode($response->getBody()->getContents(), true);
}
public function getUserProfile($token)
{
$client = new Client();
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
];
$response = $client->get( config('line.line_profile_uri'), [
'headers' => $headers
]);
return json_decode($response->getBody()->getContents(), true);
}
public function verifyIDToken($idToken) {
$client = new Client();
$response = $client->post(config("line.line_verify_uri"), [
'form_params' => [
'id_token' => $idToken,
'client_id' => env('LINE_LOGIN_CHANNEL_ID'),
]
]);
return json_decode($response->getBody()->getContents(), true);
}
}
Trong đó:
getLoginBaseUrl()
- Tạo authorization requests chuyển sang trang đăng nhập của LINE để đăng nhập tài khoản.
- API tham khảo: Make authorization request
getLineToken($code)
- Sau khi login với LINE thì callback trả về sẽ chứa code. Từ code sẽ gọi đến api get access token để lấy access_token
- API tham khảo: Get access token
getUserProfile($token)
- Lấy thông tin profile cơ bản của người dùng
- API tham khảo: Get user profile
verifyIDToken($idToken)
- Lấy thông tin profile từ ID Token (Có chứa thông tin line profile+)
- API tham khảo: Verify ID token
5. Controller
Tạo một controller cho phần Line Login.
Do các logic xử lý đã được đưa vào service nên file controller sẽ rất gọn.
<?php
namespace App\Http\Controllers;
use App\Services\LineService;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\RedirectResponse;
class LoginController extends Controller
{
/** @var LineService */
protected $lineService;
/**
* LoginController constructor.
* @param LineService $lineService
*/
public function __construct(LineService $lineService)
{
$this->lineService = $lineService;
}
/**
* Login Blade
* @param Request $request;
* @return View
*/
public function index(Request $request) {
$authUrl = $this->lineService->getLoginBaseUrl();
return view('login.line', compact('authUrl'));
}
/**
* Handle result which Line API returned.
* @param Request $request
* @return void
*/
public function handleLineCallback(Request $request) {
$code = $request->input('code', '');
$response = $this->lineService->getLineToken($code);
// Get profile from access token.
$profile = $this->lineService->getLineToken($response['access_token']);
// Get profile from ID token
$profile = $this->lineService->verifyIDToken($response['id_token']);
}
}
👏👏👏Thanks for taking the time to read my article !!