- Вопрос или проблема
- Ответ или решение
- Проблема с верификацией токена Firebase App Check при использовании reCAPTCHA Enterprise
- Причины возникновения проблемы
- Рекомендации по решениям
- 1. Проверка настройки reCAPTCHA
- 2. Источник токена
- 3. Убедитесь в успешности верификации токена
- Использование диагностических логов
- Заключение
Вопрос или проблема
Я создаю приложение, в котором люди могут создавать контейнеры Docker. Я пытаюсь защитить свой API, используя Firebase App Check с reCAPTCHA Enterprise. Я отправляю токен с фронтенда на бэкэнд для проверки. Я знаю, что токен отправляется, так как могу вывести его в консоль, когда он доходит до бэкэнда, поэтому думаю, что это ошибка с проверкой. Код не показывает никаких ошибок, он просто говорит “Неавторизован”. Вот мой код.
createcontainer.html
<!DOCTYPE html>
<html>
<head>
<title>Создать экземпляр</title>
<link rel="stylesheet" href="page.css">
<script type="module" src="check.js" defer></script>
<script type="module" src="script.js" defer></script>
</head>
<body>
<form>
<h1>Создать игровой экземпляр</h1>
<label for=""width>Ширина:</label>
<input type="text" id="width" required><br><br>
<label for="height">Высота:</label>
<input type="text" id="height" required><br><br>
<label for="user">Пользователь:</label>
<input type="text" id="user" required><br><br>
<label for="password">Пароль:</label>
<input type="text" id="password" required><br><br>
<button id="submitForm" type="submit">Отправить</button>
</form>
</body>
</html>
script.js
import { initializeApp } from "https://www.gstatic.com/firebasejs/10.14.0/firebase-app.js";
import { initializeAppCheck, ReCaptchaEnterpriseProvider, getToken } from "https://www.gstatic.com/firebasejs/10.14.0/firebase-app-check.js";
const firebaseConfig = {
apiKey: "xxxxxxxx",
authDomain: "reyv-a8452.firebaseapp.com",
projectId: "reyv-a8452",
storageBucket: "reyv-a8452.appspot.com",
messagingSenderId: "174731893649",
appId: "1:174731893649:web:685b864d27176334b4d830"
};
const app = initializeApp(firebaseConfig);
const appCheck = initializeAppCheck(app, {
provider: new ReCaptchaEnterpriseProvider("xxxxxxxxxx"),
isTokenAutoRefreshEnabled: true // Установите в true, чтобы разрешить автоматическое обновление.
});
const submitForm = document.getElementById('submitForm');
submitForm.addEventListener("click", async function (event) {
event.preventDefault()
var width = document.getElementById("width").value;
var height = document.getElementById("height").value;
var user = document.getElementById("user").value;
var password = document.getElementById("password").value;
let appCheckTokenResponse;
appCheckTokenResponse = await getToken(appCheck, /* forceRefresh= */ false)
// Отправить данные на бэкэнд
fetch('/process', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Firebase-AppCheck': appCheckTokenResponse.token
},
body: JSON.stringify({ width: width, height: height, user: user, password: password })
})
.then(response => response.json())
.then(data => {
// Обработать ответ от бэкэнда
data = JSON.stringify({ data: data })
data = data.replace('{"data":{"message":"', '')
data = data.replace('"}}', '')
window.location.href = data;
})
})
server.js
const fs = require("fs");
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
var Docker = require('dockerode');
var docker = new Docker({host: 'xxxxxx', port: xxxxx});
var portnumber = "8080"
var admin = require("firebase-admin");
var serviceAccount = require("./xxxxxxxxx");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
function createdockercontainer(width, height, portnumber, user, password) {
docker.createContainer({Image: 'selkies', Tty: false, HostConfig: {ShmSize: 1073741824, NetworkMode: "host", Privileged: true}, Cmd: [width, height, portnumber, user, password]}, function(err,container){
container.start();
})
}
const incrementNr = (nr) => {
const [nrDigits] = /\d*$/.exec(nr);
const next="" + (+nrDigits + 1);
const nextNr = nr.slice(0, nr.length - Math.min(next.length, nrDigits.length)) + next;
return nextNr;
};
// Middleware
app.use(bodyParser.json());
const appCheckVerification = async (req, res, next) => {
const appCheckToken = req.header('X-Firebase-AppCheck');
console.log(appCheckToken)
if (!appCheckToken) {
res.status(401);
return next("Неавторизован");
}
try {
const appCheckClaims = await getAppCheck().verifyToken(appCheckToken);
// Если verifyToken() завершается успешно, продолжить с следующим middleware
// функцией в стеке.
return next();
} catch (err) {
res.status(401);
return next("Неавторизован");
}
}
// Обработка данных формы
app.post('/process', [appCheckVerification], (req, res) => {
const width = req.body.width;
const height = req.body.height;
const user = req.body.user;
const password = req.body.password;
// Обработать данные или выполнить любые задние задачи
// ...
// Вернуть ответ обратно на фронтенд
portnumber = incrementNr(portnumber)
createdockercontainer(width, height, portnumber, user, password)
res.json({
message: 'https://reyv.org'
});
});
// Запустить сервер
const port = 3000;
app.use(express.static('public'))
app.listen(port, () => {
console.log(`Сервер запущен на порту ${port}`);
});
Не уверен, связано ли это, но при добавлении ключа reCAPTCHA enterprise в консоль Firebase он показывает красное кольцо. Консоль Firebase
Ответ или решение
Проблема с верификацией токена Firebase App Check при использовании reCAPTCHA Enterprise
Ваша проблема с верификацией токена Firebase App Check может быть вызвана различными факторами. В данном ответе мы рассмотрим основные причины и предложим пути их устранения.
Причины возникновения проблемы
-
Отсутствие токена: Вы уже упомянули, что токен успешно отправляется на бэкэнд, но стоит удостовериться, что он действительно присутствует в заголовках запроса. В вашем коде есть лог для вывода токена
console.log(appCheckToken)
. Проверьте, что токен действительно отображается корректно на сервере. -
Неверная конфигурация:
- Проверьте правильность настройки ключа reCAPTCHA Enterprise в консоли Firebase. Красное кольцо может указывать на неправильную настройку или отсутствие доступа. Убедитесь, что ключ активирован и имеет все необходимые разрешения.
- Убедитесь, что вы используете тот же проект Firebase как на фронтенде, так и на бэкенде.
-
Неправильная верификация токена:
- В коде бэкенда вы обращаетесь к функции
getAppCheck()
для верификации токена. Убедитесь, что эта функция корректно инициализирует администраторскую библиотеку Firebase. Попробуйте импортировать и использоватьadmin.appCheck()
.
- В коде бэкенда вы обращаетесь к функции
Рекомендации по решениям
1. Проверка настройки reCAPTCHA
Перейдите в консоль Firebase и убедитесь, что ключ reCAPTCHA Enterprise правильно настроен. Попробуйте сделать следующее:
- Создайте новый ключ и убедитесь, что у него правильные доменные имена.
- Проверьте, активирован ли ключ.
2. Источник токена
Убедитесь, что токены от клиента действительно сгенерированы и не истекли. Вы можете реализовать ручное обновление токена, установив forceRefresh = true
в getToken()
. Кроме того, следите за тем, чтобы на фронтенде не было ошибок в запросах, которые могли бы мешать получению токена.
appCheckTokenResponse = await getToken(appCheck, /* forceRefresh= */ true);
3. Убедитесь в успешности верификации токена
Вот ваш текущий код верификации:
const appCheckClaims = await getAppCheck().verifyToken(appCheckToken);
Необходимо уточнить, что getAppCheck()
возвращает. Возможно, правильным будет заменять его на admin.appCheck().verifyToken(appCheckToken)
:
const appCheckClaims = await admin.appCheck().verifyToken(appCheckToken);
Если токен не может быть проверен, поймите, в чем именно заключается ошибка, выбрасываемая сервером.
Использование диагностических логов
Добавьте более детализированные логи в свой код для диагностики:
- Логируйте входящие заголовки и сам токен.
- В случае ошибки верификации, логируйте ошибку, чтобы понять природу проблемы.
try {
const appCheckClaims = await admin.appCheck().verifyToken(appCheckToken);
} catch (err) {
console.error("Ошибка верификации App Check:", err);
res.status(401).send("Unauthorized");
}
Заключение
Проблемы с верификацией токена Firebase App Check могут быть вызваны неправильной конфигурацией ключа reCAPTCHA Enterprise или ошибками в коде верификации. Следуйте рекомендациям и внимательно проверяйте каждую стадию процесса, чтобы устранить проблему. Если все еще возникают трудности, рекомендуется обратиться к официальной документации Firebase или в службу поддержки для получения более индивидуальной помощи.