I have a NextJS web app and I'm adding firebase authentication to it.
I want to make secure GET calls to my server, and was wondering what is the token I should use with the server and where to set it?
Should I use the firebase user's AccessToken?
And should I send it in the URL query parameter (or header)? Aren't both alternatives exposed to whomever sees the URL and they can impersonate the user?
Thank you in advance for the help.
Are you talking about your API keys? if you are they are supposed to be visible, you need to write Security Rules which are pretty simple to use.
Read more here: Learn about using and managing API keys for Firebase
If you want your own server-side code to use the caller's Firebase Authentication credentials to ensure they are authorized for the operation they are trying to perform, you should:
Pass the users ID token from the client to your server over a secure connection. This is typically done in the Authorization header of the HTTP request.
On the server decode the ID token, and then check your own authorization logic to see if the call is allowed.
The entire process is quite well described in the Firebase documentation on verifying ID tokens, so I recommend checking that out too.
Related
I have been wondering what is the correct way to handle authorized requests on my Symfony backend. Whenever user id is neccesary while executing request on backend, is it better practice to receive it from frontend or just get it itself on backend. There is also third option to take it from request body and make backend validation. Thanks in advance.
I think you can use a generated user token. And you should not use the user ID. The idea is to use a token linked to the user and re-generate that token every time the user logs in.
There are few best practices and a lot of ready bundles/solutions for any framework.
Please read about "Bearer Authentication" and about "JWT token authentication", below are few links.
JWT authentication is kind of standard way. It has good support from Postman for example.
API Platform has a good support for JWT authentication too, but it might not be the best bundle for starting, because it has own restrictions and it is sometimes not easy to use.
But when you know it well it does help you a lot with starting new application.
So, my advice is to use JWT. Or if you want you can create own solution and own way to generate user tokens.
https://symfony.com/bundles/LexikJWTAuthenticationBundle/current/index.html
https://swagger.io/docs/specification/authentication/bearer-authentication
https://symfony.com/doc/current/the-fast-track/en/26-api.html
All of the React Native Twitter Login Clients that I'm finding seem to be hard-coding the TWITTER_CONSUMER_KEY and TWITTER_CONSUMER_SECRET into the the client code, rather than relying on a server to generate tokens and/or a twitter redirect URL.
Is this safe? (e.g. couldn't a consumer then DOS the API with the TWITTER_CONSUMER_KEY, causing the app to be rate limited?)
Is this the correct way to do it?
Is there a better / more secure way?
According to twitter's documentation, it seems like this is NOT the correct way to do this:
"In the event that you believe that your API keys has been exposed, you should regenerate your API keys by following these steps" - Authentication best practices
Examples which specify that the consumer key/secret should be hardcoded:
https://rnfirebase.io/docs/v5.x.x/auth/social-auth#Twitter
https://github.com/GoldenOwlAsia/react-native-twitter-signin/blob/master/Example/TwitterButton.js#L14
Related questions:
Twitter consumer secret really a secret?
Is it a security vulnerability
Yes.
Your app can be rate limited or flagged as malware/spam etc.
Is there a better / more secure way?
Basically only to have your own site auth (oauth2) done correctly and proxy specific requests from your clients, after validation or a simplified locked down site API that is then translated to the Twitter API.
Why is this, Twitter app-only auth supports OAuth2, allows a secure negotiated handshake and then requests made using a Bearer token. In this mode you can make requests on behalf of your App, but without a logged in user. So can't post tweets or see private accounts or read DMs.
For user-auth, Twitter only support OAuth1 and both the App and User are authenticated, but using a model that assumed plaintext http, so can't share a single token. Every single request needs to be made using consumer key/secret and signing the request. So there isn't a way to do this from a javascript client safely.
Is this safe?
Absolutely not. A bad actor can get users to authenticate via Twitter to receive their token credentials and then use your app's consumer key/secret (which would be available in plain text) to masquerade as your app to do all kinds of nasty stuff.
Is this the correct way to do it?
Given the security vulnerability described above, no.
Is there a better / more secure way?
I'm currently in the process of trying to figure out how to securely achieve authentication with Twitter. This involved a lot of reading, but it appears as though it's simply not possible without your own backend. I'll try and explain why:
Your goal is to receive the user's email/Twitter-ID
To achieve (1), you need to send a request to the GET account/verify_credentials endpoint (https://developer.twitter.com/en/docs/twitter-api/v1/accounts-and-users/manage-account-settings/api-reference/get-account-verify_credentials).
To do (2), you need to provide an authorisation header, which is constructed out of several items, including the user's OAuth tokens as well as your app's consumer key/secret. More info here: https://developer.twitter.com/en/docs/authentication/oauth-1-0a/authorizing-a-request.
You retrieve the user's OAuth tokens using the 3-legged OAuth flow
described here: https://developer.twitter.com/en/docs/authentication/oauth-1-0a/obtaining-user-access-tokens. The first step of this process is to send a POST request to the oauth/request_token endpoint (https://developer.twitter.com/en/docs/authentication/api-reference/request_token).
This endpoint itself requires an authorisation header constructed using
your app's consumer key/secret.
Obviously you can't perform step (4) because that implies you would have your consumer secret available in the client; even if it's not hardcoded, it would have to be in memory at runtime, at some point
Once you have your own backend service, one option would be for your client app to open a browser and direct to an endpoint (let's call it /auth/twitter) on this service which will perform all the steps mentioned above.
This same service could also implement another endpoint (/auth/twitter/token) which handles requests to the callback URL, which you set in your Twitter app settings. This callback URL is used as part of the same 3-legged flow. This endpoint would have all the information needed to then go ahead and retrieve the user's email/Twitter-ID.
Finally, /auth/twitter/token can redirect to a custom URL which your client app would need to handle as part of its URL schemes. It can include enough information by way of parameters for your app to continue as needed post-auth.
I have a Lambda function which triggered by API Gateway service, however this API is accessed by front-end application, this application not requiring the users to login or sign up to use it.
However I would like to secure my API to allow only from my front-end application.
After my research I found that I can use custom authorization in API Gateway, this custom authorization will check the authorization header of the incoming request and validate it.
the question is, can I use Amazon Cognito for something like this(implicit grant type)?
if not what is the thing that the front-end application will send to me to be validated and how can I keep it always changeable, so no one can guess it?
Thank You.
You could check the headers, but if they're always the same, someone can send an HTTP request with those headers - from any client - and trick your Lambda into thinking it's coming from your UI.
Even if you generate a unique token every time your UI is loaded and include it in the headers, someone could take that token and send requests from another client as well.
You could build fancy JavaScript tricks to make headers more dynamic, but it would only make it harder to use your API from another client, not impossible.
I was wondering if there is a easy way to implement a authentication with custom fields. For ex: My app generate a code that is sent by SMS and I want to authenticate the user with this code. So I can’t use strategy local or anything.
I was thinking about create another service that when the code is received it check the database and generate a JWT token and return to the client app. But how to set that token to the app so it will use in the nexts rest and socket calls?
Any clues?
If you know the user prior to the generation of code then you can do it via local strategy by saving the generatrd code to that user and use it for authentication. You can also make use of the authentication service hooks. Or in the verifier.
See it here. https://docs.feathersjs.com/api/authentication/local.html#local-authentication
In addition to the local auth feathersjs provides, there is an additional library supporting all kinds of confirmation procedures, password reset, etc. It is only referenced in the API part of the docs somehow. Here it is.
I was wondering, how can I authenticate requests to FireBase?
I have created new firebase account, marked Enable Email & Password Authentication, created a user with e-mail/password and using { ".read": "auth != null" } in security rules for read access.
Using PostMan plugin for chrome, selected basic auth, entered e-mail/password, GET to https://crackling-fire-NNNN.firebaseio.com/key.json but I always get { "error": "Permission denied" }. It is working if I remove security rules.
HTTPS Basic Auth is not allowed in FireBase?
Can anyone provide some simples examples in pure HTTP how to authenticate GET/PUT/DELETE requests?
Thanks!
I am posting this answer only to help other users to understand how FireBase works.
What I needed was to create an application that allows user (with password) to access his data stored on some server using REST. I thought that I could use FireBase to do that.
But. I have investigated a little bit and find out that FireBase uses JSON Web Tokens (JWT) to authenticate users. Token generation should be done on (other) server side, because it uses FireBase secret. So, apparently you can't send username&password to FireBase. FireBase SDK to be used by another server, and not client. Please feel free to correct me if I am wrong.
Firebase authentication when using the REST API requires an auth token to be passed.
See:
https://www.firebase.com/docs/rest/api/#section-query-parameters
https://www.firebase.com/docs/rest/guide/user-auth.html#section-rest-server-authentication
https://www.firebase.com/docs/rest/guide/user-auth.html
If I understand you question, you would like to use firebase purely with REST services, including authentication. For what I understand, if you want to do that you will need a server that generates a token that then you can append to the querystring. So if what you want is a serverless app that uses REST services, including logging in, the answer is you cannot. Correct me If I'm wrong