API Authentication sử dụng JWT trong PHP(Phalcon)

Phalcon

Như bạn biết thì khi sử dụng REST API thì khái niệm session không còn tồn tại nữa, vậy làm thế nào để chứng thực người dùng, hoặc bảo vệ REST API thì chúng ta phải dùng một công nghệ mới, trong bài viết này chúng tôi sẽ hướng dẫn dùng JWT. Đây là một ví dụ mà mình thấy khá hữu ích trong việc xác thực người dùng trong các ứng dụng web đặc biệt là mobile app.

JSON Web Token là gì?

JSON Web Token (JWT) là một tiêu chuẩn mở (RFC 7519) định nghĩa một cách nhỏ gọn và an toàn để truyền tải thông tin giữa các bên một cách an toàn dưới dạng 1 đối tượng JSON . Các thông tin này được xác thực và có độ tin cậy cao vì nó có chứa chữ ký số (digital signature).

Sử dụng JWT là cách tốt để áp dụng cơ chế bảo mật đối với các dịch vụ API RESTful mà có thể được sử dụng để truy cập vào cơ sở dữ liệu của bạn.

Chú ý rằng ngoài JWT chúng ta còn có chuẩn OAUTH2, nhưng chuẩn này phức tạp hơn chuẩn ta sẽ bàn sau, hiện tại nếu bạn xây dựng REST API thì JWT là đủ rồi.

JWT là một phương tiện đại diện cho các yêu cầu chuyển giao giữa hai bên Client – Server, các thông tin trong chuỗi JWT được định dạng bằng JSON.

Trong đó chuỗi Token phải có 3 phần:

  • header
  • payload
  • signature

Phần header sẽ chứa kiểu dữ liệu , và thuật toán sử dụng để mã hóa ra chuỗi JWT

{
    "typ": "JWT",
    "alg": "HS256"
}

“typ” (type) chỉ ra rằng đối tượng là một JWT “alg” (algorithm) xác định thuật toán mã hóa cho chuỗi là HS256

Phần payload sẽ chứa các thông tin mình muốn đặt trong chuỗi Token như username , userId , author , … ví dụ:

Signature: Phần chử ký này sẽ được tạo ra bằng cách mã hóa phần header, payload kèm theo một chuỗi secret (khóa bí mật) , ví dụ:

signature = Hash( data, secret );

Cách sử dụng JWT

Nói chung việc tạo hash thế nào chuẩn ta không cần quan tâm, chỉ cần sử dụng sẵn có thư viện php cung cấp là được rồi, chúng tôi thường dùng thư viện

firebase/php-jwt

Bạn có thể tham khảo tại file composer.json https://github.com/lackky/api/blob/master/composer.json#L9, sau khi chúng ta cài đặt thư viện thành công thông qua lệnh composer install, chúng ta hãy tạo một function

$user = $this->auth->check($data);
$key  = base64_decode($this->config->application->jwtSecret);
$time = time();
$expires = $time + env('EXPIRES_TOKEN');
$token = [
   'iss' =>  $this->request->getURI(),
   'iat' =>  $time,
   'exp' =>  $expires,
   'data' =>[
     'id' => $user->getId(),
      'email' => $user->getEmail(),
    ]
 ];
 $jwt = JWT::encode($token, $key);

Toàn bộ mã nguồn tham khảo tại đây https://github.com/lackky/api/blob/master/app/controllers/AuthController.php#L45-L59, cơ bản việc dùng thư viện bạn chỉ việc gọi hàm JWT::encode còn biến token ở trên do tôi chỉ muốn có thông tin userId và email nên tôi chỉ thêm 2 giá trị đó vào, nếu bạn nào muốn có thêm username, thì chỉ việc thêm vào trường(field) username.

Thời gian hiệu lực của token, tuỳ thuộc vào ứng dụng của bạn như trong ví dụ trên chúng tôi cho thời gian tồn tại token là 1 năm thông qua biến $expires

Demo

Chúng ta hãy gửi một post request như sau tới url 127.0.0.1/auth

auth.json
{
	"email" : "[email protected]",
	"password": "lackkylove"
}
curl -d auth.json -H "Content-Type: application/json" -X POST 127.0.0.1/auth

Bạn sẽ nhận được kết quả như sau:

{
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJcL2F1dGgiLCJpYXQiOjE1ODEyMzA3MDQsImV4cCI6MTYxMjc2NjcwNCwiZGF0YSI6eyJpZCI6IjQiLCJlbWFpbCI6InVzZXIwMUBsYWNra3kuY29tIn19.d0_QtK6bec9gw7GV7vOmyGufi_Pd8OnGdVVd1_AmdWk",
    "message": "Successful Login",
    "expires": 1612766704
}

Chúc mừng bạn đã sữ dụng thành công JWT, để check coi mã token có đúng hay không bạn có thể lên trang https://jwt.io/ sau đó dán đoạn code token vào thì có dạng như sau:



Việc lấy thông tin user cũng rất đơn giản. Chúng ta chỉ cần truyền thêm token đã nhận được sau khi login để xác thực và nhận về thông tin user.

try {
   $decoded = JWT::decode($jwt[1], $key, ['HS256']);
   // @TODO verify
  $app->cookies->set('auth', $decoded);
} catch (\Exception $e) {
  return $this->sendError($app);
}

Bạn có thể xem chi tiết cách dùng nó tại đây https://github.com/lackky/api/blob/master/app/library/Auth/AuthenticationMiddleware.php#L45-L53, Nếu bạn truyền sai token, thì sẽ nhận được kết quả token_invalid như thế này:

{ "token_invalida"}

Chúng ta có một vấn đề nữa đó làm thế nào để xoá token này, khi người dùng logout chẵng hạn, chúng ta sẽ thảo luận về đề này ở bài viết kế tiếp.

Kết luận

Trong hướng dẫn này chúng tôi đã chỉ bạn cách dùng JWT với Phalcon PHP khá là đơn giản phải không nào, nếu bạn nào có bất kỳ câu hỏi nào hãy để bình luận bên dưới chúng tôi sẽ giải đáp.

Leave a Reply

Your email address will not be published. Required fields are marked *