diff --git a/docs/api.rst b/docs/api.rst index ff35369..3d10d5e 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -28,7 +28,7 @@ :settings: `OAUTH_EXPIRE_DELTA` :default: `datetime.timedelta(days=365)` - + The time to expiry for access tokens as outlined in :rfc:`4.2.2` and :rfc:`5.1`. @@ -36,9 +36,17 @@ :settings: `OAUTH_EXPIRE_CODE_DELTA` :default: `datetime.timedelta(seconds=10*60)` - + The time to expiry for an authorization code grant as outlined in :rfc:`4.1.2`. - + +.. attribute:: DELETE_EXPIRED + + :settings: `OAUTH_DELETE_EXPIRED` + :default: `False` + + To remove expired tokens immediately instead of letting them persist, set + to `True`. + .. attribute:: ENFORCE_SECURE :settings: `OAUTH_ENFORCE_SECURE` diff --git a/provider/constants.py b/provider/constants.py index 82587ab..7f94b8e 100644 --- a/provider/constants.py +++ b/provider/constants.py @@ -26,11 +26,15 @@ DEFAULT_SCOPES = ( SCOPES = getattr(settings, 'OAUTH_SCOPES', DEFAULT_SCOPES) EXPIRE_DELTA = getattr(settings, 'OAUTH_EXPIRE_DELTA', timedelta(days=365)) + # Expiry delta for public clients (which typically have shorter lived tokens) EXPIRE_DELTA_PUBLIC = getattr(settings, 'OAUTH_EXPIRE_DELTA_PUBLIC', timedelta(days=30)) EXPIRE_CODE_DELTA = getattr(settings, 'OAUTH_EXPIRE_CODE_DELTA', timedelta(seconds=10 * 60)) +# Remove expired tokens immediately instead of letting them persist. +DELETE_EXPIRED = getattr(settings, 'OAUTH_DELETE_EXPIRED', False) + ENFORCE_SECURE = getattr(settings, 'OAUTH_ENFORCE_SECURE', False) ENFORCE_CLIENT_SECURE = getattr(settings, 'OAUTH_ENFORCE_CLIENT_SECURE', True) diff --git a/provider/oauth2/models.py b/provider/oauth2/models.py index d6e6f8a..e4ab484 100644 --- a/provider/oauth2/models.py +++ b/provider/oauth2/models.py @@ -7,7 +7,7 @@ views in :attr:`provider.views`. from django.db import models from django.conf import settings from .. import constants -from ..constants import CLIENT_TYPES +from ..constants import CLIENT_TYPES, DELETE_EXPIRED from ..utils import short_token, long_token, get_token_expiry from ..utils import get_code_expiry from ..utils import now diff --git a/provider/oauth2/tests.py b/provider/oauth2/tests.py index 988af23..247f66e 100644 --- a/provider/oauth2/tests.py +++ b/provider/oauth2/tests.py @@ -533,19 +533,15 @@ class ScopeTest(TestCase): self.assertEqual('read read+write write', ' '.join(names)) -class CleanExpiredTest(BaseOAuth2TestCase): +class DeleteExpiredTest(BaseOAuth2TestCase): fixtures = ['test_oauth2'] def setUp(self): - self._old_oauth_clean_expired = getattr(settings, - 'OAUTH_CLEAN_EXPIRED', None) - settings.OAUTH_CLEAN_EXPIRED = True + self._delete_expired = constants.DELETE_EXPIRED + constants.DELETE_EXPIRED = True def tearDown(self): - if self._old_oauth_clean_expired is not None: - settings.OAUTH_CLEAN_EXPIRED = self._old_oauth_clean_expired - else: - delattr(settings, 'OAUTH_CLEAN_EXPIRED') + constants.DELETE_EXPIRED = self._delete_expired def test_clear_expired(self): self.login() @@ -563,8 +559,6 @@ class CleanExpiredTest(BaseOAuth2TestCase): code = urlparse.parse_qs(location)['code'][0] self.assertTrue(Grant.objects.filter(code=code).exists()) - from pprint import pprint - # use the code/grant response = self.client.post(self.access_token_url(), { 'grant_type': 'authorization_code', diff --git a/provider/oauth2/views.py b/provider/oauth2/views.py index fa9fbb1..d0de51d 100644 --- a/provider/oauth2/views.py +++ b/provider/oauth2/views.py @@ -1,6 +1,6 @@ from datetime import timedelta -from django.conf import settings from django.core.urlresolvers import reverse +from .. import constants from ..views import Capture, Authorize, Redirect from ..views import AccessToken as AccessTokenView, OAuthError from ..utils import now @@ -117,21 +117,21 @@ class AccessTokenView(AccessTokenView): ) def invalidate_grant(self, grant): - if getattr(settings, 'OAUTH_CLEAN_EXPIRED', False): + if constants.DELETE_EXPIRED: grant.delete() else: grant.expires = now() - timedelta(days=1) grant.save() def invalidate_refresh_token(self, rt): - if getattr(settings, 'OAUTH_CLEAN_EXPIRED', False): + if constants.DELETE_EXPIRED: rt.delete() else: rt.expired = True rt.save() def invalidate_access_token(self, at): - if getattr(settings, 'OAUTH_CLEAN_EXPIRED', False): + if constants.DELETE_EXPIRED: at.delete() else: at.expires = now() - timedelta(days=1) diff --git a/provider/views.py b/provider/views.py index 7c2a266..3b0bb1d 100644 --- a/provider/views.py +++ b/provider/views.py @@ -492,6 +492,7 @@ class AccessToken(OAuthView, Mixin): """ rt = self.get_refresh_token_grant(request, data, client) + # this must be called first in case we need to purge expired tokens self.invalidate_refresh_token(rt) self.invalidate_access_token(rt.access_token)