最近做一个国外app的爬虫,抓包写完了整个登录流程,最后一步一直提示:{"status_code":"401 UNAUTHORIZED","message":"invalid authorization code"},最后通过排除法定位到这两个字段,这两个字段通常出现在使用OAuth 2.0 PKCE登录流程中。因对OAuth 2.0 PKCE不了解,查阅资料后发现verifier字段是随机字符串,通常是64位或者128位,code_challenge=base64url(sha256(verifier)),具体实现:
python:
import secrets
import hashlib
import base64
# 生成code_verifier
code_verifier = secrets.token_urlsafe(64)
# 生成code_challenge
code_challenge = base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest()).decode().rstrip('=')
print(code_verifier)
print(code_challenge)
js:
function generateRandomString(length) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
const bytes = new Uint8Array(length);
window.crypto.getRandomValues(bytes);
return Array.from(bytes).map(byte => chars[byte % chars.length]).join('');
}
function base64URLEncode(str) {
return btoa(str)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}
function generatePKCE() {
const codeVerifier = generateRandomString(43);
const hash = CryptoJS.SHA256(codeVerifier);
const codeChallenge = base64URLEncode(
CryptoJS.enc.Base64.stringify(hash)
);
return { codeVerifier, codeChallenge };
}
const { codeVerifier, codeChallenge } = generatePKCE();
console.log('Verifier:', codeVerifier);
console.log('Challenge:', codeChallenge);
抓包发现APP先提交了code_challenge,在后面的数据中才提交了code_verifier进行验证,习惯了先提交数据后校验结果的流程,对此类先提交结果,再校验数据的操作有点懵,菜鸟一枚,写个文章记录一下。