OAuth PKCE cho ứng dụng thu thập: verifier sai bị chặn
OAuth PKCE cho ứng dụng thu thập là lớp bảo vệ bước đổi authorization code lấy token, để ai chặn được code trên đường chuyển hướng cũng không dùng được nó. Ứng dụng giữ một chuỗi bí mật gọi là code verifier, chỉ gửi bản băm của nó lúc xin quyền, rồi gửi bản gốc lúc đổi code. ProxyVN dựng máy chủ ủy quyền lab theo RFC 7636, chạy client Authlib thật qua tám ca và tìm ra một chỗ thư viện im lặng bỏ PKCE.
OAuth PKCE cho ứng dụng thu thập: mục tiêu và phạm vi không lặp
Phần này chốt bài toán, đầu ra và giới hạn.
Bài toán cần giải
Một ứng dụng desktop thu thập dữ liệu từ API của đối tác, chạy bằng tài khoản của từng người dùng. Ứng dụng không giữ được client secret, vì ai tải ứng dụng về cũng đọc được. Luồng authorization code chuyển code qua một địa chỉ chuyển hướng cục bộ. Nếu một chương trình khác trên máy chặn được code, nó đổi được token. PKCE ngăn chuyện này.
Đầu ra nghiệm thu
Đầu ra là sequence trao code đầy đủ: tạo verifier, tính challenge, gửi authorization request kèm state, nhận code, đổi code bằng verifier. Kèm theo là ca verifier sai bị máy chủ từ chối, cùng các ca verifier quá ngắn, sai state, không gửi PKCE, hạ xuống plain và kẻ chặn code.
Ranh giới với bài device flow
Bài device flow trong cụm này dành cho CLI không có trình duyệt, dùng polling và mã nhập tay. PKCE dành cho ứng dụng có trình duyệt và có địa chỉ chuyển hướng. Hai luồng không thay nhau. Bài này cũng không lặp lại cách gắn token vào request của thư viện HTTP.
Không thu token của người khác
PKCE bảo vệ người dùng của chính ứng dụng. Lab chỉ có một người dùng giả, trên một máy chủ ủy quyền tự viết. Không có bước nào trong bài dùng để lấy token của tài khoản người khác. Ca kẻ chặn code là để chứng minh PKCE chặn được, không phải hướng dẫn chặn.
Giới hạn của lab
Nói rõ ngay. Lab không dùng nhà cung cấp OAuth thật. ProxyVN viết máy chủ ủy quyền theo RFC 7636 trên cổng 9486. Bước người dùng đăng nhập và đồng ý được bỏ qua: máy chủ tự cấp code cho người dùng lab. Client là Authlib 1.9.4 thật, gửi request bằng requests 2.34.2.
Thứ gì theo RFC, thứ gì do lab đặt
Độ dài verifier, tập ký tự, phép băm S256, mã lỗi invalid_grant khi verifier không khớp lấy từ RFC. Chính sách bắt buộc PKCE, không nhận plain và không hủy code khi verifier sai là lựa chọn của máy chủ lab. Máy chủ thật có thể chọn khác, bài ghi rõ ở từng chỗ.
Ai nên đọc bài này
Người viết ứng dụng desktop, ứng dụng dòng lệnh có mở trình duyệt, hay ứng dụng web không có backend riêng, cần token OAuth của người dùng. Người dùng thư viện OAuth và muốn biết thư viện có thật sự gửi PKCE không. Người quản trị máy chủ ủy quyền cần biết nên bật chính sách gì.
OAuth PKCE cho ứng dụng thu thập: bảo vệ authorization code bằng verifier và challenge
Phần này tóm tắt RFC 7636.
Tấn công mà PKCE chặn
RFC 7636 mô tả tấn công chặn authorization code với public client. Một ứng dụng độc hại trên cùng thiết bị đăng ký cùng địa chỉ chuyển hướng, nhận code thay ứng dụng thật, rồi đổi code lấy token. Ứng dụng không có client secret nên máy chủ không phân biệt được ai đang đổi.
Ý tưởng chính
Trước mỗi lần xin quyền, client tạo một verifier ngẫu nhiên. Nó gửi challenge, là verifier đã biến đổi, trong authorization request. Khi đổi code, nó gửi verifier gốc. Máy chủ biến đổi verifier rồi so với challenge đã lưu. Kẻ chặn được code không có verifier nên không đổi được.
Verifier
RFC định nghĩa code verifier là chuỗi ngẫu nhiên có entropy cao, dùng các ký tự unreserved: chữ hoa, chữ thường, chữ số, gạch ngang, chấm, gạch dưới và dấu ngã. Độ dài tối thiểu 43 ký tự, tối đa 128 ký tự.
Challenge
RFC định nghĩa hai phương thức biến đổi. Plain: challenge bằng chính verifier. S256: challenge là SHA-256 của verifier, mã hóa base64url không có dấu bằng ở cuối. RFC nêu client có khả năng dùng S256 thì phải dùng S256. Plain chỉ dành cho trường hợp không thể dùng S256 vì lý do kỹ thuật.
Ví dụ trong RFC
Phụ lục B của RFC đưa một ví dụ cụ thể. Lab tính lại và khớp.
verifier = dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
challenge = E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
RFC 7636 Appendix B: True
Chạy lại ví dụ này là cách nhanh nhất để kiểm hàm S256 tự viết.
Tham số mới
Authorization request thêm hai tham số: code_challenge và code_challenge_method. Token request thêm code_verifier. Không có tham số nào khác thay đổi so với luồng authorization code thường.
Máy chủ xử lý thế nào
RFC nêu máy chủ lưu challenge và phương thức cùng với code. Khi nhận token request, máy chủ biến đổi verifier theo phương thức đã lưu, so với challenge. Khớp thì cấp token. Không khớp thì trả lỗi invalid_grant như với code sai.
Máy chủ bắt buộc PKCE
RFC cho phép máy chủ yêu cầu public client dùng PKCE. Nếu bắt buộc mà request không có challenge, máy chủ trả lỗi invalid_request về địa chỉ chuyển hướng. Lab bật chính sách này. Phần sau cho thấy vì sao không bật là nguy hiểm.
Bước |
Client gửi |
Máy chủ lưu hoặc kiểm |
|---|---|---|
Xin quyền |
code_challenge, method, state |
Lưu challenge, method cùng code |
Chuyển hướng |
Trả code, state |
|
Đổi code |
code, code_verifier |
Băm verifier, so challenge |
OAuth PKCE cho ứng dụng thu thập: tạo verifier và challenge theo phương thức S256
Phần này tạo cặp verifier và challenge, kiểm độ dài.
Tạo verifier
Lab dùng hàm generate_token của Authlib với độ dài 48. Hàm trả chuỗi chữ và số ngẫu nhiên, nằm trong tập ký tự cho phép.
from authlib.common.security import generate_token
v = generate_token(48)
Có thể dùng secrets.token_urlsafe của Python. Hàm này sinh ký tự trong bảng base64url, cũng nằm trong tập unreserved.
Tính challenge S256
Hàm S256 tự viết của lab: băm SHA-256 verifier dạng ASCII, mã hóa base64url, bỏ dấu bằng.
import hashlib, base64
def s256(v):
d = hashlib.sha256(v.encode("ascii")).digest()
return base64.urlsafe_b64encode(d).rstrip(b"=").decode()
Challenge S256 luôn dài 43 ký tự, bất kể verifier dài bao nhiêu. Lab in verifier 48 ký tự và challenge 43 ký tự.
Lỗi hay gặp khi tự viết
Ba lỗi hay gặp: dùng base64 thường thay vì base64url, quên bỏ dấu bằng, băm chuỗi hex của SHA-256 thay vì byte. Mỗi lỗi cho một challenge khác, máy chủ trả invalid_grant mà không nói vì sao. Kiểm bằng ví dụ trong RFC trước khi gửi request thật.
Verifier mới cho mỗi lần
Mỗi authorization request cần một verifier mới. Dùng lại verifier cũ làm mất ý nghĩa, vì challenge đã lộ trong URL lần trước. Lab tạo verifier mới cho mỗi ca.
Giữ verifier ở đâu
Verifier chỉ cần sống từ lúc tạo authorization URL tới lúc đổi code, thường vài chục giây. Ứng dụng desktop giữ trong bộ nhớ là đủ. Ứng dụng web không có backend giữ trong session storage của tab. Không ghi verifier ra tệp hay log.
Độ dài nên chọn
RFC cho phép 43 tới 128 ký tự. Chọn khoảng 48 tới 64 là đủ entropy và không làm URL hay body quá dài. Lab dùng 48. Độ dài không ảnh hưởng challenge S256, chỉ ảnh hưởng token request.
OAuth PKCE cho ứng dụng thu thập: gắn challenge vào authorization request và giữ state
Phần này dựng authorization URL và nói về state.
Tạo session Authlib
Session Authlib nhận client_id, redirect_uri, scope và code_challenge_method.
from authlib.integrations.requests_client import OAuth2Session
sess = OAuth2Session("app-thu-thap", redirect_uri="http://127.0.0.1:9499/callback",
scope="read:api", code_challenge_method="S256")
url, state = sess.create_authorization_url(AS_URL + "/authorize", code_verifier=v)
Địa chỉ chuyển hướng là cổng cục bộ, kiểu thường dùng cho ứng dụng desktop.
URL có gì

