Как использовать Firebase refreshToken для повторной аутентификации?

Я использую вызов библиотеки JS firebase.auth().signInWithEmailAndPassword(email, password) и возвращаю объект User. Объект User содержит refreshToken.

Я использую curl 'https://docs-examples.firebaseio.com/rest/saving-data/auth-example.json?auth=TOKEN' для звонков в Firebase.

Срок действия токена в конечном итоге истечет. Чтобы все выглядело так, как будто приложение (iOS и macOS) имеет постоянный вход в систему, я хочу обновить токен, как мне это сделать с помощью библиотеки REST или JS? Я не могу найти в документации никаких вызовов, которые позволили бы мне использовать refreshToken для получения нового token.


person kgaidis    schedule 06.07.2016    source источник


Ответы (4)


Когда вы звоните из браузера, .getIdToken(true) автоматически обновляет ваш токен. Звоните так:

firebase.auth().currentUser.getIdToken(/ forceRefresh / true)
.then(function(idToken) {

}).catch(function(error) {

});

Подробнее здесь https://firebase.google.com/docs/reference/js/firebase.User#getIdToken

person Yevgen    schedule 06.07.2016
comment
Разве currentUser не будет NULL при новом запуске приложения? Я не знаю, как это происходит в обычном браузере, но я не храню файлы cookie или локальные данные. Я храню только refreshToken и все, что мне конкретно нужно. - person kgaidis; 07.07.2016
comment
Чтобы использовать этот код, сначала необходимо выполнить вход. Если вы используете вход с помощью firebase, он должен работать. - person Yevgen; 07.07.2016
comment
Этот! Но .getToken устарел, вы должны использовать .getIdToken. - person Nick Rameau; 12.07.2017
comment
Я получил 403 (ошибка отказа в разрешении), хотя currentUser не равен нулю (т.е. пользователь вошел в систему). Вы знаете причину? - person Takamitsu Mizutori; 13.03.2020
comment
@TakamitsuMizutori У меня была такая же проблема, токен не может быть обновлен. Я решил это, включив API службы токенов для моего ключа API Google. - person Louis Ameline; 18.04.2020
comment
@ Луис Амелин Это работает! Никогда не задумывался о ключе API. Большое спасибо - person Takamitsu Mizutori; 04.05.2020

** ОБНОВЛЕНИЕ ** теперь это также задокументировано в документации Firebase REST в разделе Exchange a refresh token for an ID token:

https://firebase.google.com/docs/reference/rest/auth/#section-refresh-token.


В настоящее время я нашел единственный способ сделать это здесь: https://developers.google.com/identity/toolkit/reference/securetoken/rest/v1/token

Вы должны сделать HTTP-запрос:

POST https://securetoken.googleapis.com/v1/token?key=YOUR_KEY

Где YOUR_KEY можно найти в консоли разработчиков Google ›Диспетчер API› Учетные данные. Это в разделе API Keys.

Убедитесь, что тело запроса имеет следующий формат:

grant_type=refresh_token&refresh_token=REFRESH_TOKEN

Где REFRESH_TOKEN - токен обновления из пользовательского объекта Firebase при входе в систему.

Вы должны установить заголовок Content-Type: application/x-www-form-urlencoded, иначе вы получите ошибку (например, MISSING_GRANT_TYPE).

Вызов POST вернет новый idToken (раньше назывался access_token)

