LocalStorage và Cookies - chọn cái nào để lưu JWT Tokens hiệu quả và an toàn?

JWT Tokens là một cách thức lưu trữ thông tin xác thực hiệu quả, nhưng làm cách nào để chúng ta có thể giúp chúng an toàn hơn? Có 2 cách thường dùng để lưu trữ JWT Tokens là LocalStorage và Cookies. Bây giờ chúng ta sẽ bắt đầu "mổ xẻ" các ưu - nhược điểm của mỗi loại nhé.
LocalStorage và Cookies - chọn cái nào để lưu JWT Tokens hiệu quả và an toàn?
LocalStorage và Cookies - chọn cái nào để lưu JWT Tokens hiệu quả và an toàn?

Tóm tắt đơn giản về Access Token và Refresh Token

Access Token thường là các JWT Tokens tồn tại trong một khoảng thời gian ngắn, được tạo ra từ phía server, và được server yêu cầu đính kèm trong mỗi Http Request để phía server xác thực người dùng.

Refresh Token thường là các chuỗi string đặc thù nào đó được lưu trong database của server, được sử dụng để tạo ra các Access Token mới mỗi khi chúng hết hạn.

 

Mỗi khi nhận được token rồi thì lưu chúng ở đâu?

Có 2 cách lưu trữ Access Token phổ biến, đó là localStorageCookies.

Khá nhiều cuộc tranh luận đã nổ ra nhằm xác định cái nào tốt hơn, tuy nhiên hầu hết mọi người đều cho rằng Cookies tốt hơn vì chúng an toàn hơn.

 

Local Storage

Ưu điểm: tiện lợi.

Đây là một tính năng hầu hết các trình duyệt đều hỗ trợ mà không phải cài gì thêm. Nếu bạn không có phần backend và phải dựa vào API của bên thứ 3 thì bạn không thể yêu cầu người ta đặt Cookies cụ thể cho website của mình. 

Nó làm việc với các API bằng cách đặt Access Token vào Request Header như ví dụ sau đây:

Authorization: `Bearer ${accessToken}`

Nhược điểm: dễ bị tấn công XSS.

Cross-Site Scripting (XSS) là một trong những kĩ thuật tấn công phổ biến nhất hiện nay. Kỹ thuật XSS được thực hiện dựa trên việc chèn các đoạn script nguy hiểm vào trong source code ứng dụng web, nhằm thực thi các đoạn mã độc Javascript để chiếm phiên đăng nhập của người dùng.

Một cuộc tấn công XSS có thể xảy ra từ mã JavaScript của bên thứ ba có trong trang web của bạn, như React, Vue, jQuery, Google Analytics, v.v.

Ở thời điểm người người xài js, nhà nhà xài js như hiện tại, hầu như không thể không đưa bất kỳ thư viện bên thứ ba nào vào trang web của bạn.

Hacker có thể chạy 1 đoạn js kiểu: localStorage.get('token') trên site của mình để lấy đc token, sau đó gửi ajax tới server của hacker.

Kiểu như này:

<script src="https://cdn.awesomejs-site.com/jquery.min.js"></script>

Có trời mới biết mấy cái thư viện bên thứ 3 như vầy có cái gì trong đó. Đến đây chắc bạn cũng biết mất token thì nguy hiểm như thế nào rồi chứ?

 

Vậy bạn có bao giờ tự hỏi, tại sao các trang dạy coding online lại thường sử dụng localStorage mặc dù biết nó không bảo mật?

Đơn giản là việc sử dụng localStorage sẽ tiện dụng và dễ dàng hơn cho họ khi demo.

Hầu hết khóa học ứng dụng các Javascript framework đều chỉ tập trung vào concept và cách triển khai chúng mà thôi, và khi ứng dụng thực tế sẽ có đôi điểm khác biệt.

Và nếu như cái gì cũng chỉ hết cho bạn rồi thì làm sao họ bán được các khóa học nâng cao hơn, phải không nào? =)))

 