URL chỉ mang challenge
Lab đọc lại các tham số trong URL vừa tạo.
authorize URL co: {'code_challenge': 'b-W4nB4O__oR...', 'code_challenge_method': 'S256', 'state': 'RESggkzHZVHI...'}
Verifier không có trong URL. Chỉ challenge và phương thức đi ra ngoài.
State là gì
State là chuỗi ngẫu nhiên client gửi đi và phải nhận lại nguyên vẹn khi chuyển hướng về. Nó chống giả mạo request xuyên trang, một vấn đề khác với chặn code. PKCE không thay state, state không thay PKCE.
Ca sai state
Lab sửa state trong địa chỉ chuyển hướng trước khi đưa cho Authlib. Authlib từ chối ngay, không gửi token request.
ket qua: MismatchingStateException mismatching_state: CSRF Warning! State not equal in request and response.
log AS: [('authorize', 'code', 'S256')]
Log máy chủ chỉ có bước authorize, không có bước token. Client tự chặn trước khi tới máy chủ.
Nhận code từ chuyển hướng
Máy chủ lab trả mã 302 với Location chứa code và state. Ứng dụng desktop thật mở một máy chủ HTTP nhỏ ở cổng chuyển hướng để nhận request này. Lab đọc thẳng header Location thay cho bước đó.
Địa chỉ chuyển hướng phải khớp
Khi đổi code, client gửi lại redirect_uri. Máy chủ lab so với redirect_uri lúc xin quyền, khác thì trả invalid_grant. Đây là kiểm tra của OAuth thường, giữ nguyên khi có PKCE.
OAuth PKCE cho ứng dụng thu thập: đổi authorization code bằng đúng verifier
Phần này là ca thành công và ca dùng lại code.
Ca A: đúng verifier
Authlib gửi code cùng verifier tới token endpoint. Máy chủ băm verifier, so khớp, cấp token.
tok = sess.fetch_token(AS_URL + "/token", authorization_response=cb,
state=state, code_verifier=v)
# ket qua: TOKEN Bearer | verifier gui di dai 48
Log máy chủ: một bước authorize trả code, một bước token trả token, cả hai với phương thức S256.
Sequence trao code

