Loading file from Firebase storage through selfLink gives 401 - javascript

I am putting files in Firebase Storage, and (using cloud functions) store the objectMetaData.selflink in the database. I am trying to load a file using that link, but get a 401 stating that:
Anonymous users does not have storage.objects.get access to filename]
But since i am logged in (there is a currentUser on the auth() instance), i am confused what i am doing wrong here. Should i be sending some kind of token with my request?
I have not changed the initial ruleset for storage:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Also, maybe related but maybe not: since this example uses another approach, what is the difference between selfLink and getDownloadURL?
EDIT:
I finally got it working by using firebase.storage().ref(somePath). I also tried firebase.storage().refFromURL(selfLink).getDownloadURL() but that gave the error of supplying an invalid link to refFromURL. Then the question remains: what exactly is the selfLink?

Documentation states that the selfLink is the link to access the object, assuming you have sufficient permissions. It is not the download URL
Docs

Related

How to retrieve a Firebase-Instance-ID-token?

I am using the Firebase Functions Shell to interactively test a callable HTTPS function. The documentation (Test functions interactively) states that I can pass a Firebase-Instance-ID-token for authentication but doesn't say how to acquire one.
Optionally, you may pass in a Firebase-Instance-ID-token as the second
parameter. This must be a string.
# invoke with Instance ID token
myCallableFunction('test data', {instanceIdToken: 'sample token'})
It also says,
Emulation of context.auth is currently unavailable.
Does this mean even if I pass a token my function will not receive context: { auth: uid }, etc? If so, what would be a good way to mock this for testing purposes?
FYI, I am not using Firebase Messaging.
If you don't know exactly what you want there, then don't pass anything at all. If you're not using FCM, then the string will be useless to your function. It's only really used to in the API call to send messages, or to be stored for later use with FCM.
This token has nothing to do with user auth. FCM tokens don't identify an authenticated user. They identify a device that the user is using your app on.
I will point out also that the documentation states:
Emulation of context.auth is currently unavailable.
So there's nothing you can do to get context.auth populated in your function, from the perspective of this local testing tool.

Firebase storage rules error: unexpected identifier; function taken from documentation

I am using firebase and am trying to make the storage publicly accessible. According to the firebase documentation I need to include the following code, which I added to the .js file which contains a function that sends user input to storage.
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}
Based off others' problems I've tried:
adding ;-s
changing it to firebase.storage(code),
doing var storage ...
but none of these methods work.
I have my code for configuring firebase (apiKey, authDomain, databaseURL, projectID, and storageBucket) and also initialized the app.
This isn't code that you would put in a JS file, this is a firebase storage security rule. It is a configuration that you would configure in the console for your project (alternatively, you can deploy the rules via the CLI, but they are still not a direct part of your application code).
You should navigate to the rules tab and input the configuration there:
Of course, the rule you are suggesting here is very dangerous!
This rule will allow any user (including unauthenticated users!) to write as much as they want into your storage bucket -- effectively giving you the bill for their free storage. You should consider carefully if this is what you really want.

How to properly implement firestore database rules to prevent update to data when certain field changed?

I am building a NodeJS Express app and am using Firebase as the backend. I am trying to secure my firebase backend, more specifically the firestore database with Firestore Security Rules. However, I cannot seem to get my security rules to trigger.
I have a route called /api/goalPRs/:goalPRId which updates a database ref with the body of the request by calling
const goalPRsRef = db.collection('goalProgressReports');
goalPRsRef.doc(goalPRId).update(newGoalPR).then(()=>({update: 'Success'}));
Now, each goalPR has a field called targetGoalId, which I want to be constant, I dont want that data to be editable. Hence I have tried to set up the following firestore security rule.
service cloud.firestore {
match /databases/{database}/documents {
match /goalProgressReports/{goalPR} {
allow update: if request.resource.data.targetGoalId == resource.data.targetGoalId;
}
}
}
With this security rule I expect that any update to a document within goalProgressReport collection should be denied if the old targetGoalId is not equal to the new one. However, this is not the case. I can provide a new targetGoalId and it incorrectly updates.
Also, even when I try something like this with the security rules:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false
}
}
}
I am still allowed to write to the database, even though from my understanding this rule shouldn't allow any reads or writes to the database. Is my understanding of how security rules work incorrect? How can I fix my goalProgressReport security rule to not allow updates if the targetGoalId has changed?
Since you're running on nodejs, that means you're using either the Cloud Firestore node SDK or the Firebase Admin SDK which wraps the Cloud SDK. In this case, security rules don't apply. They only apply to access coming directly from web and mobile applications, and not from the server SDKs. The server SDKs always bypass all security rules, because it's coming from a privileged service account.