Cookies

Ưu điểm: Không thể truy cập httpOnlysecure cookie qua JavaScript, do đó nó không dễ bị tấn công XSS như localStorage.

Nếu bạn đang sử dụng httpOnlysecure cookie, hacker không thể truy cập cookie của bạn bằng JavaScript. Điều này có nghĩa là, ngay cả khi hacker có thể chạy javascript trên trang web của bạn, chúng cũng không thể đọc các Access Token của bạn từ cookie.

Cookies tự động được gửi trong mọi yêu cầu HTTP đến máy chủ của bạn.

Nhược điểm: Tùy thuộc vào các use case cụ thể mà bạn có thể không lưu trữ được Access Token của mình vào trong cookie.

Cookie có giới hạn kích thước là 4KB. Do đó, nếu bạn đang sử dụng một JWT Access Token lớn, thì việc lưu trữ trong cookie không phải là một lựa chọn đúng đắn.

Có những trường hợp bạn không thể chia sẻ cookie với máy chủ API của mình hoặc API yêu cầu bạn đặt Access Token vào trong Authorization Header. Trong trường hợp này, bạn sẽ không thể sử dụng cookie để lưu trữ Access Token của mình.

 

LocalStorage và tấn công XSS

localStorage dễ bị tấn công vì nó có thể dễ dàng truy cập bằng JavaScript và hacker có thể lấy Access Token của bạn và sử dụng nó sau này.

Tuy nhiên, mặc dù không thể truy cập cookie gắn cờ httpOnly bằng JavaScript, điều này không có nghĩa là bằng cách sử dụng cookie, bạn sẽ an toàn trước các cuộc tấn công XSS liên quan đến Access Token của mình.

Nếu kẻ tấn công có thể chạy JavaScript trong ứng dụng của bạn, thì chúng chỉ có thể gửi một HTTP Request đến server của bạn và điều đó sẽ tự động gửi kèm cookie của bạn. Nó chỉ kém thuận tiện hơn cho kẻ tấn công vì họ không thể đọc nội dung Access Token mặc dù họ hiếm khi phải làm vậy.

Việc hacker phải tấn công bằng cách sử dụng trình duyệt của nạn nhân (bằng cách gửi HTTP Request) đương nhiên sẽ tốt hơn là hacker có thể sử dụng máy của chính hacker để tấn công bạn bằng các phương thức khác.

 

Cookies và tấn công CSRF

CSRF (Cross-site Request Forgery) là một kiểu tấn công lợi dụng sự tin tưởng của người dùng. Chúng lừa nạn nhân gửi đi các HTTP Request không mong muốn đến website nào đó.

Khi gửi một HTTP Request (hợp pháp hoặc không hợp pháp), trình duyệt của nạn nhân sẽ gửi kèm theo các Cookies Header. Các cookies thường được dùng để lưu trữ một session nhằm định danh người dùng giúp họ không phải xác thực lại mỗi khi thực hiện Request.

Nếu phiên làm việc đã xác thực của nạn nhân được lưu trữ trong một Cookie vẫn còn hiệu lực, và website nạn nhân bảo mật kém và dễ bị tấn công CSRF, kẻ tấn công có thể sử dụng CSRF để chạy bất cứ Request nào với website nạn nhân mà website nạn nhân không biết được các Request này có hợp pháp hay không.

Một lỗ hổng CSRF sẽ ảnh hưởng đến các quyền của người dùng ví dụ như quản trị viên, kết quả là chúng truy cập được đầy đủ quyền hạn trên website nạn nhân.

Một ví dụ về kịch bản tấn công CSRF

  • Người dùng Trung Nghĩa truy cập 1 diễn đàn yêu thích của mình như thường lệ. Một người dùng khác, Duy PT - đăng tải một bài viết lên diễn đàn. Giả sử rằng Duy PT có ý đồ không tốt và hắn ta muốn xóa đi một dự án quan trọng nào đó mà Trung Nghĩa đang làm.
  • Duy PT sẽ tạo một bài viết trên diễn đàn, trong đó có chèn thêm một đoạn code như sau:
