Implement email verification during sign-up process - django

I need to validate user's email before allowing them to proceed with account creation.
What will be the best way of doing so in Django ?
I was thinking of sending cookies with UUID which will be used during registration.
email_validation_DB:
UUID | Email | Confirmation Code | is_verified
Then, when user will click on register. UUID will be used to get the verified email address from email_validation_DB and proceed with account creation.

Instead of allowing users with only verified emails to proceed, I would suggest that you allow any user to register but activate their account only after they verify their emails.
What you can do is create a hash token and send the email with hash token and a link. When user clicks on the link, you can verify the token and activate the account. Here is a good tutorial about this - https://www.javatpoint.com/django-user-registration-with-email-confirmation
Alternatively, you can use a python package. Here is a good one - https://github.com/LeoneBacciu/django-email-verification. You can also use this package to add additional functionalities around email sending like forgot password etc.

Related

How to verify users email with token generator link for signup in django webapp

I am doing a web app in Django. I hardly tried to create a TokenGenerator for verifying the user's email to activate the user's account
coming to the problem,
how to send the verification email to the user account while
signup. while signup, users can receive a verification link email
with a token generator
the user has to input the password at the time of account signup
After verifying the email user can log in to the respective page via their mail id and password
while login it should check whether an email is present in the DB
(DB will be updated with user emails )
for the first question, Django has built-in functions and classes for sending emails, you can check them here: https://docs.djangoproject.com/en/3.2/topics/email/ and this post will help you send and email: https://dev.to/yash2115/how-to-send-e-mail-in-django-37ge, and if you want sen an email for any user's sign up you have to use signals, check it here: https://docs.djangoproject.com/en/3.2/ref/signals/
other questions are all related and they are pre-built in Django, these links will help you: https://learndjango.com/tutorials/django-login-and-logout-tutorial
https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Authentication
repositories which may help:
https://github.com/shoukreytom/pdfstack
https://github.com/shoukreytom/notes
https://github.com/shoukreytom/blog (advanced - apis)
https://github.com/mitchtabian/Food2Fork

AWS Cognito - How to determine if a user signed up with email or phone number

We have implemented the Custom Auth Triggers as described here. We have the user pool set up to let users login with either phone number or email.
The problem I am having is determining what medium (email or phonenumber) the user signed in as. I am using CognitoIdentityServiceProvider#signUp to reg / login a user.
When observing the event passed into the define / create / verify auth triggers, it seems like doesn't pass through what the username was used to initiate the authentication flow.. only the user attributes which in my case there could be both email or phone. I need to know which one it is so I know if i need to send the code through SMS or Email.
I have tried to add a custom UserAttribute with a prefix of custom: so I could do something like custom:preferredAuthMedium but that doesn't seem to populate the UserAttributes map on the user even though the docs say it should.
Is there a standard way to do this with the custom authentation flow?
This is a workaround by adding a custom attribute during passwordless login
Actually, the authenticationUser function needs to identify whether the user is adding email or phone during login
Step 1: during login process, before calling initiateAuthCommand, First set a custom attribute in Cognito user object - logged_in_by - email or phone
Step 2: once you add a key after that InitiateAuthCommand will be started and call the triggers
Step 3: When createAuthChallenge runs at the time we will have userAttributes.logged_in_by
If this attribute contains email this indicates that the user is trying to login with the email and we need to send OTP over email.
If this attribute contains a phone this indicates that the user is trying to log in with the phone and we need to send OTP over the phone number.
Different medium requires their own confirmation.
The following attributes says which medium the user signed up or verified for,
phone_number_verified is phone number.
email_verified is for email.
Hope it helps.

AWS Cognito verification email not received by user account