person kgaidis    schedule 09.07.2016
comment
Должен ли этот запрос работать для обновления токена Gmail API? @kgaidis - person ArtStyle; 27.08.2016
comment
@ArtStyle Я не знаком с Gmail API, поэтому не знаю - person kgaidis; 27.08.2016
comment
Это работает, но, к сожалению, не запускает onIdTokenChanged прослушиватель firebase. ... я чувствую, что это должно - person Luiz; 09.10.2017
comment
Я использую тот же способ и получаю id_token. Но когда я пытаюсь получить значения из БД с помощью id_token, я получаю сообщение об ошибке «В разрешении отказано». - person Kumar KS; 16.11.2018
comment
как использовать полученные данные для установки нового токена? - person Killy; 05.12.2018
comment
Будет ли новый токен google-identity недействителен, если пользователь firebase будет удален или аннулирован? @kgaidis - person Lane; 03.09.2019
comment
Когда я это делаю, у меня возникает ошибка 403 (Permission denied). Могу ли я вызвать этот API из javascript веб-клиента? - person Takamitsu Mizutori; 13.03.2020
comment
Я использую ключи ограничения для запросов к указанным веб-сайтам. Но если добавить https://securetoken.googleapis.com в мой список с ограничениями, я не смогу вызвать API, и мне придется удалить все другие URL с ограниченным доступом, чтобы позвонить. В этом случае мой ключ будет доступен для каждого адреса. Любое предложение? - person ikarayel; 15.10.2020
comment
Большое спасибо, что вы сделали мой день, я бы хотел проголосовать 100 раз. Мое приложение продолжало кричать, что срок действия токена истек на протяжении всей разработки, пока вы не пришли мне на помощь - person Maduekwe Pedro; 12.11.2020

Я думаю, что большинство людей здесь ищут способ сохранить свою аутентификацию не в браузере, а, например, на серверной части узла. Оказывается, на самом деле есть способ сделать это:

  1. Обменяйте токен обновления на токен доступа (используя общедоступный API Google)
  2. Обменяйте токен доступа на пользовательский токен (используя функцию firebase, см. Ниже)
  3. Войти с пользовательским токеном

Вот суть кода:

const requestP = require('request-promise');
const fsP = require('fs').promises;

const refreshToken = await fsP.readFile('./refresh_token.txt');
const res = await requestP.post({
  headers: {'content-type': 'application/x-www-form-urlencoded'},
  url: 'https://securetoken.googleapis.com/v1/token?key=' + firebaseConf.apiKey,
  body: 'grant_type=refresh_token&refresh_token=' + refreshToken,
  json: true
});
const customToken = await requestP.post({
  headers: {'content-type': 'text/plain'},
  url: 'https://<yourFirebaseApp>.cloudfunctions.net/createCustomToken',
  body: {token: res.access_token},
  json: true
});
await firebaseApp.auth().signInWithCustomToken(customToken);

И функция firebase:

export const createCustomToken = functions.https.onRequest(async (request, response) => {
    response.set('Access-Control-Allow-Origin', '*');

    try {
        const token = JSON.parse(request.body).token;
        const decodedToken = await admin.auth().verifyIdToken(token);
        const customToken = await admin.auth().createCustomToken(decodedToken.uid);
        response.send(customToken);
    } catch(e) {
        console.log(e);
        response.sendStatus(500);
    }
});
person Martin Cremer    schedule 19.07.2019
comment
В моем случае срок действия пользовательского токена истекает через час. Что вы сделали, чтобы решить эту проблему? - person realappie; 04.08.2019
comment
Я просто прочитал ваш ответ еще раз, я думаю, что мне нужно сохранить токен обновления, а не пользовательский токен. Вы постоянно создаете собственные токены. - person realappie; 05.08.2019
comment
Да, вы должны сохранить токен обновления, например: firebaseApp.auth (). OnAuthStateChanged ((user) = ›{if (user) {fs.writeFileSync ('./ refresh_token.txt', refreshToken);}}); - person Martin Cremer; 05.08.2019
comment
но токен обновления меняется от одного пользователя к другому, как его сохранить в текстовом файле? - person Ayyash; 28.08.2019
comment
безопасно ли для публики создавать собственные токены из токенов обновления? - person Michael Xu; 17.03.2021

// Create a callback which logs the current auth state
function authDataCallback(authData) {
  if (authData) {
    console.log("User " + authData['uid'] + " is logged with token" + authData['ie']);
  } else {
    console.log("User is logged out");
  }
}
// Register the callback to be fired every time auth state changes
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.onAuth(authDataCallback);

Событие onAuth будет вызываться при обновлении страницы, если пользователь вышел из системы, authData будет иметь значение null, в противном случае - нет. Вы можете найти токен в authdata['ie']. На скриншоте ниже я напечатал токен после объекта auth и authdata, как вы можете увидеть, что authData ['ie'] и токен похожи.

authdata.ie и токен

person Nikita    schedule 13.07.2017