<img width="0" height="0" src="www.nghiattran-sample.com/project/1/destroy"/>

Thêm vào đó thẻ img sử dụng trong trường hợp này có kích thước 0x0 pixel và người dùng sẽ không thể thấy được.

Giả sử Trung Nghĩa đang truy cập vào tài khoản của mình ở www.nghiattran-sample.com và chưa thực hiện logout để kết thúc session. Bằng việc xem bài post bên diễn đàn mà Duy PT đăng lên, trình duyệt của Trung Nghĩa sẽ đọc thẻ img và cố gắng load ảnh từ www.nghiatran-sample.com, do đó sẽ gửi câu lệnh xóa đến địa chỉ này.

Ứng dụng web ở www.nghiatran-sample.com sẽ chứng thực Trung Nghĩa dựa trên cookie và sẽ xóa project với ID là 1. Nó sẽ trả về trang kết quả mà không phải là ảnh, do đó trình duyệt sẽ không hiển thị ảnh.

 

Kết luận

Mặc dù Cookies vẫn tồn tại nhiều khuyết điểm, nhưng bạn nên ưu tiên sử dụng Cookies bất cứ khi nào có thể.

  • Cả localStoragecookie đều dễ bị tấn công XSS nhưng kẻ tấn công sẽ khó thực hiện cuộc tấn công hơn khi bạn đang sử dụng Cookie với cờ httpOnly.
  • Cookie dễ bị tấn công CSRF nhưng nó có thể được giảm thiểu bằng cách sử dụng cờ sameSite, secure và Anti CSRF Token. Nếu bạn sử dụng một số framework như Laravel thì nó đã có sẵn cơ chế xác thực CSRF.

Bạn có thể tham khảo các khuyến cáo về bảo mật của tổ chức OWASP.ORG tại HTML5 Security Cheat Sheet.

Ở đây có một vài khuyến cáo về việc sử dụng Cookies thay cho Local Storage để lưu trữ các thông tin quan trọng.

Pay extra attention to "localStorage.getItem" and "setItem" calls implemented in HTML5 page. It helps in detecting when developers build solutions that put sensitive information in local storage, which is a bad practice.

Do not store session identifiers in local storage as the data is always accessible by JavaScript. Cookies can mitigate this risk using the httpOnly flag.

 

Bài viết đến đây là kết thúc rồi. Cám ơn các bạn đã theo dõi :D

Comments

Mục lục

Bài viết nổi bật

PHP là ngôn ngữ được sử dụng rộng rãi nhất trên thế giới trong lập trình web. Nó cũng bị ghét nhất. Nhưng tại sao nhiều developer lại ghét nó đến vậy? Hôm nay chúng ta hãy cùng tìm hiểu lý do xem chúng có thuyết phục không nhé ^_^
Ở bài viết này mình sẽ hướng dẫn bạn bắt đầu xây dựng một ứng dụng HMVC với Laravel, và tận dụng sức mạnh của Composer khi quản lí modules.
Trong quá trình làm việc với Laravel Eloquent ORM, chắc hẳn các bạn từng thực hiện khá nhiều tác vụ lặp đi lặp lại - mà bạn không hề biết Laravel đã hỗ trợ sẵn. Thông qua vài mẹo và thủ thuật nhỏ trong bài viết này, mình hi vọng sẽ giúp các bạn giảm bớt sự phức tạp khi viết code cũng như bớt nhàm chán khi thực hiện các tác vụ lặp đi lặp lại theo cách thông thường.
Có khá nhiều bạn đã yêu cầu mình một bài viết về Repository Design Pattern. Vậy mục đích của nó là gì? Nó có thực sự cần thiết cho ứng dụng của bạn hay không? Những điểm mạnh, điểm yếu của nó là gì? Chúng ta cùng đi sâu tìm hiểu qua bài viết này nhé.
Như đã được thông báo vào năm 2018, React Native đã và đang được đội ngũ phát triển của Facebook nỗ lực tái kiến trúc nhằm giúp nền tảng này trở nên mạnh mẽ hơn và giải quyết một số vấn đề phổ biến mà các nhà phát triển đã gặp phải trong vài năm qua.