While creating user in userpool, user invitation messages are sent with a temporary password but email verification messages is not being sent.
I was creating a very simple setup to try out aws cognito service.
Here is what I did in AWS cognito, I created a user pool with step by step as follows:
1)What do you want to name your user pool?
-> testpool
2)How do you want to create your user pool?
-> step through settings
3)How do you want your end users to sign in?
->Email address or phone number-Allow email addresses
4)What password strength do you want to require?
->Minimum length=6
5)Do you want to allow users to sign themselves up?
->Allow users to sign themselves up
6)How quickly should user accounts created by administrators expire if not used?
->Days to expire-7
7)Do you want to enable Multi-Factor Authentication (MFA)?
->off
8)Do you want to require verification of emails or phone numbers?
->Email
9)You must provide a role to allow Amazon Cognito to send SMS messages
->testpool-SMS-Role
10)Do you want to customize your email verification messages?
->Verification type-link
->Email subject = Your verification link
->Email message = Please click the link below to verify your email address. {##Verify Email##}
11)Do you want to customize your user invitation messages?
->SMS message = Your username is {username} and temporary password is ->{####}.
->Email subject = Your temporary password
->Email message = Your username is {username} and temporary password is {####}.
12)Do you want to customize your email address?
->no
13)Do you want to add tags for this user pool?
->no
14)Do you want to remember your user's devices?
->no
15)Which app clients will have access to this user pool?
->none(will simulate from create user option in genral setting-user and group)
16)Do you want to customize workflows with triggers?
->no
17)Review page - this page shows summary of whatever I selected
Create pool
Now after pool creation went ot genral setting-user and group and clicked create user
A Create user pop-up shows:
Username (Required): myEmailAddress
Send an invitation to this new user?: check
Temporary password: left blank
Phone Number: empty(not required)
Mark phone number as verified? unCheck
Email: myEmailAddress
Mark email as verified? unCheck
Click on Create User
A mail is received into my account form no-reply#verificationemail.com via amazonses.com,with subject: Your temporary password with message as: Your username is somemailid#gmail.com and temporary password is agsjyk.
This is okay.
But I didnot receive any verification mail link before previous mail.
Not sure if you're missing this particular setup....Domain name is require for link verification.
Under "Tab integration" then "Domain name"
A mail is received into my account form no-reply#verificationemail.com via
amazonses.com,
with subject: Your temporary password
with message as: Your username is somemailid#gmail.com and temporary password is > agsjyk.
Looking at this it seems you are creating the user via the Cognito API by the AdminCreateUser method, and that's why you are receiving a temporary password.
The confirmation email you are expecting will only be sent if the user registers itself, so you should use the SignUp method.
verification mail link is for when users sign themselves up, they will receive a link to ask them to verify the email address instead of a code. In your case, you are send a temporary password to the user, so the link wont show up.
You need to add a domain in this section of the Incognito Service:
Also, if you are not getting the email, click on the user, and check their email, it could be wrong.
If anyone else is facing this issue, it appears that you cannot send verification emails if you use SAML or a federated identity provider. Cognito sets the cognito user to EXTERNAL_PROVIDER and no Cognito API calls allow sending a verifcation code or link. The cognito user is automatically created on initial sign-in. I have my user pool set to validate email address but it is always set to false.
The only way that I know to confirm the user via SSO is to use an external verification process outside of cognito.
With Cognito, if you have added both email and phone number then you should allow both as verification methods(In the SignUp experience Tab) as below:
Otherwise the email verification link or code is not sent

How to design email and username login

I have two question about usernames and emails
1. I judge username is a Email if '#' in username, and auth it follow:
email_user = User.objects.get(email__iexact=username)
authenticate(username=email_user.username)
Is that a good way that you recommended? or you may have a better advice?
I know a AbstractBaseUser can do it, but I think use User is more reasonable.
2. Should I store the user's email within the User.email field?
Imagine if I sign up a new user with:
username: '123'
email: '456#google.com'
and when I signup success, then I find that my email is wrong,
and now another user that email is '456#google.com' can't signup again.
I just want to a email is verified that can associate with the user.
what's your advice?
If you want to use email as your unique sign in key, it would save you a lot of trouble in future development of your website if you make a custom User model using AbstractBaseUser. If you want i can post a sample working code
In reference to your second question - You can use Cryptographic signing in Django (https://docs.djangoproject.com/ja/1.9/topics/signing/) to produce a key. Further send this key as a link (eg www.example.com/verify/:some_crypto_key:) and send it as a link to user's email address. This key will contain user id and time stamp. If you receive a request on that link, it means that email is legit. You may find a package that does a similar task maybe.
EDIT:
Implementation (short way) - As the user signups on your website, Immediately ask him/her to verify account using the link you have sent to the given email. If you do not receive a response from that email within a given time (say 20 mins), delete that user entry. This means that you can not let the user access your website until he/she verifies the account.
Flaw - Consider a situation where the user has submitted a wrong email. It is obvious that the user will never be able to verify it but for those 20 mins if co-incidentally the actual user with that same email tries to signup on your website, he won't be able to access. This is very unlikely. Also this user will receive an email from your website saying that user has signed-up on a website (so here you can provide another link, 'if this was not you, please click here' kind of thing)
Unless you have a burning desire to write your own custom user model, which will let you replace the username field with the email, I would recommend using something like Django AllAuth. It includes email verification (as outlined in your question), and can be set to use email as username fairly easily. It's a well established library with lots of support, and will be more immediately usable than rolling your own.
(That said - rolling your own is an illuminating experience, and RA123's point is the answer you should accept if you're going down that road.)

how to get a users #facebook.com email?

I am trying to find out if a user has an #facebook.com email for messaging but can not see where to request that I do request perms for their regular email and can get that, but can't see where to get their #facebook.com email. It's not included in https://graph.facebook.com/me/ and since there's no guarantee that they have set one up I can't assume that it's based on their username
If a user has a facebook.com email address it will be their {username}#facebook.com. However, just because a user has a username setup, doesn't mean there's a corresponding email for it. I've had a username since Facebook landrushed them, and just the other day I setup an email for it. There's no way to tell if they've set it up. Your best bet is to ask the user for an email address that your app can use.
Just go to your privacy settings and from there act as you are editing you email address then there is a Facebook email button setup there.