def revoke(self, request, pk=None): access_tokens = get_access_token_model().objects.filter(application=pk) refresh_tokens = get_refresh_token_model().objects.filter( application=pk) for access_token in access_tokens: access_token.revoke() for refresh_token in refresh_tokens: refresh_token.revoke() return Response(status=status.HTTP_204_NO_CONTENT)
def revoke_tokens(app_id, user_id): app = get_application_model().objects.filter(id=app_id) user = User.objects.get(pk=user_id) if app.exists(): app = app.first() refresh_tokens = get_refresh_token_model().objects.filter( user=user, application=app) for token in refresh_tokens: token.revoke() access_tokens = get_access_token_model().objects.filter( user=user, application=app) for token in access_tokens: token.revoke()
class SSORefreshTokenViewSet(viewsets.ReadOnlyModelViewSet): """ A `Refresh Token` is an issued token which can be used for generating new access tokens without asking the user to consent again. """ serializer_class = SSORefreshTokenSerializer queryset = get_refresh_token_model().objects.all() permission_classes = [TokenHasScopeOrSuperUser] @action(detail=False, methods=["GET"]) def get_own(self, request): return get_refresh_token_model().objects.filter(user=request.user)
def form_valid(self, form): user = self.request.user app_id = form.cleaned_data['app_id'] self.log.info('Revoking all oauth tokens for user %s, application %d', user, app_id) rt_model = oauth2_models.get_refresh_token_model() at_model = oauth2_models.get_access_token_model() gr_model = oauth2_models.get_grant_model() rt_model.objects.filter(user=user, application=app_id).delete() at_model.objects.filter(user=user, application=app_id).delete() gr_model.objects.filter(user=user, application=app_id).delete() return super().form_valid(form)
def post(self, request): app_id = request.POST.get('application_id', False) app = get_application_model().objects.filter(id=app_id) if app.exists(): app = app.first() refresh_tokens = get_refresh_token_model().objects.filter( user=request.user, application=app) for token in refresh_tokens: token.revoke() access_tokens = get_access_token_model().objects.filter( user=request.user, application=app) for token in access_tokens: token.revoke() messages.add_message(request, messages.SUCCESS, f'Acesso de {app.name} revogado com sucesso') return redirect('apps_connected')
def test_set_password_revoke_oauth2_tokens(self): org = setup_org() setup_admin(org) user = setup_user(org) application_model = get_application_model() application = application_model.objects.create( name="Test app", redirect_uris="http://example.org/redirect", client_type=application_model.CLIENT_PUBLIC, authorization_grant_type=application_model. GRANT_AUTHORIZATION_CODE, skip_authorization=False, ) access_token_model = get_access_token_model() access_token = access_token_model.objects.create( user=user, scope="read", expires=timezone.now() + timedelta(seconds=3600), token="ACCESS-TOKEN", application=application, ) refresh_token_model = get_refresh_token_model() refresh_token = refresh_token_model.objects.create( user=user, token="REFRESH_TOKEN", application=application, access_token=access_token, ) self.assertIsNone(refresh_token.revoked) user.set_password("Changed password") with self.assertRaises(access_token_model.DoesNotExist): access_token.refresh_from_db() refresh_token.refresh_from_db() self.assertIsNotNone(refresh_token.revoked)
from django.test import TestCase from django.core.urlresolvers import reverse from django.contrib.auth import get_user_model from oauth2_provider.models import get_access_token_model, get_refresh_token_model AccessToken = get_access_token_model() RefreshToken = get_refresh_token_model() User = get_user_model() # We don't import django.contrib.auth.models.User directly. Instead, we use # django.contrib.auth.get_user_model() as described at: # https://docs.djangoproject.com/en/1.9/topics/auth/customizing/ class BlenderIdAddonSupportTest(TestCase): fixtures = ['bid_addon_support/fixtures/bid_addon_support'] def setUp(self): self._create_user() def test_verify_identity_happy(self, email='*****@*****.**', password='******'): """ Happy flow of the Blender ID add-on authentication. """ url = reverse('addon_support:identify') resp = self.client.post(url, { 'email': email, 'password': password,
from urllib.parse import urlencode from django.contrib.auth import get_user_model from django.test import RequestFactory, TestCase from django.urls import reverse from django.utils import timezone from oauth2_provider.models import ( get_access_token_model, get_application_model, get_refresh_token_model ) from oauth2_provider.settings import oauth2_settings Application = get_application_model() AccessToken = get_access_token_model() RefreshToken = get_refresh_token_model() UserModel = get_user_model() class BaseTest(TestCase): def setUp(self): self.factory = RequestFactory() self.test_user = UserModel.objects.create_user("test_user", "*****@*****.**", "123456") self.dev_user = UserModel.objects.create_user("dev_user", "*****@*****.**", "123456") self.application = Application( name="Test Application", redirect_uris="http://localhost http://example.com http://example.org", user=self.dev_user, client_type=Application.CLIENT_CONFIDENTIAL, authorization_grant_type=Application.GRANT_AUTHORIZATION_CODE,
list_display = ("jti", "user", "application", "expires") raw_id_fields = ("user", ) search_fields = ("user__email", ) if has_email else () list_filter = ("application", ) class RefreshTokenAdmin(admin.ModelAdmin): list_display = ("token", "user", "application") raw_id_fields = ("user", "access_token") search_fields = ("token", ) + (("user__email", ) if has_email else ()) list_filter = ("application", ) application_model = get_application_model() access_token_model = get_access_token_model() grant_model = get_grant_model() id_token_model = get_id_token_model() refresh_token_model = get_refresh_token_model() application_admin_class = get_application_admin_class() access_token_admin_class = get_access_token_admin_class() grant_admin_class = get_grant_admin_class() id_token_admin_class = get_id_token_admin_class() refresh_token_admin_class = get_refresh_token_admin_class() admin.site.register(application_model, application_admin_class) admin.site.register(access_token_model, access_token_admin_class) admin.site.register(grant_model, grant_admin_class) admin.site.register(id_token_model, id_token_admin_class) admin.site.register(refresh_token_model, refresh_token_admin_class)
def migrate_oauth_tokens(self): from oauth2_provider import models as oa2_models from django.contrib.auth import get_user_model app_model = oa2_models.get_application_model() at_model = oa2_models.get_access_token_model() rt_model = oa2_models.get_refresh_token_model() user_model = get_user_model() # Old database: # +---------------+--------------+------+-----+---------+----------------+ # | Field | Type | Null | Key | Default | Extra | # +---------------+--------------+------+-----+---------+----------------+ # | id | int(11) | NO | PRI | NULL | auto_increment | # | client_id | varchar(40) | NO | MUL | NULL | | # | user_id | int(11) | NO | MUL | NULL | | # | token_type | varchar(40) | YES | | NULL | | # | access_token | varchar(255) | YES | UNI | NULL | | # | refresh_token | varchar(255) | YES | UNI | NULL | | # | expires | datetime | YES | | NULL | | # | _scopes | text | YES | | NULL | | # | host_label | varchar(255) | YES | | NULL | | # | subclient | varchar(40) | YES | | NULL | | # +---------------+--------------+------+-----+---------+----------------+ migrated = 0 # Get an in-memory maping from client ID to application. apps = {app.client_id: app for app in app_model.objects.all()} # Some optimisation to only fetch a user when it's different than the previous one. last_user = None skip_user_id = None # noinspection PyProtectedMember sql = ( f"SELECT client_id, user_id, access_token, refresh_token, expires, " f"_scopes as scopes, host_label, subclient " f"FROM token " f"WHERE " f" expires > now() " f" and access_token not in (select token from {at_model._meta.db_table}) " f" and refresh_token not in (select token from {rt_model._meta.db_table}) " f"ORDER BY user_id") for result in query(sql): # Some optimisation to only fetch a user when it's different than the previous one. if skip_user_id is not None: if result.user_id == skip_user_id: continue # We've skipped that user, time to forget about it. skip_user_id = None if last_user is None or last_user.id != result.user_id: try: user = user_model.objects.get(id=result.user_id) except user_model.DoesNotExist: self.stdout.write( self.style.WARNING( f'User {result.user_id} does not exist, skipping tokens' )) skip_user_id = result.user_id continue last_user = user else: user = last_user app = apps[result.client_id] at = at_model( user=user, token=result.access_token, application=app, expires=localise_datetime(result.expires), scope=result.scopes or '', host_label=result.host_label or '', subclient=result.subclient or '', ) at.save() if result.refresh_token: rt = rt_model( user=user, token=result.refresh_token, application=app, access_token=at, ) rt.save() migrated += 1 self.stdout.write( self.style.SUCCESS('Migrated %d OAuth2 tokens' % migrated))
def get_own(self, request): return get_refresh_token_model().objects.filter(user=request.user)
class Meta: model = get_refresh_token_model() fields = ["id", "created", "updated", "revoked", "user", "application"]
from django.contrib.auth.mixins import LoginRequiredMixin from django.http import HttpResponse, JsonResponse, HttpResponseBadRequest from django.utils.decorators import method_decorator from django.utils import timezone from django.core import exceptions as django_exc import oauth2_provider.models as oa2_models from oauth2_provider.views.generic import ProtectedResourceView import oauthlib.common # Braces is a dependency of oauth2_provider. from braces.views import CsrfExemptMixin AccessToken = oa2_models.get_access_token_model() RefreshToken = oa2_models.get_refresh_token_model() Application = oa2_models.get_application_model() # Oops, I (Sybren) made a mistake in the Blender ID add-on and used the # wrong datetime format string to parse the new format. Can't easily # change the add-on as it's bundled with Blender, so for now let's use # the expected format for the expiry date here. EXPIRY_DATE_FMT = '%Y-%m-%dT%H:%M:%S.%fZ' def index(request): return HttpResponse('This is an API end-point for the Blender ID add-on.') class HttpResponseUnauthorized(HttpResponse): status_code = 401