Сбой рабочего процесса SAML платформы Google Cloud Identity (CICP)
Задний план
Использование Firebase Auth и SAML Auth Provider со следующей конфигурацией:
const config = {
apiKey: "AIzaSy...",
authDomain: "example-app.firebaseapp.com",
};
firebase.initializeApp(config);
const provider = new firebase.auth.SAMLAuthProvider('saml.example-idp');
function saml() {
firebase.auth().signInWithRedirect(provider)
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
});
}
В конфигурации CICP для восходящего потока SAML есть поставщик услуг: наш идентификатор объекта и ACS, настроенный как наш CICP. https://example-app.firebaseapp.com/__/auth/handler
.
Что я ожидаю произойти
Чтобы иметь возможность установить точку останова в signInWithRedirect()
обещание then
и увидеть аутентифицированного пользователя.
Что на самом деле происходит
Поток перенаправляется к IdP, и выполняется аутентификация.
IdP выдает страницу перенаправления с автоматической отправкой при загрузке и multipart/form-data
форма с:
- Content-Disposition: форма-данные; name=SAMLResponse - содержащий подписанный SAMLResponse в кодировке base64
- Content-Disposition: форма-данные; name=RelayState - содержит состояние реле из потока SAML
- Content-Disposition: форма-данные; name="ssourl" - содержащий URI обработчика аутентификации проекта firebase
Это, в свою очередь, заставляет CICP отображать и возвращать страницу со скриптом, который устанавливает
var POST_BODY=""------WebKitFormBoundary9bn7AOpnZiIRk9qZ\r\nContent....."
т.е. вместо того, чтобы анализировать тело формы и извлекать поле SAMLResponse, он воспроизводит весь Request.body в скрипте, а затем вызывает fireauth.oauthhelper.widget.initialize();
Это, очевидно, не удается, потому что эти обходы, а затем попытки отправить все тело ответа в /__/auth/handler
конечная точка как строка запроса.
Я подозреваю, что в этой цепочке отсутствует простой элемент конфигурации, потому что все потоки выглядят нормально для меня, пока данные из составной формы не будут помещены в POST_BODY, а затем не предотвратят преобразование токена SAML в токен OAuth.
Вопрос
Какой элемент конфигурации неверен в этой (отредактированной) настройке и каков правильный вывод значения для его замены?
2 ответа
Краткий ответ на длинный вопрос:
Обработка поставщика SAML в Firebase Auth и Google CICP не обрабатывается multipart/form-data
и должен быть в application/x-www-form-urlencoded
.
Это конфигурация SAML IdP, а не то, что может быть обработано конфигурацией поставщика службы Firebase Auth.
Возможно, с SAML есть еще одна техническая проблема, но, по крайней мере, в этом есть некоторая несогласованность. sign-in
используется метод.
Согласно (Официальные документы)[https://cloud.google.com/identity-platform/docs/how-to-enable-application-for-saml, у вас есть 2 варианта для входа:
1) Со всплывающим окном
В этом случае вы можете использовать обещание для получения user credential
с sign-in
метод:
firebase.auth().signInWithPopup(provider)
.then((result) => {
// User is signed in.
// Identity provider data available in result.additionalUserInfo.profile,
// or from the user's ID token obtained via result.user.getIdToken()
// as an object in the firebase.sign_in_attributes custom claim
// This is also available via result.user.getIdTokenResult()
// idTokenResult.claims.firebase.sign_in_attributes.
})
.catch((error) => {
// Handle error.
});
2) С перенаправлением
В этом случае ваш код следует разбить на 2 части. Первыйsign-in
метод без использования обещаний:
firebase.auth().signInWithRedirect(provider);
Затем инициализация "слушателя" для получения учетных данных пользователя после перенаправления входа:
// On return.
firebase.auth().getRedirectResult()
.then((result) => {
// User is signed in.
// Identity provider data available in result.additionalUserInfo.profile,
// or from the user's ID token obtained via result.user.getIdToken()
// as an object in the firebase.sign_in_attributes custom claim
// This is also available via result.user.getIdTokenResult()
// idTokenResult.claims.firebase.sign_in_attributes.
})
.catch((error) => {
// Handle error.
});
Будет добавлено в загрузочную часть вашей страницы / приложения.
Надеюсь, это поможет.