-
Notifications
You must be signed in to change notification settings - Fork 311
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: add to_json
method to google.oauth2.credentials.Credentials
#367
Conversation
Hi @patkasper - apologies for it taking a long time to comment on this. I brought up credentials storage in a weekly meeting and it looks like folks are generally opposed to the idea of this library handling credentials storage. It may be convenient to store credentials in memory or in a file, but it isn't great from a security perspective. There was interest in adding a method like |
I've removed the storage interface and I've kept the I'm happy to add the storage interface + automated loading/storing to google-auth-oauthlib, should I go ahead with that? Thanks. |
google/auth/_helpers.py
Outdated
@@ -232,3 +241,34 @@ def unpadded_urlsafe_b64encode(value): | |||
Union[str|bytes]: The encoded value | |||
""" | |||
return base64.urlsafe_b64encode(value).rstrip(b'=') | |||
|
|||
|
|||
def validate_file(filename): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this function is used anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, that was a remnant from my earlier additions. Removing.
google/oauth2/credentials.py
Outdated
Raises: | ||
ValueError: If the file is not in the expected format. | ||
""" | ||
with io.open(filename, 'r', encoding='utf-8') as json_file: | ||
data = json.load(json_file) | ||
return cls.from_authorized_user_info(data, scopes) | ||
|
||
def to_json(self, strip=None, indent=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to remove indent
. If the user would like to do more formatting they can do it with the return value from this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, no problem.
google/oauth2/credentials.py
Outdated
@@ -160,13 +165,12 @@ def from_authorized_user_info(cls, info, scopes=None): | |||
|
|||
Args: | |||
info (Mapping[str, str]): The authorized user info in Google | |||
format. | |||
format. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean to change the indent here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Funny, there are a few occurrences where the indent is not what I had locally. Not sure what happened.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind reverting these whitespace changes?
google/auth/_helpers.py
Outdated
warnings.warn(_MISSING_FILE_MESSAGE.format(filename)) | ||
|
||
|
||
def parse_expiry(expiry): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this function used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes coming!
google/auth/_helpers.py
Outdated
@@ -232,3 +241,34 @@ def unpadded_urlsafe_b64encode(value): | |||
Union[str|bytes]: The encoded value | |||
""" | |||
return base64.urlsafe_b64encode(value).rstrip(b'=') | |||
|
|||
|
|||
def validate_file(filename): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, that was a remnant from my earlier additions. Removing.
google/oauth2/credentials.py
Outdated
@@ -160,13 +165,12 @@ def from_authorized_user_info(cls, info, scopes=None): | |||
|
|||
Args: | |||
info (Mapping[str, str]): The authorized user info in Google | |||
format. | |||
format. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Funny, there are a few occurrences where the indent is not what I had locally. Not sure what happened.
google/oauth2/credentials.py
Outdated
Raises: | ||
ValueError: If the file is not in the expected format. | ||
""" | ||
with io.open(filename, 'r', encoding='utf-8') as json_file: | ||
data = json.load(json_file) | ||
return cls.from_authorized_user_info(data, scopes) | ||
|
||
def to_json(self, strip=None, indent=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, no problem.
google/oauth2/credentials.py
Outdated
@@ -160,13 +165,12 @@ def from_authorized_user_info(cls, info, scopes=None): | |||
|
|||
Args: | |||
info (Mapping[str, str]): The authorized user info in Google | |||
format. | |||
format. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind reverting these whitespace changes?
google/oauth2/credentials.py
Outdated
Args: | ||
strip (Sequence[str]): Optional list of members to exclude from the | ||
generated JSON. | ||
indent (int): This parameter is passed to `json.dumps` to create |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove the documentation for this arg
google/oauth2/credentials.py
Outdated
Raises: | ||
ValueError: If the file is not in the expected format. | ||
""" | ||
with io.open(filename, 'r', encoding='utf-8') as json_file: | ||
data = json.load(json_file) | ||
return cls.from_authorized_user_info(data, scopes) | ||
|
||
def to_json(self, strip=None): | ||
"""Utility function that creates JSON repr. of a Credentials object. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"""Utility function that creates JSON repr. of a Credentials object. | |
"""Utility function that creates JSON representation of a Credentials object. |
to_json
method to google.oauth2.credentials.Credentials
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@patkasper This looks good! I am doing some cleanup of the CI in another PR, but I will merge this once that is resolved.
Thank you for all the work you've put into this!
👋 Hi @patkasper. Would you mind resolving the merge conflicts here? |
@patkasper Would you be able to run the code formatter?
If nox gives you trouble for any reason you can also do:
@michaelawyu If you're around next week could you help see this PR over the finish line? Since Patrick is an external contributor the CI does not trigger automatically. You'll have to add the label |
@patkasper @busunkim96 I noticed this evening that I cannot round-trip a credential using "to_json" to serialize the object, and then reload. I hit this when deserializing my credential and attempting to use it with a Dialogflow client; in that case, I received:
The hint here was the "billing quota"; when I compared the dict representations of the original and serialized-then-serialized clone of the original object, I saw that the "_quota_project_id" attribute was missing on the clone. Sure enough, after I added this in manually, my credential works. Was the "quota_project_id" attribute intentionally excluded from the contents of the json blob, on serialization? If not, I am happy to work up a PR to include that attribute in the serialization (it is a kwarg of the initializaer of the Credentials class, so very easy to round-trip). One other minor note; the serialized-then-serialized clone of the original credential cannot itself be serialized with to_json if the expiry kwarg is naively set to the expiry string from the serialization dict. This happened to me when I tried to naively deserialize by just "**" unpackinging the dictionary contents into the kwargs of the initializer. Then this line fails because self.expiry is a string, not a datetime. This should be pretty easy to fix with a isinstance or try-catch, and I am happy to provide a PR here as well. What are your thoughts on these issues? |
This adds a
Storage
base interface class and afile
module based onStorage
to save and load credentials.The
credentials
module was modified to rely on the newerStorage
class while retaining compatibility.