-
Notifications
You must be signed in to change notification settings - Fork 339
Revoke refresh token #123
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
Revoke refresh token #123
Conversation
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.
Looks mostly good. Just a number of nits to address.
CHANGELOG.md
Outdated
@@ -1,11 +1,18 @@ | |||
# Unreleased | |||
- | |||
### Token revokaction | |||
- [added] The ['verify_id_token(...)'](https://firebase.google.com/docs/reference/admin/python/firebase_admin.auth#verify_id_token) | |||
method can now take an additional parameter `check_revoked`, when `True`, |
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.
...method now accepts an optional check_revoked
argument. When set to True
an additional check is performed to see...
firebase_admin/_user_mgt.py
Outdated
@@ -113,6 +113,20 @@ def validate_photo_url(cls, photo_url): | |||
except Exception: | |||
raise ValueError('Malformed photo URL: "{0}".'.format(photo_url)) | |||
|
|||
@classmethod | |||
def validate_tokens_valid_after_time(cls, valid_since): | |||
if not isinstance(valid_since, six.string_types) or not valid_since: |
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.
How come this is a string?
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.
the other timestamps in the UserMetadata are also returned as quoted strings. (passwordUpdate is a float in the response, but all other timestamps are quoted.)
firebase_admin/_user_mgt.py
Outdated
try: | ||
int(valid_since) | ||
except ValueError: | ||
raise ValueError('Malformed Tokens Valid After Time: "{0}" ' |
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.
"Invalid tokens_valid_after_time value: {0}" should suffice here
firebase_admin/auth.py
Outdated
@@ -85,17 +85,27 @@ def verify_id_token(id_token, app=None): | |||
Args: | |||
id_token: A string of the encoded JWT. | |||
app: An App instance (optional). | |||
check_revoked: check whether the token was revoked(optional). |
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.
A boolean indicating whether the token has been revoked (optional).
firebase_admin/auth.py
Outdated
|
||
Returns: | ||
dict: A dictionary of key-value pairs parsed from the decoded JWT. | ||
|
||
Raises: | ||
ValueError: If the JWT was found to be invalid, or if the App was not | ||
initialized with a credentials.Certificate. | ||
AuthError: If check_token is requested and the token was revoked. |
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.
If check_revoked is requested...
firebase_admin/auth.py
Outdated
int: Timestap in seconds since the epoch. All tokens issued before that time | ||
are considered revoked. | ||
""" | ||
return int(self._data.get('validSince', 0)) |
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.
We seem to return 0 by default.
- Is that consistent with the behavior in Node SDK (perhaps
None
is more appropriate here)? - We should document this in the docstring.
tests/test_auth.py
Outdated
ids=list(invalid_tokens)) | ||
@pytest.mark.parametrize('id_token', valid_tokens.values(), ids=list(valid_tokens)) | ||
def test_valid_token_check_revoked(self, user_mgt_app_for_verify_token, id_token): | ||
_instrument_user_manager(user_mgt_app_for_verify_token, 200, MOCK_GET_USER_RESPONSE) |
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.
Also need a test case for when the UserRecord
contains a future timestamp.
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.
this is MOCK_GET_USER_REVOKED_TOKENS_RESPONSE
tests/test_auth.py
Outdated
auth.verify_id_token(id_token, app=user_mgt_app_for_verify_token, | ||
check_revoked=True) | ||
|
||
assert excinfo.value.code == 'ID_TOKEN_REVOKED' |
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.
Check against the constant once you have it
tests/test_auth.py
Outdated
assert claims['admin'] is True | ||
assert claims['uid'] == claims['sub'] | ||
|
||
def test_revoke_refresh_token(self, user_mgt_app): |
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.
Add test case for setting this via update_user()
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.
the revoke in turn calls update_user, do we want to explicitly do this with update user?
tests/test_auth.py
Outdated
@@ -287,6 +326,13 @@ def user_mgt_app(): | |||
yield app | |||
firebase_admin.delete_app(app) | |||
|
|||
@pytest.fixture(scope='module') | |||
def user_mgt_app_for_verify_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.
Can we just modify the existing user_mgt_app
fixture to have the project_id
option?
…dmin-python into revoke-refresh-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.
Looks mostly good. Few more changes and we would be at an LGTM.
CHANGELOG.md
Outdated
@@ -1,11 +1,19 @@ | |||
# Unreleased | |||
- | |||
### Token revokaction | |||
- [added] The ['verify_id_token(...)'](https://firebase.google.com/docs/reference/admin/python/firebase_admin.auth#verify_id_token) | |||
method now accepts an optional `check_revoked` parameter, when `True`, an |
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.
parameter. When True
...
CHANGELOG.md
Outdated
method now accepts an optional `check_revoked` parameter, when `True`, an | ||
additional check is performed to see if the token has been revoked. | ||
- [added] A new method ['auth.revoke_refresh_tokens(uid)'](https://firebase.google.com/docs/reference/admin/python/firebase_admin.auth#revoke_refresh_tokens) | ||
has been added to invalidate all tokens issued before the current second. |
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.
...issued to a user.
CHANGELOG.md
Outdated
- [added] A new method ['auth.revoke_refresh_tokens(uid)'](https://firebase.google.com/docs/reference/admin/python/firebase_admin.auth#revoke_refresh_tokens) | ||
has been added to invalidate all tokens issued before the current second. | ||
- [added] A new property `tokens_valid_after_time` has been added to the ['UserRecord'](https://firebase.google.com/docs/reference/admin/python/firebase_admin.auth#userrecord), | ||
it denotes the time in epoch milliseconds before which tokens are not valid. |
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.
which denotes..
firebase_admin/_user_mgt.py
Outdated
@@ -113,6 +113,20 @@ def validate_photo_url(cls, photo_url): | |||
except Exception: | |||
raise ValueError('Malformed photo URL: "{0}".'.format(photo_url)) | |||
|
|||
@classmethod | |||
def validate_valid_since(cls, valid_since): | |||
if not isinstance(valid_since, six.string_types) or not valid_since: |
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.
Why is this a string? It should just accept a timestamp.
firebase_admin/auth.py
Outdated
@@ -85,17 +86,27 @@ def verify_id_token(id_token, app=None): | |||
Args: | |||
id_token: A string of the encoded JWT. | |||
app: An App instance (optional). | |||
check_revoked: A boolean indicating whether the token has been revoked (optional). |
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.
whether to check if the token has been...
firebase_admin/auth.py
Outdated
|
||
def revoke_refresh_tokens(uid, app=None): | ||
user_manager = _get_auth_service(app).user_manager | ||
user_manager.update_user(uid, valid_since=str(int(time.time()))) |
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.
Why wrap this in str()? Just pass the int timestamp.
firebase_admin/auth.py
Outdated
@@ -476,12 +497,16 @@ def __init__(self, data): | |||
|
|||
@property | |||
def creation_timestamp(self): | |||
""" Creation timestamp in epoch milliseconds. | |||
""" |
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.
Add the Returns:
section too while we are at it?
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.
LGTM with a few nits.
CHANGELOG.md
Outdated
- [added] A new property `tokens_valid_after_time` has been added to the ['UserRecord'](https://firebase.google.com/docs/reference/admin/python/firebase_admin.auth#userrecord), | ||
has been added to invalidate all tokens issued to a user before the current second. | ||
- [added] A new property `tokens_valid_after_timestamp` has been added to the | ||
['UserRecord'](https://firebase.google.com/docs/reference/admin/python/firebase_admin.auth#userrecord), | ||
it denotes the time in epoch milliseconds before which tokens are not valid. |
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.
which denotes...
firebase_admin/_user_mgt.py
Outdated
raise ValueError('Malformed Valid Since "{0}".'.format(valid_since)) | ||
'Invalid time string for: "{0}". Valid Since must be an int'.format(valid_since)) | ||
if int(valid_since) <= 0: | ||
raise ValueError('Valid Since: must be a positive interger. {0}'.format(valid_since)) |
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.
Invalid valid_since: ...
?
firebase_admin/auth.py
Outdated
While this revokes all sessions for a specified user and disables any new ID tokens for | ||
existing sessions from getting minted, existing ID tokens may remain active until their | ||
natural expiration (one hour). To verify that ID tokens are revoked, use | ||
`verify_id_token(idToken, check_revoked=true)`. |
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.
check_revoked=True
tests/data/list_users.json
Outdated
@@ -49,7 +49,7 @@ | |||
"passwordUpdatedAt" : 1.494364393E+12, | |||
"validSince" : "1494364393", | |||
"disabled" : false, | |||
"createdAt" : "1234567890", | |||
"createdAt" : "1234567890000", | |||
"customAttributes" : "{\"admin\": true, \"package\": \"gold\"}" | |||
} ] | |||
} |
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.
Not really related to your change, but lets add a new line here.
Adding the revokeRefreshToken,
and the ability to check revoked when validating a token.