我正在我的 React Native 应用程序中实现 X 身份验证流程,借助
expo-auth-session
(仅用于请求授权代码)。
我在尝试将身份验证代码交换为访问令牌时收到错误:语法错误:JSON 解析错误:意外字符:<
目前,使用以下配置获取授权码效果很好:
const TWITTER_AUTHORIZATION_ENDPOINT = "https://twitter.com/i/oauth2/authorize";
const TWITTER_TOKEN_ENDPOINT = "https://twitter.com/i/oauth2/token";
const TWITTER_REVOCATION_ENDPOINT = "https://twitter.com/i/oauth2/revoke";
const discovery = {
authorizationEndpoint: TWITTER_AUTHORIZATION_ENDPOINT,
tokenEndpoint: TWITTER_TOKEN_ENDPOINT,
revocationEndpoint: TWITTER_REVOCATION_ENDPOINT,
};
const redirectUri = makeRedirectUri({ scheme: "my-app" });
const requestConfig = {
clientId: CLIENT_ID,
redirectUri,
scopes: ["tweet.read", "users.read"],
usePKCE: true,
};
以下是钩子向用户提示浏览器的逻辑:
export default function useTwitterAuth() {
const [
request,
response,
promptAsync,
] = useAuthRequest(requestConfig, discovery);
const handleResponse = useCallback(
async () => {
if (response?.type !== "success") return;
try {
const { code } = response.params;
const { codeVerifier } = request;
console.log({ code });
console.log({ codeVerifier });
// ... HERE WE WILL CALL THE ACCESS TOKEN ENDPOINT ...
} catch (err) {
console.log(err);
}
},
[response, request]
);
useEffect(() => {
handleResponse();
}, [handleResponse]);
return { promptAsync };
}
之后,我尝试了两种获取 Twitter 访问令牌的方法:
async function exchangeAccessToken({ code, codeVerifier, redirectUri }) {
const uri = TWITTER_TOKEN_ENDPOINT;
const headers = {
"Content-Type": "application/json",
};
const response = await fetch(uri, {
method: "POST",
headers,
body: {
code,
client_id: CLIENT_ID,
grant_type: "authorization_code",
code_verifier: codeVerifier,
redirect_uri: redirectUri,
},
});
console.log(response);
const data = await response.json();
return data;
}
...
const handleResponse = useCallback(
async () => {
if (response?.type !== "success") return;
try {
const { code } = response.params;
const { codeVerifier } = request;
console.log({ code });
console.log({ codeVerifier });
const data = await exchangeAccessToken({
code,
codeVerifier,
redirectUri,
});
console.log(data);
} catch (err) {
console.log(err); // ERROR: [SyntaxError: JSON Parse error: Unexpected character: <]
}
},
[response, request]
);
const handleResponse = useCallback(
async () => {
if (response?.type !== "success") return;
try {
const { code } = response.params;
const { codeVerifier } = request;
console.log({ code });
console.log({ codeVerifier });
const exchangeAccessRequest = {
clientId: CLIENT_ID,
code,
redirectUri,
extraParams: {
code_verifier: codeVerifier,
},
};
const data = await AuthSession.exchangeCodeAsync(exchangeAccessRequest, discovery);
console.log(data);
} catch (err) {
console.log(err); // SAME ERROR: [SyntaxError: JSON Parse error: Unexpected character: <]
}
},
[response, request]
);
有什么想法吗?当执行
response.text()
解析 HTML 时,我得到:
<body>
<div class="errorContainer">
<img width="46" height="38"
srcset="https://abs.twimg.com/errors/logo46x38.png 1x, https://abs.twimg.com/errors/[email protected] 2x"
src="https://abs.twimg.com/errors/logo46x38.png" alt="Twitter" />
<h1>This browser is no longer supported.</h1>
<p>
Please switch to a supported browser to continue using twitter.com. You can see a list of supported browsers in our Help Center.
</p>
</div>
</body>
API 网址不正确。
正确的是:
const discovery = {
authorizationEndpoint: "https://twitter.com/i/oauth2/authorize",
tokenEndpoint: "https://api.twitter.com/2/oauth2/token",
revocationEndpoint: "https://api.twitter.com/2/oauth2/revoke",
userInfoEndpoint: "https://api.twitter.com/2/users/me",
};