2

私は python-social-auth と django-rest-framework を使用して、ユーザーが自分のアプリでソーシャル アカウントにサインアップできるようにしています。

私のケースはこの投稿に似て います Facebookでログインした後にユーザーが作成されない (おそらく同名のケース)

django-rest-framework の TokenAuthentication を使用してユーザーを認証します

私のカスタム ユーザー モデルを使用している場合、ヘッダーで認証トークンが使用可能な場合 (ユーザーがログインしている場合)、作成されたソーシャル ユーザー アカウントは、トークンが要求に添付されているユーザーにリンクされますが、使用可能なトークンがない場合は、新しいアカウントを作成できません。

しかし、デフォルトの django ユーザー モデルを使用すると、すべてが期待どおりに機能します。カスタム ユーザー モデルを適切に構成していないと思われます。

以下は私の設定ファイルです。私が間違っていることを見つけられるかどうかを確認してください。

前もって感謝します。

私の設定ファイル

 REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    ),
    'PAGINATE_BY': 10
 }

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'django.core.context_processors.static',
    'django.core.context_processors.tz',
    'django.contrib.messages.context_processors.messages',
    'django.core.context_processors.request',
    'social.apps.django_app.context_processors.backends',
)

SOCIAL_AUTH_FACEBOOK_KEY = os.environ.get('FB_APP_ID')
SOCIAL_AUTH_FACEBOOK_SECRET = os.environ.get('FB_APP_SECRET')
SOCIAL_AUTH_FACEBOOK_EXTENDED_PERMISSIONS = ['email']
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']

SOCIAL_AUTH_USER_MODEL = 'users.FLUser'

SOCIAL_AUTH_TWITTER_KEY = os.environ.get('TWITTER_APP_ID')
SOCIAL_AUTH_TWITTER_SECRET = os.environ.get('TWITTER_APP_SECRET')

AUTHENTICATION_BACKENDS = (
    'social.backends.twitter.TwitterOAuth',
    'social.backends.facebook.FacebookOAuth2',
    'social.backends.facebook.Facebook2OAuth2',
    'django.contrib.auth.backends.ModelBackend',
)

SOCIAL_AUTH_PIPELINE = (
    'social.pipeline.social_auth.social_details',
    'social.pipeline.social_auth.social_uid',
    'social.pipeline.social_auth.auth_allowed',
    'social.pipeline.social_auth.social_user',
    'social.pipeline.user.get_username',
    'social.pipeline.social_auth.associate_by_email',
    'social.pipeline.user.create_user',
    'social.pipeline.social_auth.associate_user',
    'social.pipeline.social_auth.load_extra_data',
    'social.pipeline.user.user_details'
    # 'apps.users.pipeline.user_details',
)

カスタムマネージャー

class FLUserManager(BaseUserManager):

    def _create_user(self, username, email, password,
                     is_staff, is_superuser, **extra_fields):
        """
        Creates and saves a User with the given username, email and password.
        """
        now = timezone.now()
        if not email:
            raise ValueError('The given username must be set')
        email = self.normalize_email(email)
        user = self.model(username=username, email=email,
                          is_staff=is_staff, is_active=True,
                          is_superuser=is_superuser, last_login=now,
                          date_joined=now, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, username, email=None, password=None, **extra_fields):
        return self._create_user(username, email, password, False, False,
                                 **extra_fields)

    def create_superuser(self, username, email, password, **extra_fields):
        return self._create_user(username, email, password, True, True,
                                 **extra_fields)

カスタム ユーザー モデル

class FLUser(AbstractBaseUser, PermissionsMixin):

    GENDER = (
        ('M', 'Male'),
        ('F', 'Female'),
    )
    email = models.EmailField(
        verbose_name=_('email address'),
        max_length=255,
        unique=True,
    )
    username = models.CharField(
        verbose_name=_('username'),
        max_length=30,
        unique=False,
        help_text=_('Required. 30 characters or fewer. Letters, numbers and '
                    '@/./+/-/_ characters'),
        validators=[
            validators.RegexValidator(re.compile('^[\w.@+-]+$'),
                                      _('Enter a valid username.'), 'invalid')
        ]
    )
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    birthday = models.DateTimeField(
        blank=True,
        default=None,
        null=True
    )
    gender = models.CharField(
        max_length=1,
        choices=GENDER,
        default=None,
        null=True
    )
    avatar = models.ImageField(
        upload_to='media/avatars',
        blank=True,
        default=None,
        null=True
    )
    sm_avatar = models.URLField(
        blank=True,
        default=None,
        null=True,
        verbose_name=_('Social Media Avatar')
    )
    is_active = models.BooleanField(
        _('active'),
         default=True,
        help_text=_('Designates whether this user should be treated as '
                    'active. Unselect this instead of deleting accounts.')
    )
    is_admin = models.BooleanField(default=False)

    objects = FLUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name', 'username',]

    def is_authenticated(self):
        return True

    def get_full_name(self):
        return '''{} {}'''.format(self.first_name, self.last_name)

    def get_short_name(self):
        return self.first_name

    @property
    def is_staff(self):
        return self.is_admin

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    # On Python 3: def __str__(self):
    def __unicode__(self):
        return self.email

    def email_user(self, subject, message, from_email=None):
        """
        Sends an email to this User.
        """
        send_mail(subject, message, from_email, [self.email])

    class Meta:
        ordering = ('id', 'first_name',)
        verbose_name = _('user')
        verbose_name_plural = _('users')


@receiver(post_save, sender=FLUser)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

景色

@api_view(['POST'])
@permission_classes((AllowAny,))
@strategy()
def register_by_access_token(request, backend):
   backend = request.strategy.backend
   if backend.name == 'twitter':
      token = {
          'oauth_token': request.DATA.get('access_token'),
          'oauth_token_secret': os.environ.get('TWITTER_APP_OAUTH_SECRET'),
      }
   elif backend.name == 'facebook':
      token = request.POST.get('access_token')
   else:
      raise Response('Wrong backend type', status=HTTP_400_BAD_REQUEST)

   user = backend.do_auth(
       access_token=token,
       user=request.user.is_authenticated() and request.user or None
   )
   if user and user.is_active:
      login(request, user)
      user = UserAuthSerializer(user)
      return Response(user.data, status=HTTP_200_OK)
   else:
      return Response({'detail': 'Unable to authenticate user'}, status=HTTP_400_BAD_REQUEST)
4

1 に答える 1