Gmail API OAuth2 Error: redirect_uri_mismatch

烈酒焚心 提交于 2019-12-11 12:59:42

问题


I followed this Gmail API Python Quickstart tutorial: https://developers.google.com/gmail/api/quickstart/python

I configured my OAuth client ID in the API console as instructed (see the first image below). However, launching the script opens a browser session that results in the 400 error below.

The redirect URL matches what is registered in the API console.

HOWEVER, the quickstart script opens the following URL: https://accounts.google.com/o/oauth2... &redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F ...

Manually changing redirect URI to http://localhost:8080 partially fixes the problem as I proceed to the authorization request, but then the response can't get returned to the command prompt.

How can I force the quickstart program to produce a URL that leaves the redirect URI as http://localhost:8080?


回答1:


The cause of the error you're getting is that the Python Quickstart says:

d. Select the Credentials tab, click the Create credentials button and select OAuth client ID.

e. Select the application type Other, enter the name "Gmail API Quickstart", and click the Create button.

However, looking at what you're doing, you are using Web Application instead of Other.

When I used the Other as client_secret.json, I didn't encounter this problem.

result:

The authentication flow has completed.

No hacks/workaround needed. Just follow instructions :)




回答2:


Explanation

This is happening because the uri_redirect parameter being passed to the Google API server is a percent encoded ASCII string. This can be verified by looking at the URL launched by the script:

...redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F...

The whole URL gets encoded by the quickstart script in the steps following the execution of this line:

credentials = tools.run_flow(flow, store, flags)

Stepping through the process with a debugger reveals the URL is eventually encoded with the urlencode method from Python's urllib library. This results in the redirect_uri parameter from the client_secret.json file converting from:

http://localhost:8080

To

http%3A%2F%2Flocalhost%3A8080%2F

When Google receives the OAuth request, it compares the encoded uri_redirect parameter against the un-encoded one registered in the API console. Since they don't match, a redirect_uri_mismatch is returned.

Solution

Ideally, Google should modify the API endpoint to ensure that this parameter is decoded if necessary before comparing it to what's registered in the API console.

An acceptable fix would be if the API console would accept encoded redirect URI entries, but it does not:

Workaround (warning: hacky)

Simply replace the encoded redirect_uri parameter in two places in the oauth2client library:

(1) update_query_params function in _helpers.py

...
start = new_query.find("redirect_uri")+13
end = new_query.find("&",start)
new_query2 = new_query[:start] + "http://localhost:8080" + new_query[end:]

new_parts = parts._replace(query=new_query2)
...

(2) step2_exchange in client.py

...
        body = urllib.parse.urlencode(post_data)
    start = body.find("redirect_uri")+13
    end = body.find("&",start)
    body2 = body[:start] + "http://localhost:8080" + body[end:]

    headers = {
        'content-type': 'application/x-www-form-urlencoded',
    }
    if self.authorization_header is not None:
        headers['Authorization'] = self.authorization_header
    if self.user_agent is not None:
        headers['user-agent'] = self.user_agent

    if http is None:
        http = transport.get_http_object()

    resp, content = transport.request(
        http, self.token_uri, method='POST', body=body2, headers=headers)
...

Now everything works.



来源:https://stackoverflow.com/questions/49527135/gmail-api-oauth2-error-redirect-uri-mismatch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!