google / gmail-oauth2-tools

Tools and sample code for authenticating to Gmail with OAuth2
Apache License 2.0
405 stars 211 forks source link

How to Use the Localhost Flow #75

Closed bazz1tv closed 2 months ago

bazz1tv commented 2 months ago

I figured out how to use the python/oauth2.py script with the localhost flow, ridding the need of relying on an external and potentially untrusted REDIRECT_URI. This method uses netcat.

Find in python/oauth2.py where REDIRECT_URI is defined and change it to something like:

# Hardcoded redirect URI.
REDIRECT_URI = 'http://localhost:8908/'

Then, in a shell, have netcat listen on that TCP port:

nc -l 8908

Finally, run python/oauth2.py. Click the link to authorize as per normal. Then, netcat will spit out the the code as part of its output, which you can copy and paste into the terminal oauth2.py is running in. I apologize for not having an example of the output but I've already generated everything and would prefer not to ruin today's efforts. Once you've got a refresh token, you're good to go. The browser itself will load indefinitely as it's waiting for a response from netcat, but it's safe to close.

junyer commented 2 months ago

Quoting issue https://github.com/google/gmail-oauth2-tools/issues/68:

The showstopper was not code complexity, but the requirement to support the browser being on another machine. My (extremely) layman's understanding is that using PKCE suffices to mitigate the risk if oauth2.dance gets hijacked.

oauth2.py doesn't use PKCE, but a contribution following, say, https://www.stefaanlippens.net/oauth-code-flow-pkce.html would most definitely be welcome!

bazz1tv commented 2 months ago

PKCE support is strengthening a remote connection rather than offering a local connection. I suggest adding a --localhost [port] flag for oauth2.py to offer localhost support. Would you accept this contribution?

junyer commented 2 months ago

No, sorry, but you might want to look into using https://github.com/googleapis/google-auth-library-python-oauthlib instead. Specifically, run_local_server() sounds like it facilitates precisely what you desire.