Related posts

Redux là một framework quản lý state dựa trên ý tưởng: tất cả các state của ứng dụng sẽ được lưu xuống một global state và sử dụng các reducer function để tương tác với chúng.
Styled-Components là một thư viện giúp bạn tổ chức và quản lý styles trong các dự án sử dụng React tuân theo đề xuất từ Facebook.
Decorators trong Typescript
484
Các bạn dev nào từng làm Angular chắc sẽ khá quen thuộc với Decorators đúng không? Nhưng bạn thật sự đã hiểu rõ về nó hay chưa? Chúng ta hãy cùng nhau ôn bài một tí nhé ^_^
PHP là ngôn ngữ được sử dụng rộng rãi nhất trên thế giới trong lập trình web. Nó cũng bị ghét nhất. Nhưng tại sao nhiều developer lại ghét nó đến vậy? Hôm nay chúng ta hãy cùng tìm hiểu lý do xem chúng có thuyết phục không nhé ^_^
Là developer, chúng ta luôn tìm cách để tiết kiệm thời gian cho các dự án của mình. Đó là lý do tại sao các thư viện được tạo ra để giảm bớt các khó khăn khi triển khai những thứ lặp đi lặp lại. Với các frontend framework như React, việc chia sẻ chức năng chung cho các dự án khác nhau trở nên dễ dàng hơn bao giờ hết.
Snappy là một thư viện PHP cho phép tạo các thumnails, snapshots và PDF từ URL hoặc trang HTML. Tác giả Barryvdh đã viết thư viện Laravel Snappy giúp việc tích hợp với Laravel dễ dàng hơn.
Bạn có thể sử dụng tính năng kiểm tra kiểu dữ liệu của Typescript để xác định các interface cho các components, nhằm chắc chắn rằng component của bạn chỉ nhận được các thông tin đầu vào chính xác.
Bài viết này cung cấp một cái nhìn tổng quan ngắn gọn về TypeScript, tập trung vào hệ thống kiểu dữ liệu của nó.
Hooks là một tính năng bổ sung mới từ React 16.8 trở đi. Chúng cho phép bạn sử dụng State và các tính năng khác của React mà không cần viết một class.
Giới thiệu series react
326
Một vài kiến thức cơ bản cũng như nâng cao mà mình sẽ tổng hợp lại trong quá trình làm việc cũng như self learning
Flexbox toàn tập
1259
Bài viết này sẽ hướng dẫn cho bạn mọi thứ về flexbox, bao gồm tất cả các thuộc tính cho phần tử cha (flex container) và phần tử con (flex items).
Như đã được thông báo vào năm 2018, React Native đã và đang được đội ngũ phát triển của Facebook nỗ lực tái kiến trúc nhằm giúp nền tảng này trở nên mạnh mẽ hơn và giải quyết một số vấn đề phổ biến mà các nhà phát triển đã gặp phải trong vài năm qua.

Tin mới nhất

