Cloud

Fast way to secure your Function with Basic Auth

There are many ways to secure our functions. This topic is not clear when you start using the Cloud Function and it is also constantly changing. I decided to implement my own method that uses the basic and simplest authentication, the Basic Auth. It certainly is not the safest method but it was enough for my purpose. The only flaw is that the function has to be added and implemented in every Cloud function that we make.This implementation then gives us the possibility to call our function from anywhere we want to by simply adding as a parameter of the request the user and the password encrypted in the Basic Auth. To simplify the verification, I created a function that I place in each Cloud Function. This function does the parsing of the request data, verifies if there is a basic auth and, if present, it checks whether the user and password data match. Here is the code I used: var compare = require('tsscmp') const checkAuth = async() => { // parse login and password from headers const b64auth = (req.headers.authorization || '').split(' ')[1] || '' const strauth = new Buffer(b64auth, 'base64').toString() const splitIndex = strauth.indexOf(':') const login = strauth.substring(0, splitIndex) const password = strauth.substring(splitIndex + 1) //function to validate credentials using https://www.npmjs.com/package/tsscmp //Prevents timing attacks using Brad Hill's Double HMAC pattern to perform secure string comparison function check (name, pass) { var valid = true // Simple method to prevent short-circut and use timing-safe compare valid = compare(name, 'user') && valid valid = compare(pass,'password') && valid return valid } if (!check(login, password)) { res.statusCode = 401 res.setHeader('WWW-Authenticate', 'Basic realm="example"') res.end('Access denied') } } Then we can use the function within the method called by our Cloud Function in the following way: exports.helloWorld = async (req, res) => { await checkAuth(); let message = req.query.message || req.body.message || 'Hello World!'; res.status(200).send(message); }; And that’s it, our functions are now safe! Not much but it’s a starting point. So in the end if our system is breached,it is not a big problem, in this function we only return Hello World! How do we instead call our function with Flutter? We simply have to create the Basic Auth with user and password and add it to the request as follows: var basicAuth = 'Basic '+base64Encode(utf8.encode(user:password')); http.Response response = await http.get(apiUrl, headers: <String, String>{'authorization': basicAuth}); print(response.statusCode); //200 print(response.body ); //Hello world! This method is not one of the best, however, it is very fast to implement and also gives us an advantage because it can be used in the same way from all Cloud providers. Finally, we can recall it from anywhere using any language, and it does not force us to use json keys that could be displayed. The only problem I had was having the username and password inside the code that I didn’t really like. I solved it by putting these parameters within the firebase configurations. If you are interested in this, you can read this article Flutter 2 indispensable plugins with great potential.

Metti al sicuro la tua funzione Cloud con Basic Auth

Ci sono tanti modi per poter mettere al sicuro le funzioni. Questo argomento non è chiarissimo dal primo momento in cui si utilizzano le funzioni in Cloud ed è inoltre in continuo cambiamento. Io ho deciso di implementare un mio metodo che utilizza la blasonata e più semplice autenticazione: la Basic Auth. Sicuramente non è la più sicura ma bastava al mio scopo. Unica pecca è che la funzione deve essere aggiunta e implementata in ogni funzione Cloud che andiamo a creare. In questo modo, possiamo chiamare la funzione implementata da dove vogliamo semplicemente aggiungendo come parametro della request user e password criptati nella Basic Auth. Per semplificare la verifica, ho creato, una funzione che inserisco all’interno di ogni Cloud Function. Questa funzione si occupa di fare il parsing dei dati della request, verificare se presente una basic auth e se presente verifica se i dati di user e password corrispondono. Di seguito il codice utilizzato: var compare = require('tsscmp') const checkAuth = async() => { // parse login and password from headers const b64auth = (req.headers.authorization || '').split(' ')[1] || '' const strauth = new Buffer(b64auth, 'base64').toString() const splitIndex = strauth.indexOf(':') const login = strauth.substring(0, splitIndex) const password = strauth.substring(splitIndex + 1) //function to validate credentials using https://www.npmjs.com/package/tsscmp //Prevents timing attacks using Brad Hill's Double HMAC pattern to perform secure string comparison function check (name, pass) { var valid = true // Simple method to prevent short-circut and use timing-safe compare valid = compare(name, 'user') && valid valid = compare(pass,'password') && valid return valid } if (!check(login, password)) { res.statusCode = 401 res.setHeader('WWW-Authenticate', 'Basic realm="example"') res.end('Access denied') } } Successivamente possiamo utilizzare la funzione all’interno del metodo chiamato della nostra Cloud Function nel seguente modo: exports.helloWorld = async (req, res) => { await checkAuth(); let message = req.query.message || req.body.message || 'Hello World!'; res.status(200).send(message); }; Ed il gioco è fatto, le nostre funzioni adesso sono al sicuro. Mica tanto! ma è un inizio. Tanto alla fine se dovessero superare la nostra autenticazione, non sarebbe un grosso problema. In questa funzione restituiamo solo Hello World! Come facciamo invece a richiamare la nostra funzione con Flutter? Dobbiamo semplicemente creare la Basic Auth con user e password e aggiungerla alla request come segue: var basicAuth = 'Basic '+base64Encode(utf8.encode(user:password')); http.Response response = await http.get(apiUrl, headers: <String, String>{'authorization': basicAuth}); print(response.statusCode); //200 print(response.body ); //Hello world! Questo metodo non è uno dei migliori però è molto rapido implementarlo e inoltre ci dà un vantaggio perché può essere utilizzato allo stesso modo per tutti i provider cloud. Infine, possiamo richiamarlo dappertutto utilizzando qualsiasi linguaggio, e non costringe a doversi portare dietro chiavi json che potrebbero essere esposte. L’unico problema che ho avuto è stato quello di avere nel codice scolpiti user e password che non trovavo gradevoli. Ho risolto questo problema mettendo questi parametri all’interno delle configurazioni di firebase. Se siete interessati potete leggere questo articolo Flutter 2 plugin indispensabili dalle grandi potenzialità