Sequence trao code
Bảng dưới là sequence của ca A, ghép từ log client và máy chủ lab.
Bước |
Bên |
Gửi |
Nhận |
|---|---|---|---|
1 |
Client |
Tạo verifier 48 ký tự |
|
2 |
Client |
Tính challenge S256 43 ký tự |
|
3 |
Client tới AS |
GET authorize với challenge, method, state |
302 với code, state |
4 |
Client |
So state |
Khớp |
5 |
Client tới AS |
POST token với code, verifier |
200 với token |
6 |
Client tới AS |
POST token lần nữa, cùng code |
400 invalid_grant |
Dùng lại code
Lab gửi lại đúng code và verifier lần thứ hai. Máy chủ trả invalid_grant với lý do code đã dùng. Code chỉ dùng một lần, kể cả khi verifier đúng.
Token không chứa verifier
Phản hồi token chỉ có access_token, token_type, expires_in. Verifier đã xong việc ngay khi máy chủ kiểm. Ứng dụng xóa verifier khỏi bộ nhớ sau bước này.
Kiểm phản hồi token
Sau khi nhận token, ứng dụng kiểm token_type là Bearer và có expires_in. Ghi lại thời điểm hết hạn theo đồng hồ của ứng dụng. Nếu phản hồi có scope, so với scope đã xin, vì máy chủ có quyền cấp ít hơn. Thiếu quyền thì báo sớm, đừng đợi tới lúc gọi API mới lỗi.
Thời hạn của code
Máy chủ lab cho code sống 60 giây. Người dùng đồng ý xong mà ứng dụng chậm đổi code quá hạn thì phải làm lại từ đầu, với verifier mới. Lab không thử ca hết hạn, vì code được đổi ngay.
OAuth PKCE cho ứng dụng thu thập: thử verifier sai trên authorization server lab
Phần này đi qua các ca lỗi.
Bắt lỗi từ Authlib
Authlib ném OAuthError khi token endpoint trả lỗi, với thuộc tính error và description. Ứng dụng bắt ngoại lệ này, đọc error để chọn thông báo. Với invalid_grant, thông báo cho người dùng là phiên đăng nhập không hợp lệ, hãy thử lại. Không hiện mô tả kỹ thuật cho người dùng cuối.
Ca B: verifier sai
Client gửi một verifier khác, đúng định dạng, đúng độ dài. Máy chủ trả invalid_grant.
ket qua: OAuthError invalid_grant: code_verifier khong khop
Đây là phép thử nghiệm thu chính của bài: có code mà không có đúng verifier thì không đổi được. Máy chủ không cho biết verifier sai ở ký tự nào, và không nên cho biết.
Ca C: verifier quá ngắn
Client gửi verifier sáu ký tự. Máy chủ lab trả invalid_request với mô tả độ dài phải từ 43 tới 128. Máy chủ lab kiểm định dạng trước khi so challenge, nên lỗi rõ ràng hơn. Máy chủ thật có thể chỉ trả invalid_grant chung.
Ca E: không gửi PKCE
Client tạo authorization URL không có verifier. URL không có challenge. Máy chủ lab, vì bắt buộc PKCE, trả lỗi invalid_request về địa chỉ chuyển hướng, không cấp code.
AS tra ve: error=invalid_request&error_description=code_challenge bat buoc, chi nhan S256
Lỗi trả về địa chỉ chuyển hướng
Ở ca E và F, máy chủ không hiện trang lỗi mà chuyển hướng về ứng dụng với tham số error và error_description, kèm state. Ứng dụng phải đọc tham số error trước khi tìm code. Một ứng dụng chỉ tìm code sẽ báo lỗi khó hiểu kiểu không có code, trong khi lý do thật nằm ngay trong URL.
So state cả khi có lỗi
Phản hồi lỗi vẫn mang state. Ứng dụng nên so state trước, rồi mới đọc error. Nếu state sai, coi cả phản hồi là không đáng tin, kể cả nội dung lỗi. Cách làm này giống với khi nhận code.
Ca F: đặt phương thức plain
Client đặt code_challenge_method là plain. URL tạo ra không có challenge lẫn phương thức. Máy chủ lab từ chối như ca E.
authorize URL co: {'state': 'InoeBjp4J719...'}
Authlib 1.9.4 chỉ hỗ trợ S256. Với phương thức khác, nó im lặng không gửi gì, không ném lỗi.
Bẫy của thư viện

