Reputation: 45
When I scan the qr from the quick-login code, and successfuly login, then send a post to the status endpoint, the response reflects that I'm not logged in.
code:
// sending post to create endpoint to generate qr code and login code
app.post('/login/create', async (req, res) => {
console.log('Creating login session...');
try {
const response = await axios.post('https://apis.roblox.com/auth-token-service/v1/login/create', {}, {
headers: {
'accept': 'application/json, text/plain, */*',
'accept-language': 'en-US,en;q=0.9',
'cookie': req.headers.cookie,
'x-csrf-token': req.headers['x-csrf-token'],
}
});
const { code, imagePath, privateKey } = response.data;
const qrCodeUrl = `https://apis.roblox.com/auth-token-service${imagePath}`;
console.log('Login session created successfully:', { code, qrCodeUrl, privateKey });
res.json({ code, qrCodeUrl, privateKey });
} catch (error) {
console.error('Error creating login session:', error.message);
res.status(500).json({ error: error.message });
}
});
//login status once I scan the qr code and approve the login
app.post('/login/status', async (req, res) => {
const { code, privateKey } = req.body;
console.log('Checking login status for code:', code);
try {
const response = await axios.post('https://apis.roblox.com/auth-token-service/v1/login/status', {
code,
privateKey
}, {
headers: {
'accept': 'application/json, text/plain, */*',
'accept-language': 'en-US,en;q=0.9',
'content-type': 'application/json;charset=UTF-8',
'x-csrf-token': req.headers['x-csrf-token'],
}
});
console.log('Login status response:', response.data);
res.json(response.data);
} catch (error) {
console.error('Error checking login status:', error.message);
res.status(500).json({ error: error.message });
}
});
But it still returns:
Checking login status for code: B8VHPW
Error checking login status: Request failed with status code 403
What am I missing?
Upvotes: 2
Views: 96
Reputation: 15602
As per this guide explaining the full process of authenticating an account through Quick Login in Roblox
These APIs requires a special header called x-csrf-token, this can be fetched by observing a failed response for the same header, if it’s present, you should attach the x-csrf-token from the response headers, and attach it to the request headers.
This means that in the case you're getting 403, very likely your x-csrf-token
is either not there or has expired / is invalid.
When you call Roblox without a valid CSRF token, it returns 403 and provides a fresh x-csrf-token in the response headers.
So, you can adjust the code to retry the request using that new token like so
app.post('/login/status', async (req, res) => {
const { code, privateKey } = req.body;
console.log('Checking login status for code:', code);
const postStatus = async (csrfToken = '') => {
return axios.post(
'https://apis.roblox.com/auth-token-service/v1/login/status',
{ code, privateKey },
{
headers: {
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'en-US,en;q=0.9',
'Content-Type': 'application/json;charset=UTF-8',
'x-csrf-token': csrfToken,
},
}
);
};
try {
// 1) First attempt using whatever x-csrf-token was in the request (may be empty)
const response = await postStatus(req.headers['x-csrf-token'] || '');
console.log('Login status response:', response.data);
return res.json(response.data);
} catch (error) {
// 2) If Roblox returns 403 with a new x-csrf-token, grab it and retry.
if (
error.response &&
error.response.status === 403 &&
error.response.headers['x-csrf-token']
) {
const newToken = error.response.headers['x-csrf-token'];
console.log('Received new x-csrf-token from 403:', newToken);
try {
const retryResponse = await postStatus(newToken);
console.log('Login status response (retry):', retryResponse.data);
return res.json(retryResponse.data);
} catch (retryError) {
console.error('Error on retry with new CSRF token:', retryError.message);
return res.status(500).json({ error: retryError.message });
}
}
console.error('Error checking login status:', error.message);
return res.status(500).json({ error: error.message });
}
});
Upvotes: 2