Get an access token without being connected to facebook

I need to retrieve a facebook page's list of posts (feed) using their javascript SDK, just like they explain in their docs: https://developers.facebook.com/docs/graph-api/reference/v2.4/page/feed
/* make the API call */
FB.api(
"/{page-id}/posts",
function (response) {
if (response && !response.error) {
/* handle the result */
}
}
);
I need it to be my website's "news section", so users should see it even if they are not connected to facebook.
The problem
Cool, but there is a problem... It returns: An access token is required to request this resource.
Holy cow... I'd like to get some access token for you #facebook, but my app doesn't make use of your authentication tools/plugins.
ANYWAY, I tried with FB.getLoginStatus(); but doesn't work, because the only way it can return an access_token is if the user is actually connected to the application. My users may not even be logged to facebook!
So, ¿How can I get an access_token to be stored into a variable, and later be used to get /{my-page}/posts?
I've already payed a look to this SO question, but it doesn't solves my problem, simply because there are no such "generic tokens".
I've also read https://developers.facebook.com/docs/facebook-login/access-tokens/ and that also relies on tokens generated through facebook login methods... So, can't I display a list of fb page's posts in my website, without being connected into facebook, hence an application?
ADD: My app is build with angularJS, I'm not dealing with server-side code. I shall rely purely on javascript methods.
You could either use an page or an app access token, but as you'd be using them on the client-side, neither of them are an option.
See
https://developers.facebook.com/docs/facebook-login/access-tokens#apptokens
https://developers.facebook.com/docs/facebook-login/access-tokens#pagetokens
Note that because this request uses your app secret, it must never be made in client-side code or in an app binary that could be decompiled. It is important that your app secret is never shared with anyone. Therefore, this API call should only be made using server-side code.
I'd strongly recommend to build a simple server-side script (PHP for example) to proxy the request to the Graph API. You could then call this via AJAX for example and load the posts asynchronously (and alse get rid of the FB JS SDK!). There is NO way to handle this in a secure manner if you don't want to use FB Login for all of your users (which also doesn't make much sense IMHO).
I think it's straightforward :)
Since pages' posts are always public, it only needs a valid access token to retrieve page posts.
Quoting what you've written:
So, ¿How can I get an access_token to be stored into a variable, and later be used to get /{my-page}/posts?
You only require an access token.
My suggestion would be;
- Generate an access token for yourself (no extra permission needed)
- request page-id/posts
This way you don't require other users to be connected to facebook, you can simply requests page-id/posts to retrieve posts with access token you generated for yourself.
I hope it solves your problem :D
TIP: As long as posts are public, you only require a valid access token, it doesn't need to be user or page specific.

Soundcloud API /resolve method 404 error

Simple dimple one here- trying to use Soundcloud's resolve method to retrieve a JSON feed of track data for a private set.
http://api.soundcloud.com/resolve.json?url=http://soundcloud.com/myUser/private-set
resolve returns a 401 unauthorized error, as it should
http://api.soundcloud.com/resolve.json?url=http://soundcloud.com/myUser/private-set&client_id=myClientID
resolve returns a '404' not found error. it should be 301 redirecting to the authorized JSON feed for the track, such as http://api.soundcloud.com/tracks/49931.json in the doc's example
I've created an App
I'm using the App's Client ID
I've enabled App access in the Set's edit menu
I'm formatting it as per the API docs
Am I missing something here?
So after some testing I've confirmed that the issue is related to the fact that you're trying to request a private set. Because the set is private, you would need to first go through SoundCloud's OAuth 2 authentication process before being able to access the set.
Try resolving the set url with the url found in the share dialog of your set. This url contains a secret token that can be used to access a private set without logging in.
Not sure how far this'll get you if the tracks in the set are also private, though. And like bbone mentioned, you'll be exposing this secret token, which may or may not be a problem.

Categories