What I am trying to achieve is the following:
I have got a register screen in which the user enters his email and a password. When "register" ist pressed, I want the user to receive an email with a random 6-digit-code which allows him to enter this code on the next page which is the verification screen and with that verify the email.
Everything is set up, but I can only find ways via a generated verification link.
The way I would like to go is:
- User enters credentials (email, password)
- When pressed on "register" this data is saved to the database under the users collection with an ID and an email with the code is sent.
- When this is done, the code can be entered and is somehow compared to the code that is saved somewhere in the database?? Because just sending the generated code to the next screen and store it in a class variable wouldn't be the best approach of achieving this I guess.
- After success the users "verified" field is set to true in the database.
I don't really know the best way of programming this.
Please do not bother me for the naming of the routes ;) It's just like that for the moment for simplicity. Because of the same reason I only send response codes of 400 when something went wrong.
Flutter (registration screen)
child: RawMaterialButton(
onPressed: () async {
setState(() => isLoading = true);
if (email.length < 6) setState(() => isLoading = false);
else if (password.length < 6) setState(() => isLoading = false);
else {
var registerRes = await _auth.registerWithEmailAndPassword(email, password);
if (registerRes == 200) {
var code = randomNumeric(6);
var sendRes = await _auth.sendCode(email, code);
if (sendRes == 200) {
Routes.sailor.navigate(
'/confirmation',
params: {
'email': email,
'password': password,
'code': code
}
);
} else {
setState(() => isLoading = false);
}
} else {
setState(() => isLoading = false);
}
}
},
...
)
Flutter (Auth class)
import 'package:http/http.dart' as http;
import 'dart:convert';
class AuthService {
Future<String> loginWithEmailAndPassword(String email, String password) async {
Map data = {
'email': email,
'password': password
};
String body = json.encode(data);
var res = await http.post(
'http://10.0.2.2:3000/api/users/login',
headers: { 'Content-Type' : 'application/json'},
body: body
);
if (res.statusCode == 200) return res.body;
return null;
}
Future<int> registerWithEmailAndPassword(String email, String password) async {
Map data = {
'email' : email,
'password': password
};
String body = json.encode(data);
var res = await http.post(
'http://10.0.2.2:3000/api/users/register',
headers: { 'Content-Type' : 'application/json'},
body: body
);
return res.statusCode;
}
Future<int> sendCode(String email, String code) async {
Map data = {
'email' : email,
'code': code
};
String body = json.encode(data);
var res = await http.post(
'http://10.0.2.2:3000/api/users/send',
headers: { 'Content-Type' : 'application/json'},
body: body
);
return res.statusCode;
}
}
Node JS (auth.js)
const router = require('express').Router();
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const { registerValidation, loginValidation } = require('../validation');
const User = require('../models/User');
const nodemailer = require('nodemailer');
router.post('/register', async (req, res) => {
const { error } = registerValidation(req.body);
if (error) return res.sendStatus(400);
const emailExists = await User.findOne({ email : req.body.email });
if (emailExists) return res.sendStatus(400);
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(req.body.password, salt);
const user = new User({
email : req.body.email,
password : hashedPassword
});
try {
const savedUser = await user.save();
} catch(err) {
res.sendStatus(400);
}
});
router.post('/send', async (req, res) => {
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL_ADDRESS,
pass: process.env.EMAIL_PASSWORD
},
tls: {
rejectUnauthorized: false
}
});
const mailOptions = {
from: '"coderave" <ccoderave@gmail.com>',
to: req.body.email,
subject: 'Bestätigungscode',
text: req.body.code
};
transporter.sendMail(mailOptions, function (err, info) {
if (err) res.sendStatus(400);
else res.sendStatus(200);
});
});
module.exports = router;