Thư viện im lặng
Đây là phát hiện quan trọng nhất của lab. Đọc mã nguồn Authlib 1.9.4, hàm tạo authorization URL chỉ thêm challenge khi phương thức là S256. Tài liệu của thư viện ghi chỉ hỗ trợ S256, nhưng không báo lỗi khi đặt khác. Ứng dụng tưởng đang dùng PKCE, thật ra không gửi gì.
Ca G: máy chủ không bắt buộc PKCE
Lab tắt chính sách bắt buộc PKCE trên máy chủ, rồi chạy lại client đặt plain. Máy chủ cấp code. Một request đổi code không có verifier nhận token.
== G AS khong bat buoc PKCE + client dat plain: URL co code_challenge? False
ke chan code doi KHONG verifier: 200 ['access_token', 'token_type', 'expires_in']
Kẻ chặn được code trong ca này đổi được token. Đây là đúng tấn công RFC 7636 mô tả.
Ca H: kẻ chặn code khi PKCE bật
Bật lại PKCE với S256. Một request khác lấy code và gửi verifier tự chế. Máy chủ trả invalid_grant. Ngay sau đó, ứng dụng thật đổi cùng code với verifier đúng và nhận token.
== H ke chan code, tu doi: 400 {'error': 'invalid_grant', 'error_description': 'code_verifier khong khop'}
app that doi sau do: 200 ['access_token', 'token_type', 'expires_in']
Máy chủ lab không hủy code khi verifier sai. Máy chủ thật có thể chọn hủy code sau lần sai đầu tiên.
Bảng kết quả
Ca |
Mô tả |
Kết quả |
Ai chặn |
|---|---|---|---|
A |
Đúng verifier S256 |
Token |
|
A' |
Dùng lại code |
invalid_grant |
Máy chủ |
B |
Verifier sai |
invalid_grant |
Máy chủ |
C |
Verifier 6 ký tự |
invalid_request |
Máy chủ |
D |
Sai state |
MismatchingStateException |
Client |
E |
Không gửi PKCE |
invalid_request |
Máy chủ |
F |
Đặt plain |
Không gửi challenge, invalid_request |
Máy chủ |
G |
Máy chủ không bắt buộc PKCE |
Token không cần verifier |
Không ai |
H |
Kẻ chặn code, PKCE bật |
invalid_grant |
Máy chủ |
OAuth PKCE cho ứng dụng thu thập: kiểm tra trong vận hành
Phần này nối các ca lab với việc kiểm một ứng dụng và một máy chủ thật.
Kiểm URL ứng dụng tạo ra
Cách nhanh nhất để biết ứng dụng có gửi PKCE không: in authorization URL ra một lần khi phát triển, xem có code_challenge và code_challenge_method bằng S256 không. Ca F cho thấy cấu hình nhìn đúng chưa chắc URL đúng. Thêm một test tự động kiểm hai tham số này.
Kiểm máy chủ có bắt buộc không