Redux là một framework quản lý state dựa trên ý tưởng: tất cả các state của ứng dụng sẽ được lưu xuống một global state và sử dụng các reducer function để tương tác với chúng.
Styled-Components là một thư viện giúp bạn tổ chức và quản lý styles trong các dự án sử dụng React tuân theo đề xuất từ Facebook.
Decorators trong Typescript
484
Các bạn dev nào từng làm Angular chắc sẽ khá quen thuộc với Decorators đúng không? Nhưng bạn thật sự đã hiểu rõ về nó hay chưa? Chúng ta hãy cùng nhau ôn bài một tí nhé ^_^
PHP là ngôn ngữ được sử dụng rộng rãi nhất trên thế giới trong lập trình web. Nó cũng bị ghét nhất. Nhưng tại sao nhiều developer lại ghét nó đến vậy? Hôm nay chúng ta hãy cùng tìm hiểu lý do xem chúng có thuyết phục không nhé ^_^
Là developer, chúng ta luôn tìm cách để tiết kiệm thời gian cho các dự án của mình. Đó là lý do tại sao các thư viện được tạo ra để giảm bớt các khó khăn khi triển khai những thứ lặp đi lặp lại. Với các frontend framework như React, việc chia sẻ chức năng chung cho các dự án khác nhau trở nên dễ dàng hơn bao giờ hết.
Snappy là một thư viện PHP cho phép tạo các thumnails, snapshots và PDF từ URL hoặc trang HTML. Tác giả Barryvdh đã viết thư viện Laravel Snappy giúp việc tích hợp với Laravel dễ dàng hơn.
IRAC (Issue - Rule - Analysis - Conclusion) là một phương pháp phổ biến và quen thuộc với sinh viên luật và dân luật nói chung. Cá nhân mình thấy phương pháp này khá hay và hoàn toàn có thể áp dụng vào bất cứ công việc hoặc ngành nghề nào.
Bạn có thể sử dụng tính năng kiểm tra kiểu dữ liệu của Typescript để xác định các interface cho các components, nhằm chắc chắn rằng component của bạn chỉ nhận được các thông tin đầu vào chính xác.
Bài viết này cung cấp một cái nhìn tổng quan ngắn gọn về TypeScript, tập trung vào hệ thống kiểu dữ liệu của nó.
Hooks là một tính năng bổ sung mới từ React 16.8 trở đi. Chúng cho phép bạn sử dụng State và các tính năng khác của React mà không cần viết một class.
Giới thiệu series react
326
Một vài kiến thức cơ bản cũng như nâng cao mà mình sẽ tổng hợp lại trong quá trình làm việc cũng như self learning
JWT Tokens là một cách thức lưu trữ thông tin xác thực hiệu quả, nhưng làm cách nào để chúng ta có thể giúp chúng an toàn hơn? Có 2 cách thường dùng để lưu trữ JWT Tokens là LocalStorage và Cookies. Bây giờ chúng ta sẽ bắt đầu "mổ xẻ" các ưu - nhược điểm của mỗi loại nhé.
Redux là một framework quản lý state dựa trên ý tưởng: tất cả các state của ứng dụng sẽ được lưu xuống một global state và sử dụng các reducer function để tương tác với chúng.
Styled-Components là một thư viện giúp bạn tổ chức và quản lý styles trong các dự án sử dụng React tuân theo đề xuất từ Facebook.
Decorators trong Typescript
484
Các bạn dev nào từng làm Angular chắc sẽ khá quen thuộc với Decorators đúng không? Nhưng bạn thật sự đã hiểu rõ về nó hay chưa? Chúng ta hãy cùng nhau ôn bài một tí nhé ^_^
PHP là ngôn ngữ được sử dụng rộng rãi nhất trên thế giới trong lập trình web. Nó cũng bị ghét nhất. Nhưng tại sao nhiều developer lại ghét nó đến vậy? Hôm nay chúng ta hãy cùng tìm hiểu lý do xem chúng có thuyết phục không nhé ^_^
Là developer, chúng ta luôn tìm cách để tiết kiệm thời gian cho các dự án của mình. Đó là lý do tại sao các thư viện được tạo ra để giảm bớt các khó khăn khi triển khai những thứ lặp đi lặp lại. Với các frontend framework như React, việc chia sẻ chức năng chung cho các dự án khác nhau trở nên dễ dàng hơn bao giờ hết.