Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add InstalledAppFlow #128

Merged
merged 7 commits into from
Mar 22, 2017
Merged

Add InstalledAppFlow #128

merged 7 commits into from
Mar 22, 2017

Conversation

theacodes
Copy link
Contributor

Resolves #122

@theacodes
Copy link
Contributor Author

This is DO NOT MERGE because I want a sanity check before I go any further.

  1. What do you think about this being in the library in general?
  2. What do you think about the way the implementation is structured?

Specifically for (2), I had some thoughts that it might make more sense to separate the strategies into separate classes:

flow = google.oauth2.flow.InstalledAppFlow.from_client_secrets_file(...)

strategy = flow.ServerStrategy(port=9000)
# or
strategy = flow.ConsoleStrategy()

flow.run(strategy)
# or
flow.strategy = strategy
flow.run()

But I'm unsure if that's over-engineering, even if it feels cleaner.

@theacodes
Copy link
Contributor Author

/cc @proppy

@lukesneeringer
Copy link

Can you provide some sample code for what it looks like with a single, combined flow? It would make it easier to reason about without doing a deep dive.

@theacodes
Copy link
Contributor Author

@lukesneeringer not sure what you're asking for.

@lukesneeringer
Copy link

@lukesneeringer not sure what you're asking for.

I was referring to (2) specifically.

Right now it seems to be:

flow = InstalledAppFlow(...)
flow.run(strategy=SERVER, port=9000)

I think that is fine. I do not think strategy objects are necessary. And it does seem reasonable that some arguments (like port) are ignored if they are not applicable to the strategy in use.

@theacodes
Copy link
Contributor Author

@lukesneeringer that's nearly correct, it would be:

flow = InstalledAppFlow(...)
flow.web_port = 9000
flow.run(strategy=SERVER)

I can keep that same interface but separate the internals into two separate strategy classes. Curious as to what @dhermes thinks as well.

@lukesneeringer
Copy link

lukesneeringer commented Mar 2, 2017

That makes a little less sense to me, but it certainly seems good enough. And it is probably better than making the user create a strategy object.

@theacodes
Copy link
Contributor Author

That makes a little less sense to me

It makes more sense to pass into run then we can do that. There's plenty of malleability here.

Another option is to have two runs: run_console and run_server.

@lukesneeringer
Copy link

Oooh, I think run_console and run_server taking the appropriate arguments is a good approach.

@theacodes
Copy link
Contributor Author

Oooh, I think run_console and run_server taking the appropriate arguments is a good approach.

Cool, that's what I'll go with. I'll remove run and just have run_server and run_console.

@theacodes theacodes changed the title [DO NOT MERGE] Add InstalledAppFlow Add InstalledAppFlow Mar 16, 2017
@theacodes
Copy link
Contributor Author

@dhermes @lukesneeringer this is ready for review. :)

@theacodes
Copy link
Contributor Author

@proppy it would be super cool if you took a look as well.

@@ -15,7 +15,7 @@
"""OAuth 2.0 Authorization Flow

.. warning::
This module is experimental and is subject to change signficantly
This module is experimental and is subject to change significantly

This comment was marked as spam.

@@ -54,12 +54,22 @@
"""

import json
import logging
import webbrowser

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


import google.auth.transport.requests
import google.oauth2.credentials
import google.oauth2.oauthlib


_LOGGER = logging.getLogger(__name__)

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


import google.oauth2.flow

flow = google.oauth2.flow.InstalledAppFlow.from_client_secrets_file(

This comment was marked as spam.

This comment was marked as spam.

google/oauth2/flow.py Outdated Show resolved Hide resolved
"""
kwargs.setdefault('prompt', 'consent')

self.redirect_uri = self._OOB_REDIRECT_URI

This comment was marked as spam.

This comment was marked as spam.


auth_url, _ = self.authorization_url(**kwargs)

print(authorization_prompt_message.format(url=auth_url))

This comment was marked as spam.

This comment was marked as spam.

code is then exchanged for a token.

Args:
host (str): The web host for the local redirect server.

This comment was marked as spam.

This comment was marked as spam.


return self.credentials

class _LocalRedirectServer(BaseHTTPServer.HTTPServer):

This comment was marked as spam.

This comment was marked as spam.

setup.py Outdated
@@ -39,7 +39,7 @@
description='Google Authentication Library',
long_description=long_description,
url='https://github.com/GoogleCloudPlatform/google-auth-library-python',
packages=find_packages(exclude=('tests', 'system_tests')),
packages=find_packages(exclude=('tests*', 'system_tests*')),

This comment was marked as spam.

This comment was marked as spam.

local_server = self._LocalRedirectServer(
success_message, (host, port), self._LocalRedirectRequestHandler)

webbrowser.open(auth_url, new=1, autoraise=True)

This comment was marked as spam.

This comment was marked as spam.

self.success_message = success_message
self.last_request_path = None

class _LocalRedirectRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):

This comment was marked as spam.

This comment was marked as spam.

@proppy
Copy link

proppy commented Mar 17, 2017

do we want a "smart" run that fallback to run_console if opening the browser failed?

@theacodes
Copy link
Contributor Author

do we want a "smart" run that fallback to run_console if opening the browser failed?

Webbrowser doesn't give us any indication if the open call was successful or not.

@theacodes
Copy link
Contributor Author

@dhermes @lukesneeringer should be good to review again.

Copy link
Contributor

@dhermes dhermes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM I think?

@@ -54,12 +54,22 @@
"""

import json
import logging
import webbrowser

This comment was marked as spam.


import google.auth.transport.requests
import google.oauth2.credentials
import google.oauth2.oauthlib


_LOGGER = logging.getLogger(__name__)

This comment was marked as spam.

@theacodes
Copy link
Contributor Author

I meant "having this code period"

The good news is that it's in a separate package now, woohoo. :)

@theacodes theacodes merged commit 41a2bba into master Mar 22, 2017
@theacodes theacodes deleted the installed-flow branch March 22, 2017 20:43

auth_url, _ = self.authorization_url(**kwargs)

print(authorization_prompt_message.format(url=auth_url))

This comment was marked as spam.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants