This is surprisingly excruciating. There's no documentation whatsoever for the new Firebase + Python. So I'm trying to use the REST API, which needs a special kind of authentication.
As you can see, they say it could be the app's secret (nowhere to be found in the new console) or the authentication token (which is not documented for python). If I click the REST authentication documentation I get a Java example.
I've downloaded the JSON Key file for the service account, and tried to apply pieces of code found in other places, unfortunately in vain.
Can anyone provide a hint on how to proceed with this?
You need to generate an access token from the service account JSON key file using the Google API Python client library, and then add it to the headers of your request.
Here's an example of how to do it with requests
from oauth2client.service_account import ServiceAccountCredentials
import requests
import json
import httplib2
scopes = [
'https://www.googleapis.com/auth/firebase',
'https://www.googleapis.com/auth/userinfo.email',
"https://www.googleapis.com/auth/cloud-platform"
]
credentials = ServiceAccountCredentials.from_json_keyfile_name(
'/pathto/json_file.json', scopes)
headers = {"content-type": "application/json; charset=UTF-8"}
headers['Authorization'] = 'Bearer ' + credentials.get_access_token().access_token
firebase_url = "https://docs-examples.firebaseio.com/rest/saving-data/fireblog/users/alanisawesome/name.json"
data = {
"name": "Alan Turing",
"birthday": "June 23, 1912"}
requests.put(firebase_url, headers=headers, data=json.dumps(data).encode("utf-8"))
You can install the google python api client library using pip:
pip install --upgrade google-api-python-client
Related
I have an app where the frontend is using React and the backend is using django-rest-framework. The backend enforces CSRF which is needed, and I think everything will work fine in production because the backend and the frontend will share the same origin (https://mydomain.awesome).
But for local development I have a problem, my frontend is running on localhost:3000 and my backend is running on localhost:8000, and this means they are on different origins and my backend is not sending CSRF token to my frontend.
What do people do in this case? How can I have "same origin" in the local development environment?
You need to use a package called django-cors-headers
pip install django-cors-headers.
Then, in your Django project's settings.py, include the following line at the top of the MIDDLEWARE section:
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
'django.middleware.security.SecurityMiddleware',
... (other middlware)
]
Now, add the following lines in your settings.py:
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
"http://127.0.0.1:3000"
]
This makes it so that the frontend is allowed to make requests to your backend by using the Access-Control-Allow-Origin header.
If you need to pass along cookies (e.g. csrf token, credential tokens) with the request from your frontend to the server, additionally add the following line:
CORS_ALLOW_CREDENTIALS = True
Then, you would have to set up your request client on the frontend. I personally use axios:
const response = await axios.post(url, { ...data }, { withCredentials: true })
I actually created a fullstack todo app with django as backend and react as frontend. The frontend is working perfectly fine, you can that here -> https://ym-todo-application.herokuapp.com. But somehow my application cannot connect to the django backend, also on inspecting on browser i saw this error -> GET http://localhost:8000/api/todos/ net::ERR_CONNECTION_REFUSED.
Containing lot of files and code so i pushed them on bitbucket to make it easier to debug. here's the link https://bitbucket.org/Yash-Marmat/todo-app-fullstack/src/master/.
Thanks in advance.
You need to change the REST API server address. The localhost:8000 is the server address used in the development.
What is more, I see in your code that each time you write the request you have hard-coded server URL. You don't need to do this. You can set the server address by setting baseURL:
import axios from "axios";
if (window.location.origin === "http://localhost:3000") {
axios.defaults.baseURL = "http://127.0.0.1:8000"; // development address
} else {
axios.defaults.baseURL = window.location.origin; // production address
}
Then in the request, you only write the endpoint address, example:
axios.put(`/api/todos/${item.id}/`, item)
Please see my article Docker-Compose for Django and React with Nginx reverse-proxy and Let's Encrypt certificate for more details about Django and React deployment.
I'm trying to sign in with OAuth credentials which involves issuing an HTTP POST request to the Auth verifyAssertion endpoint. How would I go about doing this syntactically? I'm trying to follow this firebase documentation but they use curls for the examples.
https://firebase.google.com/docs/reference/rest/auth/#section-sign-in-with-oauth-credential
The endpoint is https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp?key=[API_KEY]
You can either choose the native fetch api with
window.fetch('https://url-you-want-to-post-to.com/', {method: 'POST', body: { //body data } })
or you can use a third-party library like axios (although you need to npm install it first and then import it)
I am trying to add a custom domain mapping to my App Engine app using the Google API (not through console). However, I keep getting 403 forbidden error when the http request is made with the Discovery API Client. I have obtained a credentials json file from App Engine with owner permissions and I point to that with the GOOGLE_APPLICATION_CREDENTIALS env variable. Since I have full permissions, I'm guessing the problem is I'm not using the API correctly but haven't been able to see what is missing.
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = os.path.dirname(__file__) + str('/json_cred_file')
apps_client = googleapiclient.discovery.build('appengine', 'v1beta')
response = apps_client.apps().domainMappings().create(
appsId='apps/myappname', body=json.loads(
'{"id": "newsubdomain.mydomain.com","sslSettings": '
'{"sslManagementType": "AUTOMATIC" }}')).execute()
Here is the error:
WARNING 2018-07-06 23:51:09,331 http.py:119] Encountered 403 Forbidden with reason "forbidden"
I contacted Google support and the issue is when using the domain mapping function, the service account needs to be added to the search console as an owner. This is the search console: https://www.google.com/webmasters/tools/home
They have a special page in their docs for using this library on app engine: https://developers.google.com/api-client-library/python/guide/google_app_engine
This is how I use the googleapiclient library. One difference I see is this line:
credentials = GoogleCredentials.get_application_default()
from oauth2client.client import GoogleCredentials
from lib.googleapiclient import discovery
class DataFlowJobsListHandler(AdminResourceHandler):
def get(self, resource_id=None):
"""
Wrapper to this:
https://cloud.google.com/dataflow/docs/reference/rest/v1b3/projects.jobs/list
"""
if resource_id:
self.abort(405)
else:
credentials = GoogleCredentials.get_application_default()
service = discovery.build('dataflow', 'v1b3', credentials=credentials)
project_id = app_identity.get_application_id()
_filter = self.request.GET.pop('filter', 'UNKNOWN').upper()
jobs_list_request = service.projects().jobs().list(
projectId=project_id,
filter=_filter) #'ACTIVE'
jobs_list = jobs_list_request.execute()
return {
'$cursor': None,
'results': jobs_list.get('jobs', []),
}
EDIT I posted an issue on this and it should be fixed in release 1.9.16 of Google AppEngine SDK.
https://code.google.com/p/googleappengine/issues/detail?id=11414
I am developing a service using Google Cloud Endpoints.
Both the REST and the RPC API works great when I deploy it on App Engine. However the strange thing is, when I test the service locally (localhost), the REST calls works fine, but I am having trouble with calls using RPC.
My method signature in the backend is:
#ApiMethod(name = "user.updateprofile", httpMethod = HttpMethod.POST)
public UserProfileDto updateProfile(#Named("sessionToken") String sessionToken, UserProfileDto profile) throws UnauthorizedException { return profile; }
For simplicity I am just returning the UserProfileDto directly.
I have tried to execute the following request locally:
POST http://localhost:4567/_ah/api/rpc?prettyPrint=false
Content-Type: application/json-rpc
Accept: application/json-rpc
{
"method": "mobilebackend.user.updateprofile",
"id": "gtl_1",
"jsonrpc": "2.0",
"params": {
"sessionToken": "12345",
"resource": {
"username": "foo",
"userPrivate": true
}
},
"apiVersion": "v1"
}
When I set a breakpoint in the updateProfile method, I see that the sessionToken is correctly 12345 however the username field is null and the userPrivate field is false even though I specified it as true. The instance of UserProfileDto (profile) is not null.
The problem is that it fails to inject the values into the fields of the DTO when using RPC calls localhost. When I test it on the deployed version it works fine, and when I use REST calls it works both on localhost and when deployed on App Engine.
When I change the url in the above request to target the deployed version of my application on app engine it works just fine. https://<app-name>.appspot.com/_ah/api/rpc?prettyPrint=false
I start the service on localhost using:
mvn appengine:devserver
Do I miss some configuration in order to call the Cloud Endpoints RPC methods localhost? Or is it not supported?
I should notice that I have also tried with the auto-generated iOS client library which is using RPC and it also fails with the same error as the service fails to inject the values into the fields of the DTO object.
I have tested release 1.9.17 of Google AppEngine SDK and can confirm that using objects in RPC POST requests now works fine.