Autenticação para acesso administrativo ao Firebase em Ruby

Autenticação para acesso administrativo ao Firebase em Ruby

A nossa aplicação de gestão de guestlists em tempo real Guest to Impress usa a base de dados Firebase da Google.

Recentemente, ao actualizar os nossos testes na API em Ruby (Sinatra), resolvemos actualizar o modo de autenticação por "segredo" (modo que vai ser descontinuado) pelo novo SDK de autenticação. A documentação do Firebase, apesar de extensa, não cobre este caso em particular, por isso aqui está um tutorial de como o fazer.

Acesso administrativo

O primeiro passo é descarregar o ficheiro com a informação (secreta) da Service Account. Fazemos isso acedendo à consola da base dados, abrindo o menu da roda dentada à direita do Overview de dados e clicando em Project Settings.

Aí selecionamos Service Accounts.

E no fundo dessa página descarregamos o ficheiro JSON com a informação de acesso. Esta informação dá acesso adminsitrativo à base de dados, por isso convêm sermos cuidados com este ficheiro.

Google Auth Library for Ruby

Este ficheiro vai ser usado por pela Google Auth Library for Ruby da Google. Usando o ficheiro que escarregamos anteriormente esta aplicação vai-nos devolver um token de acesso que irá ser usado para a autenticação.

Para instalar basta correr gem install googleauth.

Definir variáveis

A primeira parte consiste em disponibilizar duas variáveis que vão ser necessárias:

ENV['FIREBASE_URL'] = 'https://<projectId>.firebaseio.com'  
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = './file-with-secret-info.json'  

A primeira é o URL da base de dados e a segunda a localização do ficheiro que descarregamos com os dados de acesso adminstrativo (relativo ao ficheiro que vamos criar).

Pedir um token

A seguir vamos pedir um token o usando o googleauth.

require 'googleauth'

scopes =  [  
  'https://www.googleapis.com/auth/firebase.database',
  'https://www.googleapis.com/auth/userinfo.email'
]
authorization = Google::Auth.get_application_default(scopes)

access_token = authorization.fetch_access_token!  

Nos scopes temos o scope do firebase e um segundo, userinfo.email que é necessário para ue o token seja aceite.

Efectuar o pedido ao Firebase

Com o access_token que recebemos já podemos efectuar o pedido a um endpoint do Firebase mesmo que este esteja protegido com regras já que o nosso acesso vai ser adminstrativo.

path = '/data-path'

uri = URI("#{ENV['FIREBASE_URL']}#{path}.json")

request = Net::HTTP::Get.new(uri, 'Content-Type' => 'application/json')  
request['Authorization'] = "Bearer #{access_token['access_token']}"

http = Net::HTTP.new(uri.hostname, uri.port)  
http.use_ssl = true

response = http.request(request)  

O pedido é um pedido GET normal usando o net/http. O resultado vai ser um JSON com os valores do endpoint.

O access_token está a ser enviado na header, mas também podia ser enviado como um parâmetro no URL. Bastava construir o uri desta forma:

uri = URI("#{ENV['FIREBASE_URL']}#{path}.json?access_token=#{access_token}")  

O ficheiro completo está neste gist.