-
Notifications
You must be signed in to change notification settings - Fork 4
oauth token caching #110
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
oauth token caching #110
Changes from 3 commits
9cc845a
856d026
9659cc0
640c463
fe71863
fa31d95
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |
| from datetime import datetime | ||
| import hashlib | ||
| import json | ||
| from os import path | ||
| from urllib.parse import urlencode, urlsplit, quote | ||
| from urllib.request import Request, urlopen | ||
|
|
||
|
|
@@ -40,6 +41,7 @@ | |
| GRANT_TYPE_KEY = "grant_type" | ||
| CLIENT_CREDENTIALS_KEY = "client_credentials" | ||
| EXPIRES_IN_KEY = "expires_in" | ||
| SCOPE = "scope" | ||
|
|
||
|
|
||
| _empty = bytes("", encoding="utf8") | ||
|
|
@@ -119,13 +121,52 @@ def _print_request(req: Request, level=0): | |
| print(json.dumps(json.loads(req.data.decode("utf8")), indent=2)) | ||
|
|
||
|
|
||
| def _cache_file() -> str: | ||
| return path.join(path.expanduser('~'), '.rai', 'tokens.json') | ||
|
|
||
|
|
||
| # Read oauth cache | ||
| def _read_cache() -> dict: | ||
| try: | ||
| with open(_cache_file(), 'r') as cache: | ||
| return json.loads(cache.read()) | ||
| except Exception: | ||
| return None | ||
|
|
||
|
|
||
| # Read access token from cache | ||
| def _read_token_cache(creds: ClientCredentials) -> AccessToken: | ||
| try: | ||
| cache = _read_cache() | ||
| return AccessToken(**cache[creds.client_id]) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume if the cache doesn't contain that client id an exception is thrown?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep that's true and we just by-pass it, if |
||
| except Exception: | ||
| return None | ||
|
|
||
|
|
||
| # write access token to cache | ||
| def _write_token_cache(creds: ClientCredentials): | ||
| try: | ||
| cache = _read_cache() | ||
| if cache: | ||
| cache[creds.client_id] = creds.access_token | ||
| else: | ||
| cache = {creds.client_id: creds.access_token} | ||
|
||
| with open(_cache_file(), 'w') as f: | ||
| f.write(json.dumps(cache, default=vars)) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what's
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is one way to make python class json serializable |
||
| except Exception: | ||
| pass | ||
|
|
||
|
|
||
| # Returns the current access token if valid, otherwise requests new token. | ||
| def _get_access_token(ctx: Context, url: str) -> AccessToken: | ||
| creds = ctx.credentials | ||
| assert isinstance(creds, ClientCredentials) | ||
| if creds.access_token is None or creds.access_token.is_expired(): | ||
| creds.access_token = _request_access_token(ctx, url) | ||
| return creds.access_token.token | ||
| creds.access_token = _read_token_cache(creds) | ||
| if creds.access_token is None or creds.access_token.is_expired(): | ||
| creds.access_token = _request_access_token(ctx, url) | ||
| _write_token_cache(creds) | ||
| return creds.access_token.access_token | ||
|
|
||
|
|
||
| def _request_access_token(ctx: Context, url: str) -> AccessToken: | ||
|
|
@@ -158,7 +199,8 @@ def _request_access_token(ctx: Context, url: str) -> AccessToken: | |
| token = result.get(ACCESS_KEY_TOKEN_KEY, None) | ||
| if token is not None: | ||
| expires_in = result.get(EXPIRES_IN_KEY, None) | ||
| return AccessToken(token, expires_in) | ||
| scope = result.get(SCOPE, None) | ||
| return AccessToken(token, scope, expires_in) | ||
| raise Exception("failed to get the access token") | ||
|
|
||
|
|
||
|
|
||
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 see we swallow these exceptions in these cache functions (the go sdk does sth similar as well). Is that on purpose?
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.
as far as I do understand, if the cache is not accessible for some reason we should not block the user and instead we request a new token