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

feat: all asynchronous credential types required for all authentication types (service accounts, default... etc) #573

Merged
merged 24 commits into from Jul 31, 2020

Conversation

anibadde
Copy link
Contributor

@anibadde anibadde commented Jul 28, 2020

PR # 2 for AsyncIO Auth Library:

  • Implemented all asynchronous credentials types
    • oauth2
      • client
      • credentials (inherited from credentials_async)
      • service account
    • JSON Web Token
    • default credentials

@google-cla
Copy link

google-cla bot commented Jul 28, 2020

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here with @googlebot I signed it! and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

ℹ️ Googlers: Go here for more info.

@google-cla google-cla bot added the cla: no This human has *not* signed the Contributor License Agreement. label Jul 28, 2020
@frankyn frankyn changed the base branch from master to async July 28, 2020 16:52
@google-cla google-cla bot added cla: yes This human has signed the Contributor License Agreement. and removed cla: no This human has *not* signed the Contributor License Agreement. labels Jul 28, 2020
from google.auth import exceptions


def _warn_about_problematic_credentials(credentials):
Copy link
Contributor

Choose a reason for hiding this comment

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

extract to a helper to share?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to extract from auth/_default

@@ -62,7 +63,10 @@ async def before_request(self, request, method, url, headers):
# the http request.)

if not self.valid:
self.refresh(request)
if inspect.iscoroutinefunction(self.refresh):
Copy link
Contributor

Choose a reason for hiding this comment

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

what is the scenario where this wouldn't be a coroutine?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are a couple of async credentials scenarios where self.refresh for those class instances return a None Type object (when it is not an async function). We run into this in an auth/jwt credentials object, and therefore add the check on whether refresh for that specific class instance is a coroutine or not.

from google.auth import jwt


def encode(signer, payload, header=None, key_id=None):
Copy link
Contributor

Choose a reason for hiding this comment

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

The top level methods of this don't appear to be specific to async. If that is so, you can get them here with from google.auth.jwt import encode, _unverified_decode...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Made this change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Turns out that the jwt_async test file defines our async version of the jwt token, and then calls encode/decode etc with the token object, so the direct import of that form wouldn't account for a token.decode/token.encode statement. Is there another way I could do the import to make that type of logic work? The reasoning is that there could be external locations where these encode/decode etc methods are called on the async tokens, so I'm leaning towards the current approach to account for those cases.

)

"""
except exceptions.TransportError as caught_exc:
Copy link
Contributor

Choose a reason for hiding this comment

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

commented out code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Deleted.

if hasattr(response_body1, "decode")
else response_body1
)
# CHANGE TO READ TO END OF STREAM
Copy link
Contributor

Choose a reason for hiding this comment

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

TODO?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Made this change as the approach to reading in the http response was modified, comment deleted.

error_code = response_data.get("error") or ""
if (
any(e == "internal_failure" for e in (error_code, error_desc))
and retry < 1
Copy link
Contributor

Choose a reason for hiding this comment

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

the condition for controlling the number of loops is pretty buried. I also think you may be able to use an existing retry helper for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought about changing this logic but am wary of diverging from the sync implementation of the error handling as we would want both to behave the same for consistency (especially if a user does use both async and sync clients). I would like to further understand the reasoning for using an existing retry helper so we could clarify this in our next call.

import sys

import mock
import oauth2client.client
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't appear to be testing an async module, at least according to the naming. Is this a direct copy of what is in tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These do test the async _oauth2client internal to the auth library implementation. The other library that is imported is from https://github.com/googleapis/oauth2client, and the tests in this file test conversion between credentials from the oauth2client to the types of async credentials that we define in the auth library and that are added to this PR. Therefore, though these tests parallel those of the sync oauth2client, they use the async version and are as a result not a direct copy.

@@ -1,4 +1,4 @@
# Copyright 2016 Google LLC
# Copyright 2020 Google LLC
Copy link
Contributor

Choose a reason for hiding this comment

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

similar, is this a test that is unique to async? If not we shouldn't duplicate it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These tests are unique to async, I changed the names of the test files so that this is clear. The import of credentials_async is renamed to credentials to make writing the tests shorter but we need to test the new async constructions.


if credentials.client_id == _cloud_sdk.CLOUD_SDK_CLIENT_ID:
warnings.warn(_default._CLOUD_SDK_CREDENTIALS_WARNING)
return _default._warn_about_problematic_credentials(credentials)
Copy link
Contributor

Choose a reason for hiding this comment

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

99% sure you can just import _warn_about_problematic credentials and not wrap it here, further reducing duplication.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense, made the modification to directly import and remove this method.

Comment on lines 15 to 20
"""Helpers for transitioning from oauth2client to google-auth.

.. warning::
This module is private as it is intended to assist first-party downstream
clients with the transition from oauth2client to google-auth.
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm I'd kind of be alright with us not having this in the async version, given that oauth2client has been deprecated for a few years now. @crwilcox @anibadde thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Interesting, wasn't aware that oauth2client had been depricated - As long as this isn't used in any of the other internal libraries like resumable media it may make sense to remove it if it is not going to be used.

Copy link
Contributor

Choose a reason for hiding this comment

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

sgtm :)

Copy link

@tritone tritone left a comment

Choose a reason for hiding this comment

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

Generally looks good aside from issues already raised by @crwilcox

noxfile.py Outdated
@@ -1,4 +1,4 @@
# Copyright 2019 Google LLC
# Copyright 2020 Google LLC
Copy link

Choose a reason for hiding this comment

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

This should be reverted to 2019 since it's not a new file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed.

@crwilcox crwilcox merged commit b822e48 into googleapis:async Jul 31, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants