2

I access a Google calendar using a service account. This means that the owner of the calendar will not be prompted for his authorization.

This works fine in Python, where I make a requests call to https://accounts.google.com/o/oauth2/token with a specific body. This gets me back a token I can use later.

I now need to have an application running in a standalone browser (Chrome - without user interaction) and tried to directly port this call as

fetch('https://accounts.google.com/o/oauth2/token',
 {
 method: 'POST',
 body: JSON.stringify(body),
 })
 .then(function(res) { return res.json(); })
 .then(function(data) { alert(JSON.stringify(data)) })

but I get a reply from Google

Failed to load https://accounts.google.com/o/oauth2/token: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://devd.io' is therefore not allowed access. The response had HTTP status code 400. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

My limited understanding of CORS (a previous answer was a very good read) is that

No 'Access-Control-Allow-Origin' header is present on the requested resource

means that it is not present in the response headers, which means that Google does not want me to access its resources via JS when ran from the browser (which points to something else that https://accounts.google.com).

This may be a good idea but I control all elements, from the code to the browser and would like to get that token the same way I get it in a non-browser environment, specifically my working Python code.

How can I tell https://accounts.google.com to send me back a Access-Control-Allow-Origin header which tell my browser that it is OK to accept the call?

asked Oct 18, 2017 at 20:06
2
  • See stackoverflow.com/questions/43276462/… Commented Oct 18, 2017 at 21:51
  • @sideshowbarker: "OAuth2 auth endpoint doesn't support AJAX by design" -- I do not understand that point. AJAX, from the prespective of the server, is just a HTTP call. It does support non-interactive authentication (and the associated authorization for a given scope) - this works fine in my server code mentionned in the question. Commented Oct 19, 2017 at 6:03

2 Answers 2

6

You can't.

Client side and server side code need to interact with OAuth in different ways.

Google provide documentation explaining the client side process.

Importantly, part of it involves redirecting to Google's servers instead of accessing them with fetch or XMLHttpRequest.

answered Oct 18, 2017 at 20:14
Sign up to request clarification or add additional context in comments.

8 Comments

What I do not understand is that from python I can either make a call which requires a user authorisation (by copy paste a link received as a response) OR make a service account type of call where interactive authorization is not needed (it is provided to the service account upstream). Why not in JS? The context is the same (a human - less access to data) and the same rights for the requesting account.
I read the link you provided, it is great and very similar to the one in the python version of the docs (where explicit user authorisation may also be an option)
Moreover, the security implications are none - I will end up writing a python layer which will request, service account style, the data and provide them verbatim to my JS code. This could have happened directly in JS (I am not whining, just trying to understand the rationale)
In JS you can't hide the authorisation details from the user - so you'd have to provide the secret key etc. in the JS code. And since anyone using your page (including a bot) can view the browser code and debug the variable values, your secret key is then no longer secret. So that's why you can't use a service account from JS, as I understand it. Whereas Oauth is fine in JS because you ask the user themselves for their credentials, not yours.
@ADyson: these are fair points - but in my case I control the code and the browser (thi sis a kiosk or dashboard kind of application).
|
0

@Quentin's answer "You can't" is the right one for my question ("how can I force the server to send back the right header").

This is a decision at Google not to provide this header, effectively cutting off any non-interactive applications.

As a solution, I will look at

  • how to force the browser not to take into account the security mechanisms provided by CORS (there seems to be some ways through extensions or command-line arguments, I will update this answer once I find it)
  • or write an intermediate layer which will query the data for me and pass them verbatim to the application (this is equivalent, in my case, of just making the query from JS - but it adds an extra layer of code and server)
answered Oct 19, 2017 at 6:08

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.