Why authorization validation for Firebase onCall is inefficient? - firebase

According to the Firebase documentation about onCall 'callable' functions :
The functions.https.onCall trigger automatically deserializes the request body and validates auth tokens.
Also, according to the Firebase callable Functions protocol specification:
If the auth token supplied in the request is invalid, the request is rejected with 401 Unauthorized, with an error code of UNAUTHENTICATED.
However, I experimented that it's possible to call a function with invalid Authorization header like Authorization: fooBar or worst, without providing it:
curl -X POST --location https://my-test-app.cloudfunctions.net/hello -d "{data:{})"
The function responds "Hello world!" as expected (http 200 'ok').
Of course, context.auth is undefined in that case, but still, it's considered as valid.
This is very misleading and dangerous as developers can think their functions are protected by default, but they aren't : anyone can call it publicly.
I know about the default "AllUser" access credential on the firebase deployed function, nevertheless the documentation is confusing.
Did I missed anything to enable or configure to activate a concrete out-of-the-box token validation?

A missing auth token is never an error for a callable function. All callable functions are considered publicly accessible.
If you don't want the function to do its work unless a valid auth token is presented in the request, then you should simply write a few lines of code to check that and bail early. The code for that is actually provided in the page of documentation that you linked.
// Checking that the user is authenticated.
if (!context.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
'while authenticated.');
}
If you feel that some functionality is not working as described in the documentation, file a bug report on GitHub with your steps to reproduce the problem.

Related

Return Browser-Understandable Status Code with Callable Firebase Cloud Functions

I'm aware that a status code that is interpretable by the browser can be sent via Firebase Cloud Functions when using the onRequest method, however, I would like to return a status code using on callable (i.e., onCall) implementation.
I don't want to simply return an arbitrary JSON object such as
{
status: 401
}
because the browser won't flag that.
Do callable Firebase Cloud Functions support browser-recognisable status codes?
Edit
I found documentation referring to method of throwing an error via e.g.:
throw new functions.https.HttpsError(
'permission-denied',
'Must be an administrative user to initiate delete.'
);
The question still stands though, what about other statuses (e.g., 201)

Is it possible to obtain an access_token with expo-auth-session/providers/google?

I am trying to obtain an access token for use with Google APIs using the up-to-date expo-auth-session package.
It works fine to fetch an id_token via useAuthRequest({responseType: "id_token", ...}) or useIdTokenAuthRequest({...})
However, when trying useAuthRequest({responseType: "code", ...}), I get the following error:
[Unhandled promise rejection: Error: The request is missing a required parameter, includes an unsupported parameter value (other than grant type), repeats a parameter, includes multiple credentials, utilizes more than one mechanism for authenticating the client, or is otherwise malformed.]
Does anyone know what is missing from the request? I am using the Expo Go app currently, so I'm not sure if that prevents obtaining an access token. Currently digging through the package's source code...
Add the following two props to useAuthRequest
shouldAutoExchangeCode: false,
clientSecret: 'any_bogus_value!'
shouldAutoExchangeCode will prevent the code from being exchanged and send it back to you in the response.
clientSecret will simply trigger and if check to be true in the providers source code that will avoid that error you specified being returned.
Note that in general it is not a good practice to avoid errors, but in this case, I feel like the error is being shown in error itself!

"The provided value for the input parameter 'redirect_uri' is not valid" Using firebase

Firebase tells me to do this:
So I did
But I'm still getting this error "The provided value for the input parameter 'redirect_uri' is not valid"
I feel like I've followed instructions exactly but it's still not working. I have no idea how to debug this further. Any suggestions?
Here is my frontend code where I call signIn
let provider = new firebase.auth.OAuthProvider("microsoft.com");
provider.addScope("Calendars.Read");
firebase.auth().signInWithPopup(provider).then(handleResponse);
Edit
I changed the url to my custom domain and it seemed to be working but now I'm getting Error getting verification code from microsoft.com response: proof key for code exchange is required for cross-origin
For some reason Firebase decided to change the url where it handled auth. Instead of using the .firebaseapp.com/__/auth/handler url, it is using my actual custom domain. Though I don't really understand why this would happen...?
The Error getting verification code from microsoft.com response: proof key for code exchange is required for cross-origin was happening because I had configured an SPA on Azure instead of a Web platform.

firebase.messaging.deleteToken() FAILED when deleting token

I am trying stop web browser from receiving notification for cases where user logs out/ when oauth refresh token timeout (forced logout).
But when calling method firebase.messaging.deleteToken() with a valid token passed in as parameter, I keep getting errors "A problem occurred while unsubscribing the user from FCM: Requested entity was not found. (messaging/token-unsubscribe-failed)".
My use case and issue is same as described here, except for the part that I am using firebase 7.24.0.
I can't downgrade to firebase version 7.6.1(it is mentioned as a solution in the above mentioned GitHub thread) because I am also using messaging.onBackgroundMessage() and it has been added recently.

How to set Authorization header while calling "callable function" on Firebase

Basically my problem is, I have my callable functions on Firebase where I want to use "context" to identify if the user is authenticated or not. In the front-end I am logging in user using Firebase authentication (which is an http function on firebase), and as I result I get my user token (which should be used as a Bearer token in the authorization header). The problem is I am not sure how to set the header when I sign in the user so that my "context.auth" would contain the logged in user info rather than being empty. I use firebase.functions().httpsCallable('myFunction'); as the document suggests to make the call from front-end where the problem is even though I logged in before making this call, my context is null.
To give more context think about the following scenario,
//Backend (deployed to cloud functions)
exports.signout = functions.https.onCall((data, context) => {
if(context.auth){
//do signout stuff and return true
}
else{
//not logged in so you can't sign out return false
}
});
//Client
let signout = firebase.functions().httpsCallable('signout');
signout()
.then(res => console.log("signed out"))
.catch(err => console.log(err))
So simply put, while making the httpsCallable('signout') in client, I should have the user token in the 'Authorization' header according to docs, so that I can access the context.auth from my callable function. The thing that I don't understand is how that header should be set there? The most logical thing is setting it on login, but it is not something like setting default header for axios since the call is not exactly an http request rather we use that special httpsCallable function. So how/when is that auth header should be set?
When you use a callable type function from a web or mobile client using the provided SDK, all of the details of the HTTP protocol are handled automatically. There's nothing you have to do to set any headers.
If the user is currently signed in at the time of the request, the SDK will add the authorization header automatically. If the user is signed out, then no header will be added. So, if you want to invoke signout with the authorization of the end user, you will obviously have to call it while they are signed in.
It sounds like you might have signed out the user before invoking the callable. In that case, your function will receive no user data.

Resources