Cheesecake Labs Builds SMS User Verification With Python and Django

December 19, 2016
Written by

This post is part of Twilio’s archive and may contain outdated information. We’re always building something new, so be sure to check out our latest posts for the most up-to-date insights.

cheesecakelabs

Cheesecake Labs, a development shop, built their SMS user verification app in less than a day using Python and Django. Here’s how it works from the user’s end.

1. The user enters his/her phone number in the app

2. The app pings the server, and the user quickly receives an SMS with a confirmation 6-digit pin-code.

3. As soon as the user types the correct pin in the app, the phone number is validated.

This was iOS developer, Marcelo Salloum‘s first Twilio hack. Marcello wanted to create a verification feature that didn’t require the users to create a log-in and password. Instead, he used the username everyone has in their pocket at all times — your phone number.

Here’s the code he used to build the feature, which Marcello based off of these docs.

Cheesecake Lab’s SMS Verification Solution — Built With Python + Django

When a new user signs up, a http request is triggered through @receiver(user_signed_up), then the SMSVerification model creates a pin code for that user and sends it to the user’s phone.

class SMSVerification(TimestampedModel):
    user = models.ForeignKey(User)
    verified = models.BooleanField(default=False)
    pin = RandomPinField(length=6)
    sent = models.BooleanField(default=False)
    phone = PhoneNumberField(null=False, blank=False)

    def send_confirmation(self):

        logger.debug('Sending PIN %s to phone %s' % (self.pin, self.phone))

        if phonenumbers.is_valid_number(self.phone):
            if all([settings.TWILIO_ACCOUNT_SID, settings.TWILIO_AUTH_TOKEN, settings.TWILIO_FROM_NUMBER]):
                try:
                    twilio_client = TwilioRestClient(settings.TWILIO_ACCOUNT_SID, settings.TWILIO_AUTH_TOKEN)
                    twilio_client.messages.create(
                        body="Your forgeter activation code is %s" % self.pin,
                        to=str(self.user.userprofile.phone),
                        from_=settings.TWILIO_FROM_NUMBER
                    )
                    self.sent = True
                    self.save()
                    return True
                except TwilioException, e:
                    logger.error(e)
            else:
                logger.warning('Twilio credentials are not set')
        return False

    def confirm(self, pin):
        if self.pin == pin:
            self.user.auth_token.delete()
            self.user.auth_token = TokenModel.objects.create(user=self.user)
            self.verified = True
            self.save()

        return self.verified


@receiver(user_signed_up)
def send_sms_verification(request, user, **kwargs):
    verification = SMSVerification.objects.create(user=user, phone=user.userprofile.phone)
    verification.send_confirmation()

In the case where the user asks for another SMS, Cheesecake Labs sends ReSend logic:

class ResendView(GenericAPIView):
    permission_classes = (AllowAny,)
    allowed_methods = ('POST',)

    def resend_or_create(self):
        phone = self.request.data.get('phone')
        send_new = self.request.data.get('new')
        sms_verification = None

        user = User.objects.filter(userprofile__phone=phone).first()

        if not send_new:
            sms_verification = SMSVerification.objects.filter(user=user, verified=False) \
                .order_by('-created_at').first()

        if sms_verification is None:
            sms_verification = SMSVerification.objects.create(user=user, phone=phone)

        return sms_verification.send_confirmation()

    def post(self, request, *args, **kwargs):
        success = self.resend_or_create()

        return Response(dict(success=success), status=status.HTTP_200_OK)

That’s all the code it takes to build User Verification. Check out a tutorial on how to build it here.