Có rất nhiều cách để thiết kế API nhưng phổ biến và được sử dụng nhiều nhất là RESTful API. Vì RESTful API không sử dụng session và cookie nên để xác thực ta sử dụng đến JSON Web Token. Để hiểu rõ hơn về RESTful API và JWT thì trên viblo đã có rất nhiều bài viết về chủ đề này, các bạn có thể tìm hiểu thêm. Trong phạm vi bài viết này mình sẽ sử dụng RESTful API và JWT để xây dựng API đăng nhập Facebook, Twitter và Google. Trước hết ta cần hiểu cơ chế authen của JWT, về cơ bản và dễ hiểu nhất mình xin phép quote đoạn kịch bản authen sau
xác thực. Đây là bản kịch bản phổ biến nhất cho việc sử dụng JWT. Một khi người dùng đã đăng nhập vào hệ thống thì những yêu cầu tiếp theo từ phía người dùng sẽ bao gồm thêm mã JWT, cho phép người dùng có quyền truy cập vào các đường dẫn, dịch vụ và tài nguyên mà cần phải có sự cho phép. . Phương pháp này không bị ảnh hưởng bởi Chia sẻ tài nguyên nguồn gốc chéo [CORS] do nó không sử dụng cookie
Đầu tiên để xây dựng được đăng nhập API bằng mạng xã hội ta cần trải qua một bước gọi tạm thời là "phân tích thiết kế". Việc cần làm là vẽ ra cái Database. Ta có một bảng
composer require facebook/graph-sdk
6 chứa các thông tin về người dùng. composer require facebook/graph-sdk
7, composer require facebook/graph-sdk
8, composer require facebook/graph-sdk
9. Mỗi người dùng có thể liên kết với nhiều mạng xã hội khác nhau vì vậy ta sẽ thiết kế thêm 1 bảng nữa tạm gọi là // app\Http\Controllers\Api\AuthController.php
// use Facebook\Facebook;
public function facebook[Request $request]
{
$facebook = $request->only['access_token'];
if [!$facebook || !isset[$facebook['access_token']]] {
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
// Khởi tạo instance của Facebook Graph SDK
$fb = new Facebook[[
'app_id' => config['services.facebook.app_id'],
'app_secret' => config['services.facebook.app_secret'],
]];
try {
$response = $fb->get['/me?fields=id,name,email,link,birthday', $facebook['access_token']]; // Lấy thông tin
// user facebook sử dụng access_token được gửi lên từ client
$profile = $response->getGraphUser[];
if [!$profile || !isset[$profile['id']]] { // Nếu access_token không lấy đc thông tin hợp lệ thì trả về login false luôn
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
$email = $profile['email'] ?? null;
$social = SocialNetwork::where['social_id', $profile['id']]->where['type', config['user.social_network.type.facebook']]->first[];
// Lấy được userId của Facebook ta kiểm tra trong bảng social_networks đã có chưa, nếu có thì tài khoản facebook này
// đã từng đăng nhập vào hệ thống ta chỉ cần lấy ra user rồi generate jwt trả về cho client; Ngược lại nếu chưa có thì
// ta sẽ tiếp tục dùng email trả về từ facebook kiểm tra xem nếu có user với email như thế rồi thì lấy luôn user đó nếu
// không thì tạo user mới với email trên và tạo bản ghi social_network lưu thông tin userId của facebook rồi generate jwt
// để trả về cho client
if [$social] {
$user = $social->user;
} else {
$user = $email ? User::firstOrCreate[['email' => $email]] : User::create[];
$user->socialNetwork[]->create[[
'social_id' => $profile['id'],
'type' => config['user.social_network.type.facebook'],
]];
$user->name = $profile['name'];
$user->save[];
}
$token = JWTAuth::fromUser[$user];
return $this->responseSuccess[compact['token', 'user']];
} catch [\Exception $e] {
Log::error['Error when login with facebook: ' . $e->getMessage[]];
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
}
0 có quan hệ 1 nhiều với người dùng bảng và có chứa các trường // app\Http\Controllers\Api\AuthController.php
// use Facebook\Facebook;
public function facebook[Request $request]
{
$facebook = $request->only['access_token'];
if [!$facebook || !isset[$facebook['access_token']]] {
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
// Khởi tạo instance của Facebook Graph SDK
$fb = new Facebook[[
'app_id' => config['services.facebook.app_id'],
'app_secret' => config['services.facebook.app_secret'],
]];
try {
$response = $fb->get['/me?fields=id,name,email,link,birthday', $facebook['access_token']]; // Lấy thông tin
// user facebook sử dụng access_token được gửi lên từ client
$profile = $response->getGraphUser[];
if [!$profile || !isset[$profile['id']]] { // Nếu access_token không lấy đc thông tin hợp lệ thì trả về login false luôn
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
$email = $profile['email'] ?? null;
$social = SocialNetwork::where['social_id', $profile['id']]->where['type', config['user.social_network.type.facebook']]->first[];
// Lấy được userId của Facebook ta kiểm tra trong bảng social_networks đã có chưa, nếu có thì tài khoản facebook này
// đã từng đăng nhập vào hệ thống ta chỉ cần lấy ra user rồi generate jwt trả về cho client; Ngược lại nếu chưa có thì
// ta sẽ tiếp tục dùng email trả về từ facebook kiểm tra xem nếu có user với email như thế rồi thì lấy luôn user đó nếu
// không thì tạo user mới với email trên và tạo bản ghi social_network lưu thông tin userId của facebook rồi generate jwt
// để trả về cho client
if [$social] {
$user = $social->user;
} else {
$user = $email ? User::firstOrCreate[['email' => $email]] : User::create[];
$user->socialNetwork[]->create[[
'social_id' => $profile['id'],
'type' => config['user.social_network.type.facebook'],
]];
$user->name = $profile['name'];
$user->save[];
}
$token = JWTAuth::fromUser[$user];
return $this->responseSuccess[compact['token', 'user']];
} catch [\Exception $e] {
Log::error['Error when login with facebook: ' . $e->getMessage[]];
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
}
1, // app\Http\Controllers\Api\AuthController.php
// use Facebook\Facebook;
public function facebook[Request $request]
{
$facebook = $request->only['access_token'];
if [!$facebook || !isset[$facebook['access_token']]] {
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
// Khởi tạo instance của Facebook Graph SDK
$fb = new Facebook[[
'app_id' => config['services.facebook.app_id'],
'app_secret' => config['services.facebook.app_secret'],
]];
try {
$response = $fb->get['/me?fields=id,name,email,link,birthday', $facebook['access_token']]; // Lấy thông tin
// user facebook sử dụng access_token được gửi lên từ client
$profile = $response->getGraphUser[];
if [!$profile || !isset[$profile['id']]] { // Nếu access_token không lấy đc thông tin hợp lệ thì trả về login false luôn
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
$email = $profile['email'] ?? null;
$social = SocialNetwork::where['social_id', $profile['id']]->where['type', config['user.social_network.type.facebook']]->first[];
// Lấy được userId của Facebook ta kiểm tra trong bảng social_networks đã có chưa, nếu có thì tài khoản facebook này
// đã từng đăng nhập vào hệ thống ta chỉ cần lấy ra user rồi generate jwt trả về cho client; Ngược lại nếu chưa có thì
// ta sẽ tiếp tục dùng email trả về từ facebook kiểm tra xem nếu có user với email như thế rồi thì lấy luôn user đó nếu
// không thì tạo user mới với email trên và tạo bản ghi social_network lưu thông tin userId của facebook rồi generate jwt
// để trả về cho client
if [$social] {
$user = $social->user;
} else {
$user = $email ? User::firstOrCreate[['email' => $email]] : User::create[];
$user->socialNetwork[]->create[[
'social_id' => $profile['id'],
'type' => config['user.social_network.type.facebook'],
]];
$user->name = $profile['name'];
$user->save[];
}
$token = JWTAuth::fromUser[$user];
return $this->responseSuccess[compact['token', 'user']];
} catch [\Exception $e] {
Log::error['Error when login with facebook: ' . $e->getMessage[]];
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
}
2, // app\Http\Controllers\Api\AuthController.php
// use Facebook\Facebook;
public function facebook[Request $request]
{
$facebook = $request->only['access_token'];
if [!$facebook || !isset[$facebook['access_token']]] {
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
// Khởi tạo instance của Facebook Graph SDK
$fb = new Facebook[[
'app_id' => config['services.facebook.app_id'],
'app_secret' => config['services.facebook.app_secret'],
]];
try {
$response = $fb->get['/me?fields=id,name,email,link,birthday', $facebook['access_token']]; // Lấy thông tin
// user facebook sử dụng access_token được gửi lên từ client
$profile = $response->getGraphUser[];
if [!$profile || !isset[$profile['id']]] { // Nếu access_token không lấy đc thông tin hợp lệ thì trả về login false luôn
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
$email = $profile['email'] ?? null;
$social = SocialNetwork::where['social_id', $profile['id']]->where['type', config['user.social_network.type.facebook']]->first[];
// Lấy được userId của Facebook ta kiểm tra trong bảng social_networks đã có chưa, nếu có thì tài khoản facebook này
// đã từng đăng nhập vào hệ thống ta chỉ cần lấy ra user rồi generate jwt trả về cho client; Ngược lại nếu chưa có thì
// ta sẽ tiếp tục dùng email trả về từ facebook kiểm tra xem nếu có user với email như thế rồi thì lấy luôn user đó nếu
// không thì tạo user mới với email trên và tạo bản ghi social_network lưu thông tin userId của facebook rồi generate jwt
// để trả về cho client
if [$social] {
$user = $social->user;
} else {
$user = $email ? User::firstOrCreate[['email' => $email]] : User::create[];
$user->socialNetwork[]->create[[
'social_id' => $profile['id'],
'type' => config['user.social_network.type.facebook'],
]];
$user->name = $profile['name'];
$user->save[];
}
$token = JWTAuth::fromUser[$user];
return $this->responseSuccess[compact['token', 'user']];
} catch [\Exception $e] {
Log::error['Error when login with facebook: ' . $e->getMessage[]];
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
}
3. Migration as after________số 8Đăng nhập API với Facebook
Đầu tiên ta tải thư viện đồ thị của facebook
composer require facebook/graph-sdk
Ta will code same as flow đã vẽ ra trên. Các bạn cùng xem code nhé, mình comment cho dễ hiểu nhé
// app\Http\Controllers\Api\AuthController.php
// use Facebook\Facebook;
public function facebook[Request $request]
{
$facebook = $request->only['access_token'];
if [!$facebook || !isset[$facebook['access_token']]] {
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
// Khởi tạo instance của Facebook Graph SDK
$fb = new Facebook[[
'app_id' => config['services.facebook.app_id'],
'app_secret' => config['services.facebook.app_secret'],
]];
try {
$response = $fb->get['/me?fields=id,name,email,link,birthday', $facebook['access_token']]; // Lấy thông tin
// user facebook sử dụng access_token được gửi lên từ client
$profile = $response->getGraphUser[];
if [!$profile || !isset[$profile['id']]] { // Nếu access_token không lấy đc thông tin hợp lệ thì trả về login false luôn
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
$email = $profile['email'] ?? null;
$social = SocialNetwork::where['social_id', $profile['id']]->where['type', config['user.social_network.type.facebook']]->first[];
// Lấy được userId của Facebook ta kiểm tra trong bảng social_networks đã có chưa, nếu có thì tài khoản facebook này
// đã từng đăng nhập vào hệ thống ta chỉ cần lấy ra user rồi generate jwt trả về cho client; Ngược lại nếu chưa có thì
// ta sẽ tiếp tục dùng email trả về từ facebook kiểm tra xem nếu có user với email như thế rồi thì lấy luôn user đó nếu
// không thì tạo user mới với email trên và tạo bản ghi social_network lưu thông tin userId của facebook rồi generate jwt
// để trả về cho client
if [$social] {
$user = $social->user;
} else {
$user = $email ? User::firstOrCreate[['email' => $email]] : User::create[];
$user->socialNetwork[]->create[[
'social_id' => $profile['id'],
'type' => config['user.social_network.type.facebook'],
]];
$user->name = $profile['name'];
$user->save[];
}
$token = JWTAuth::fromUser[$user];
return $this->responseSuccess[compact['token', 'user']];
} catch [\Exception $e] {
Log::error['Error when login with facebook: ' . $e->getMessage[]];
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
}
Time job but res only to create route cursor to the function on more is done
composer require facebook/graph-sdk
1Đăng nhập API với Twitter
Với Twitter, ta sẽ sử dụng thư viện
// app\Http\Controllers\Api\AuthController.php
// use Facebook\Facebook;
public function facebook[Request $request]
{
$facebook = $request->only['access_token'];
if [!$facebook || !isset[$facebook['access_token']]] {
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
// Khởi tạo instance của Facebook Graph SDK
$fb = new Facebook[[
'app_id' => config['services.facebook.app_id'],
'app_secret' => config['services.facebook.app_secret'],
]];
try {
$response = $fb->get['/me?fields=id,name,email,link,birthday', $facebook['access_token']]; // Lấy thông tin
// user facebook sử dụng access_token được gửi lên từ client
$profile = $response->getGraphUser[];
if [!$profile || !isset[$profile['id']]] { // Nếu access_token không lấy đc thông tin hợp lệ thì trả về login false luôn
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
$email = $profile['email'] ?? null;
$social = SocialNetwork::where['social_id', $profile['id']]->where['type', config['user.social_network.type.facebook']]->first[];
// Lấy được userId của Facebook ta kiểm tra trong bảng social_networks đã có chưa, nếu có thì tài khoản facebook này
// đã từng đăng nhập vào hệ thống ta chỉ cần lấy ra user rồi generate jwt trả về cho client; Ngược lại nếu chưa có thì
// ta sẽ tiếp tục dùng email trả về từ facebook kiểm tra xem nếu có user với email như thế rồi thì lấy luôn user đó nếu
// không thì tạo user mới với email trên và tạo bản ghi social_network lưu thông tin userId của facebook rồi generate jwt
// để trả về cho client
if [$social] {
$user = $social->user;
} else {
$user = $email ? User::firstOrCreate[['email' => $email]] : User::create[];
$user->socialNetwork[]->create[[
'social_id' => $profile['id'],
'type' => config['user.social_network.type.facebook'],
]];
$user->name = $profile['name'];
$user->save[];
}
$token = JWTAuth::fromUser[$user];
return $this->responseSuccess[compact['token', 'user']];
} catch [\Exception $e] {
Log::error['Error when login with facebook: ' . $e->getMessage[]];
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
}
4 để lấy thông tin người dùng từ Twitter Mã tương tự như với facebook, chỉ có khác là với twitter, ta sẽ nhận tới 2 tham số token là access_token và access_token_secretcomposer require facebook/graph-sdk
3Thêm tuyến đường
composer require facebook/graph-sdk
4API đăng nhập với Google
Với google thì ta sẽ dùng
// app\Http\Controllers\Api\AuthController.php
// use Facebook\Facebook;
public function facebook[Request $request]
{
$facebook = $request->only['access_token'];
if [!$facebook || !isset[$facebook['access_token']]] {
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
// Khởi tạo instance của Facebook Graph SDK
$fb = new Facebook[[
'app_id' => config['services.facebook.app_id'],
'app_secret' => config['services.facebook.app_secret'],
]];
try {
$response = $fb->get['/me?fields=id,name,email,link,birthday', $facebook['access_token']]; // Lấy thông tin
// user facebook sử dụng access_token được gửi lên từ client
$profile = $response->getGraphUser[];
if [!$profile || !isset[$profile['id']]] { // Nếu access_token không lấy đc thông tin hợp lệ thì trả về login false luôn
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
$email = $profile['email'] ?? null;
$social = SocialNetwork::where['social_id', $profile['id']]->where['type', config['user.social_network.type.facebook']]->first[];
// Lấy được userId của Facebook ta kiểm tra trong bảng social_networks đã có chưa, nếu có thì tài khoản facebook này
// đã từng đăng nhập vào hệ thống ta chỉ cần lấy ra user rồi generate jwt trả về cho client; Ngược lại nếu chưa có thì
// ta sẽ tiếp tục dùng email trả về từ facebook kiểm tra xem nếu có user với email như thế rồi thì lấy luôn user đó nếu
// không thì tạo user mới với email trên và tạo bản ghi social_network lưu thông tin userId của facebook rồi generate jwt
// để trả về cho client
if [$social] {
$user = $social->user;
} else {
$user = $email ? User::firstOrCreate[['email' => $email]] : User::create[];
$user->socialNetwork[]->create[[
'social_id' => $profile['id'],
'type' => config['user.social_network.type.facebook'],
]];
$user->name = $profile['name'];
$user->save[];
}
$token = JWTAuth::fromUser[$user];
return $this->responseSuccess[compact['token', 'user']];
} catch [\Exception $e] {
Log::error['Error when login with facebook: ' . $e->getMessage[]];
return $this->responseErrors[config['code.user.login_facebook_failed'], trans['messages.user.login_facebook_failed']];
}
}
5 để verify token và lấy thông tin user. Và khách hàng sẽ gửi id_token khi khách hàng thực hiện đăng nhập bằng Đăng nhập Googlecomposer require facebook/graph-sdk
6Thêm tuyến đường
composer require facebook/graph-sdk
7Kết quảNhư vậy mình vừa xây dựng đủ 3 API đăng nhập với 3 dịch vụ ta vẫn thường hay sử dụng mỗi khi phát triển web hoặc ứng dụng. Hi vọng bài viết hữu ích với các bạn. Các bạn có thể tham khảo code tại link Github. https. //github. com/quanvhframgia/api-login-socials Link