我目前正在尝试使用 Twitter 的 v2 API 和 expo-auth-session 为 React Native (Expo) 应用程序构建 Twitter 授权流程。在对用户进行身份验证后,我能够从 Twitter 的 API 接收代码,但在按照文档将代码交换为访问令牌时遇到了问题。我已经构建了一个 React hook 来处理整个 Twitter 身份验证过程,但是登录后,我总是收到此错误
为代码验证者传递的值与代码质询不匹配
这是我的代码片段
import React from "react"
import {
useAuthRequest,
CodeChallengeMethod,
ResponseType,
makeRedirectUri,
} from "expo-auth-session"
import { SocialLogins, SOCIAL_TOKENS, useGlobalStore } from "@libs/shared"
import { TWITTER_CLIENT_ID, TWITTER_CLIENT_SECRET } from "@env"
import pkceChallenge from "react-native-pkce-challenge"
const { codeChallenge, codeVerifier: code_verifier } = pkceChallenge()
export const useTwitterAuth = () => {
const { socialAuth, handleSocialAuth, services } = useGlobalStore()
const discovery = {
authorizationEndpoint: "https://twitter.com/i/oauth2/authorize",
tokenEndpoint: "https://twitter.com/i/oauth2/token",
revocationEndpoint: "https://twitter.com/i/oauth2/revoke",
}
const state = "my-state"
const [, , promptAsync] = useAuthRequest(
{
clientId: TWITTER_CLIENT_ID!,
clientSecret: TWITTER_CLIENT_SECRET,
// TODO: Refactor
redirectUri: makeRedirectUri({ scheme: "scheme" }),
usePKCE: true,
state,
scopes: ["tweet.read", "users.read", "offline.access"],
responseType: ResponseType.Code,
codeChallengeMethod: CodeChallengeMethod.S256,
codeChallenge,
},
discovery
)
const handlePressAsync = async () => {
const result = await promptAsync()
if (result.type !== "success") {
alert("Uh oh, something went wrong")
return
}
const accessCode = result.params?.code as string
const body = new URLSearchParams({
code: accessCode,
grant_type: "authorization_code",
client_id: TWITTER_CLIENT_ID!,
state,
redirect_uri: makeRedirectUri({ scheme: "scheme" }),
code_verifier,
}).toString()
fetch("https://api.twitter.com/2/oauth2/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body,
})
.then((resp) => resp.json())
.then((data) => console.log("DATA =>", data))
handleSocialAuth(SocialLogins.Twitter, true)
await services.storage.setSocialToken(SOCIAL_TOKENS.Twitter, accessCode)
}
const handleAuth = async () => {
if (socialAuth[SocialLogins.Twitter]) {
handleSocialAuth(SocialLogins.Twitter, false)
await services.storage.removeSocialToken(SOCIAL_TOKENS.Twitter)
} else {
handlePressAsync()
}
}
React.useEffect(() => {
const handleHasTwitterUser = async () => {
const twitterToken = await services.storage.getSocialToken(
SOCIAL_TOKENS.Twitter
)
if (!twitterToken) {
return
}
handleSocialAuth(SocialLogins.Twitter, true)
}
handleHasTwitterUser()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
return {
handleTwitterAuth: handleAuth,
}
}
这仍然返回以下错误:
Value passed for the code verifier did not match the code challenge
我已经检查了我使用的react-native-pkce-challenge依赖项是否正在工作,通过检查代码挑战哈希器创建与依赖项完全相同的代码挑战,并且它似乎按预期工作。
如果有人遇到过这个问题,我很乐意听取您的意见。谢谢!
我试图让用户授权我的应用程序代表他们作为 Twitter 用户行事。我已成功收到访问代码,但无法使用 PKCE 将访问代码转换为令牌,因为即使它是正确的,我仍然收到相同的错误。
Value passed for the code verifier did not match the code challenge
我遇到了同样的问题,只是通过使用钩子 useAuthRequest() 返回的请求中包含的 codeVerifier 来修复它,而不是使用react-native-pkce-challenge创建一个新的问题