Kiểm máy chủ
Gửi một authorization request không có challenge tới máy chủ, với client thử. Nếu máy chủ vẫn cấp code, nó không bắt buộc PKCE. Với ứng dụng public client, đề nghị bên quản trị bật chính sách bắt buộc. Ca G cho thấy thiếu chính sách này thì PKCE chỉ còn là tùy chọn.
Kiểm máy chủ từ chối plain
Gửi request với phương thức plain. Máy chủ chặt chẽ sẽ từ chối. Nếu nhận, kẻ đọc được URL sẽ đọc được luôn verifier, vì plain không băm. Theo RFC, client có khả năng dùng S256 thì phải dùng S256.
Thư viện khác có thể khác
Bẫy ở ca F là của Authlib 1.9.4. Thư viện OAuth khác có thể hỗ trợ plain, có thể ném lỗi, có thể tự chọn S256. Đọc mã hoặc chạy test URL như trên cho đúng thư viện và phiên bản đang dùng. Ghi phiên bản vào tệp khóa phụ thuộc.
Log ở phía ứng dụng
Log của ứng dụng ghi thời điểm tạo URL, có PKCE hay không, kết quả đổi code. Không ghi verifier, không ghi code, không ghi token. Ghi độ dài verifier và vài ký tự đầu của challenge là đủ để gỡ lỗi.
Đổi code ngay
Ứng dụng đổi code ngay khi nhận chuyển hướng. Mỗi giây chờ là thêm thời gian cho ai đó thử code. Với PKCE, thử cũng vô ích nếu không có verifier, nhưng đổi ngay vẫn là thói quen tốt.
Địa chỉ chuyển hướng cục bộ
Ứng dụng desktop thường lắng nghe ở 127.0.0.1 với cổng ngẫu nhiên. Mở cổng xong, nhận một request, đóng cổng ngay. Cổng mở lâu là cơ hội cho chương trình khác nhận nhầm chuyển hướng. PKCE là lớp bảo vệ khi chuyện đó vẫn xảy ra.
OAuth PKCE cho ứng dụng thu thập: áp dụng theo từng loại ứng dụng
Phần này nói cách áp các ca lab vào ba kiểu ứng dụng thu thập hay gặp.
Ứng dụng desktop
Ứng dụng desktop mở trình duyệt mặc định tới authorization URL, đồng thời lắng nghe ở một cổng cục bộ. Verifier nằm trong bộ nhớ của tiến trình. Đây là kiểu RFC 7636 nhắm tới nhiều nhất, vì nhiều chương trình trên cùng máy có thể tranh nhau địa chỉ chuyển hướng. PKCE với S256 là bắt buộc.
Công cụ dòng lệnh có trình duyệt
Một công cụ dòng lệnh chạy trên máy cá nhân có thể mở trình duyệt như ứng dụng desktop. Khi chạy trên máy chủ không có trình duyệt, dùng device flow thay vì cố mở trình duyệt. Hai chế độ có thể nằm chung một công cụ, chọn theo môi trường.
Ứng dụng web chỉ có phần giao diện
Ứng dụng chỉ chạy trong trình duyệt không giữ được secret. Verifier lưu trong bộ nhớ của tab hoặc session storage, không lưu trong local storage dùng chung giữa các tab. Chuyển hướng về chính trang của ứng dụng, đọc code, đổi ngay.
Ứng dụng có backend
Nếu ứng dụng có backend riêng, backend giữ được client secret và là confidential client. RFC vẫn khuyến nghị dùng thêm PKCE. Verifier khi đó sinh và giữ ở backend, gắn với phiên của người dùng. Trình duyệt chỉ thấy challenge.
Một client_id cho mỗi loại
Đăng ký client riêng cho desktop, web và dòng lệnh. Mỗi client có địa chỉ chuyển hướng riêng và chính sách riêng. Nếu một loại bị lộ hay bị lạm dụng, chỉ cần thu hồi client đó. Lab chỉ có một client_id để gọn.
Ghép với scope tối thiểu
Ứng dụng thu thập thường chỉ cần quyền đọc. Xin scope đọc như lab, không xin quyền ghi. PKCE bảo vệ việc lấy token, scope giới hạn token làm được gì. Hai lớp này độc lập và nên dùng cùng nhau.
Lưu token sau khi đổi
Access token và refresh token lưu vào kho bí mật của hệ điều hành với ứng dụng desktop, vào bộ nhớ với ứng dụng web chỉ có giao diện. Không lưu trong tệp cấu hình chung. PKCE không bảo vệ token đã lưu, chỉ bảo vệ bước lấy token.
Khi người dùng đóng trình duyệt giữa chừng
Người dùng đóng tab trước khi đồng ý thì không có chuyển hướng. Ứng dụng desktop nên có thời hạn chờ, hết hạn thì đóng cổng và xóa verifier. Lần sau bắt đầu lại với verifier mới. Không giữ verifier cũ cho lần sau.
Thử nghiệm trên máy chủ lab trước
Máy chủ lab trong bài có thể chạy cạnh ứng dụng trong lúc phát triển. Trỏ ứng dụng vào máy chủ lab, chạy tám ca, rồi mới trỏ sang nhà cung cấp thật. Ca F và ca G là hai ca đáng chạy nhất, vì chúng lộ lỗi cấu hình mà nhà cung cấp thật có thể không báo.
OAuth PKCE cho ứng dụng thu thập: đầu ra nghiệm thu và phần chưa chạy
Phần này gom tiêu chí đạt, tệp đầu ra và những gì còn phải kiểm.
Danh sách kiểm tra
Ứng dụng đạt khi mọi dòng dưới đây đúng.
- Mỗi authorization request có verifier mới, 43 tới 128 ký tự unreserved.
- Challenge dùng S256, hàm tự viết khớp ví dụ trong RFC.
- URL tạo ra có code_challenge và code_challenge_method bằng S256.
- State được tạo mới, so khi nhận chuyển hướng.
- Code được đổi ngay, chỉ một lần, kèm đúng verifier.
- Verifier không ghi ra tệp hay log, xóa sau khi đổi code.
- Máy chủ bắt buộc PKCE cho public client và từ chối plain.
- Có test tự động cho URL và cho ca verifier sai.
Tệp đầu ra của lab
Lab có run.py chứa máy chủ ủy quyền, client Authlib và tám ca. Output in tham số URL, kết quả từng ca và log máy chủ. Chạy lại mất vài giây.
Những gì lab chưa chạy
Chưa chạy với nhà cung cấp OAuth thật, chưa có trang đăng nhập, chưa có TLS, chưa mở máy chủ chuyển hướng cục bộ thật, chưa thử code hết hạn, refresh token, nhiều client. Chính sách không hủy code khi verifier sai là của máy chủ lab.
Kiểm lại với nhà cung cấp thật
Chạy ca A với tài khoản thử của nhà cung cấp. Kiểm URL có PKCE. Thử ca E bằng client thử để biết máy chủ có bắt buộc PKCE không. Không thử ca kẻ chặn code trên tài khoản người khác.
Proxy ở đâu trong luồng này
Nếu mạng bắt buộc đi qua proxy, authorization request và token request đi qua proxy như request HTTP khác. Proxy không đổi gì trong PKCE: cùng challenge, cùng verifier, cùng kết quả. Với API được phép truy cập, khi cần IP Việt Nam ổn định, anh em có thể mua proxy tại trang chủ ProxyVN. Vai trò proxy có ở bài Web Scraping proxy là gì, cách ghi chuỗi proxy ở bài định dạng proxy.
Proxy không thấy verifier qua TLS
Token request đi qua proxy dạng CONNECT thì proxy chỉ thấy luồng mã hóa, không đọc được verifier hay token. Proxy chặn TLS để kiểm tra nội dung thì đọc được. Ứng dụng xử lý token nên dùng proxy không chặn TLS, hoặc đi thẳng nếu chính sách mạng cho phép.
OAuth PKCE cho ứng dụng thu thập: câu hỏi thường gặp
Các câu dưới đây gom những điểm anh em hay hỏi.
PKCE có thay client secret không?
Với public client, PKCE là lớp bảo vệ bước đổi code khi không có secret. Với confidential client, RFC khuyến nghị dùng thêm PKCE, không thay secret.
Có cần PKCE nếu đã có state?
Có. State chống giả mạo request xuyên trang, PKCE chống chặn code. Lab chạy cả hai: ca D do client chặn bằng state, ca B do máy chủ chặn bằng PKCE.
Plain có dùng được không?
Chỉ khi không thể dùng S256. RFC nêu client có khả năng dùng S256 thì phải dùng S256. Authlib 1.9.4 không gửi gì khi đặt plain.
Verifier sai thì máy chủ báo lỗi gì?
invalid_grant, như code sai. Lab thấy đúng mã này ở ca B và ca H.
Kẻ chặn code có đổi được token không?
Khi máy chủ bắt buộc PKCE với S256 thì không, lab thấy invalid_grant. Khi máy chủ không bắt buộc và client không gửi challenge thì có, như ca G.
Verifier dài hơn có an toàn hơn không?
Trong khoảng RFC cho phép, verifier 48 ký tự đã đủ entropy. Dài hơn không làm challenge S256 khác độ dài, chỉ làm token request dài hơn. Thứ cần giữ là verifier ngẫu nhiên thật và mới cho mỗi lần.
Có thể dùng lại verifier khi người dùng đăng nhập lại?
Không nên. Challenge của lần trước đã xuất hiện trong URL. Mỗi lần xin quyền tạo verifier mới, như lab làm cho mỗi ca.
Làm sao biết thư viện có gửi PKCE?
In authorization URL ra và tìm code_challenge cùng code_challenge_method. Ca F cho thấy Authlib 1.9.4 không gửi gì khi đặt plain mà không báo lỗi.
Máy chủ có nên hủy code sau verifier sai?
RFC không bắt buộc. Máy chủ lab giữ code, nên ứng dụng thật vẫn đổi được sau lần thử sai của kẻ khác. Hủy code chặt hơn, nhưng làm người dùng phải đăng nhập lại.
Bài có chạy với nhà cung cấp thật không?
Không. Máy chủ ủy quyền là bản lab theo RFC 7636, client Authlib là thật. Chính sách cụ thể của nhà cung cấp cần kiểm riêng.
OAuth PKCE cho ứng dụng thu thập và những điều cần nhớ
OAuth PKCE cho ứng dụng thu thập chỉ bảo vệ được khi client thật sự gửi challenge S256 và máy chủ bắt buộc PKCE. Hãy kiểm URL ứng dụng tạo ra, kiểm hàm S256 bằng ví dụ của RFC, đổi code ngay với đúng verifier. Proxy.vn - Nhà cung cấp dịch vụ proxy chất lượng hàng đầu Việt Nam khuyên anh em chạy thử OAuth PKCE cho ứng dụng thu thập với tài khoản thử.