├── Procfile
├── .gitignore
├── templates
├── sms
│ ├── phone_2FA.js
│ ├── phone_forget.js
│ └── phone_verification.js
└── email
│ ├── email_2FA.js
│ ├── email_forget.js
│ └── email_verification.js
├── sequelize.js
├── package.json
├── middlewares
└── crypt.js
├── redoc.html
├── models
└── OTP.js
├── app.js
├── README.md
└── routes
├── sendOTP_to_email.js
├── sendOTP_to_phone.js
└── verifyOTP.js
/Procfile:
--------------------------------------------------------------------------------
1 | web:node app.js
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | /node_modules
--------------------------------------------------------------------------------
/templates/sms/phone_2FA.js:
--------------------------------------------------------------------------------
1 | const message = (otp) =>{
2 | return `Dear User,\n`
3 | + `${otp} is your otp for Login.Please Enter the OTP to proceed.\n`
4 | + `Regards\n`
5 | + `Divyansh Agarwal`
6 | }
7 |
8 | module.exports= message;
--------------------------------------------------------------------------------
/templates/sms/phone_forget.js:
--------------------------------------------------------------------------------
1 | const message = (otp) =>{
2 | return `Dear User,\n`
3 | + `${otp} is your otp for Reset Password.Please Enter the OTP to proceed.\n`
4 | + `Regards\n`
5 | + `Divyansh Agarwal`
6 | }
7 |
8 | module.exports= message;
--------------------------------------------------------------------------------
/templates/sms/phone_verification.js:
--------------------------------------------------------------------------------
1 | const message = (otp) =>{
2 | return `Dear User,\n`
3 | + `${otp} is your otp for Incampus. Please enter the OTP to verify your phone number.\n`
4 | + `Regards\n`
5 | + `Divyansh Agarwal`
6 | }
7 |
8 | module.exports= message;
--------------------------------------------------------------------------------
/templates/email/email_2FA.js:
--------------------------------------------------------------------------------
1 | const subject_mail = "OTP: For Login"
2 |
3 |
4 |
5 | const message = (otp) =>{
6 | return `Dear User, \n\n`
7 | + 'OTP for Login is : \n\n'
8 | + `${otp}\n\n`
9 | + 'This is a auto-generated email. Please do not reply to this email.\n\n'
10 | + 'Regards\n'
11 | + 'Divyansh Agarwal\n\n'
12 | }
13 |
14 | module.exports = {subject_mail, message};
--------------------------------------------------------------------------------
/templates/email/email_forget.js:
--------------------------------------------------------------------------------
1 | const subject_mail = "OTP: For Reset Password"
2 |
3 |
4 |
5 | const message = (otp) =>{
6 | return `Dear User, \n\n`
7 | + 'OTP for Reset Password is : \n\n'
8 | + `${otp}\n\n`
9 | + 'This is a auto-generated email. Please do not reply to this email.\n\n'
10 | + 'Regards\n'
11 | + 'Divyansh Agarwals\n\n'
12 | }
13 |
14 | module.exports = {subject_mail, message};
--------------------------------------------------------------------------------
/templates/email/email_verification.js:
--------------------------------------------------------------------------------
1 | const subject_mail = "OTP: For Email Verification"
2 |
3 |
4 |
5 | const message = (otp) =>{
6 | return `Dear User, \n\n`
7 | + 'OTP for your email verification is : \n\n'
8 | + `${otp}\n\n`
9 | + 'This is a auto-generated email. Please do not reply to this email.\n\n'
10 | + 'Regards\n'
11 | + 'Divyansh Agarwal\n\n'
12 | }
13 |
14 | module.exports={subject_mail, message};
--------------------------------------------------------------------------------
/sequelize.js:
--------------------------------------------------------------------------------
1 | const Sequelize = require('sequelize');
2 | const OTP_Model = require('./models/OTP');
3 |
4 | const sequelize = new Sequelize(process.env['DB_NAME'], process.env['DB_USER'], process.env['DB_PASSWORD'], {
5 | host: process.env['DB_HOST'],
6 | dialect: 'postgres',
7 | protocol: 'postgres',
8 | port: process.env['DB_PORT'],
9 | dialectOptions: {
10 | "ssl": {
11 | "require":true,
12 | "rejectUnauthorized": false
13 | }
14 | },
15 | define: {
16 | timestamps: false
17 | },
18 |
19 | pool: {
20 | max: 20,
21 | min: 0,
22 | idle: 5000
23 | },
24 | logging:false
25 | });
26 |
27 | const OTP = OTP_Model(sequelize, Sequelize);
28 |
29 | sequelize.sync().then(() => {
30 | console.log('db and tables have been created');
31 | });
32 |
33 | module.exports = {OTP};
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-js-otp",
3 | "version": "1.0.0",
4 | "description": "Basic OTP service in NodeJs using express",
5 | "main": "app.js",
6 | "scripts": {
7 | "start": "nodemon app.js",
8 | "server": "nodemon app.js",
9 | "dev": "npm run server"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "aws-sdk": "^2.709.0",
15 | "cors": "^2.8.5",
16 | "crypto": "^1.0.1",
17 | "custom-id": "^1.2.0",
18 | "dotenv": "^8.2.0",
19 | "express": "^4.17.1",
20 | "fs": "0.0.1-security",
21 | "helmet": "^3.23.0",
22 | "jsonwebtoken": "^8.5.1",
23 | "morgan": "^1.10.0",
24 | "nodemailer": "^6.4.8",
25 | "nodemon": "^2.0.4",
26 | "otp-generator": "^3.0.0",
27 | "pg": "^8.2.1",
28 | "sequelize": "^5.21.12",
29 | "sequelize-cli": "^5.5.1",
30 | "swagger-jsdoc": "^4.0.0",
31 | "swagger-ui-express": "^4.1.4",
32 | "tls": "0.0.1"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/middlewares/crypt.js:
--------------------------------------------------------------------------------
1 | const crypto = require('crypto');
2 | var password = process.env['CRYPT_PASSWORD'];
3 | // var iv = 'kiamdksndn';
4 | var iv = Buffer.from(process.env['IV']);
5 | var ivstring = iv.toString('hex');
6 |
7 | function sha1(input) {
8 | return crypto.createHash('sha1').update(input).digest();
9 | }
10 |
11 | function password_derive_bytes(password, salt, iterations, len) {
12 | var key = Buffer.from(password + salt);
13 | for (var i = 0; i < iterations; i++) {
14 | key = sha1(key);
15 | }
16 | if (key.length < len) {
17 | var hx = password_derive_bytes(password, salt, iterations - 1, 20);
18 | for (var counter = 1; key.length < len; ++counter) {
19 | key = Buffer.concat([key, sha1(Buffer.concat([Buffer.from(counter.toString()), hx]))]);
20 | }
21 | }
22 | return Buffer.alloc(len, key);
23 | }
24 |
25 |
26 | async function encode(string) {
27 | var key = password_derive_bytes(password, '', 100, 32);
28 | var cipher = crypto.createCipheriv('aes-256-cbc', key, ivstring);
29 | var part1 = cipher.update(string, 'utf8');
30 | var part2 = cipher.final();
31 | const encrypted = Buffer.concat([part1, part2]).toString('base64');
32 | return encrypted;
33 | }
34 |
35 | async function decode(string) {
36 | var key = password_derive_bytes(password, '', 100, 32);
37 | var decipher = crypto.createDecipheriv('aes-256-cbc', key, ivstring);
38 | var decrypted = decipher.update(string, 'base64', 'utf8');
39 | decrypted += decipher.final();
40 | return decrypted;
41 | }
42 |
43 |
44 | module.exports={encode, decode};
--------------------------------------------------------------------------------
/redoc.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Node-OTP-Service | Documentation
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/models/OTP.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable indent */
2 |
3 | /**
4 | * @swagger
5 | * definitions:
6 | * Details:
7 | * type: object
8 | * properties:
9 | * Status:
10 | * type: string
11 | * Details:
12 | * type: string
13 | */
14 |
15 | /**
16 | * @swagger
17 | * definitions:
18 | * VerificationDetails:
19 | * type: object
20 | * properties:
21 | * Status:
22 | * type: string
23 | * Details:
24 | * type: string
25 | * Check:
26 | * type: string
27 | */
28 |
29 | /**
30 | * @swagger
31 | * definitions:
32 | * OTP:
33 | * type: object
34 | * properties:
35 | * id:
36 | * type: uuid
37 | * first_name:
38 | * type: string
39 | * last_name:
40 | * type: string
41 | * email:
42 | * type: string
43 | * username:
44 | * type: string
45 | * password:
46 | * type: string
47 | * format: password
48 | * resetPasswordToken:
49 | * type: string
50 | * resetPasswordExpires:
51 | * type: string
52 | * format: date-time
53 | * required:
54 | * - email
55 | * - username
56 | * - password
57 | */
58 |
59 | module.exports = function(sequelize, DataTypes) {
60 | // return queryInterface.sequelize.query('CREATE EXTENSION IF NOT EXISTS "uuid-ossp";').then(()=>{
61 | return sequelize.define('OTP', {
62 | id: {
63 | type: DataTypes.UUID,
64 | primaryKey: true,
65 | defaultValue: DataTypes.UUIDV4,
66 | },
67 | otp: DataTypes.STRING,
68 | expiration_time: DataTypes.DATE,
69 | verified: {
70 | type: DataTypes.BOOLEAN,
71 | defaultValue: false,
72 | allowNull: true
73 | },
74 | created_at: {
75 | type: DataTypes.DATE,
76 | allowNull: false,
77 | defaultValue: sequelize.fn('now')
78 | },
79 | updated_at: {
80 | type: DataTypes.DATE,
81 | allowNull: false,
82 | defaultValue: sequelize.fn('now')
83 | }
84 | }, {
85 | tableName: 'OTP'
86 | });
87 | // });
88 | };
89 |
90 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 |
2 | // DB_PORT=
3 | // DB_NAME=
4 | // DB_HOST=
5 | // DB_USER=
6 | // DB_PASSWORD=
7 | // EMAIL_ADDRESS=
8 | // EMAIL_PASSWORD=
9 | // AWS_ACCESS_KEY_ID=
10 | // AWS_SECRET_ACCESS_KEY=
11 | // AWS_REGION=
12 | // IV=
13 | // CRYPT_PASSWORD=
14 |
15 | require('dotenv').config();
16 | const express = require('express');
17 | const path = require('path');
18 | const helmet = require('helmet');
19 | const logger = require('morgan');
20 | var os = require("os");
21 | var hostname = os.hostname();
22 | const app = express();
23 |
24 | const port = process.env.PORT || 4500
25 |
26 |
27 | // Getting data in json format
28 |
29 | app.use(express.urlencoded({ extended: true }));
30 | app.use(express.json());
31 |
32 | //Setting up cors
33 |
34 | var cors = require('cors');
35 | var corsOption = {
36 | origin: "*",
37 | methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
38 | credentials: true,
39 | exposedHeaders: ['x-auth-token']
40 | };
41 | app.use(cors(corsOption));
42 |
43 | // Using Helmet
44 |
45 | app.use(helmet())
46 |
47 | // Logger
48 |
49 | app.use(logger('common'))
50 |
51 | //Setting swagger Documentation
52 |
53 | const swaggerJSDoc = require('swagger-jsdoc');
54 | const swaggerDefinition = {
55 | info: {
56 | title: 'Node-OTP-Service API',
57 | version: '1.0.0',
58 | description: 'Documentation for Node-Js OTP service API',
59 | },
60 | host: 'node-otp-service.herokuapp.com',
61 | basePath: '/api/v1/',
62 | };
63 | const options = {
64 | swaggerDefinition,
65 | apis: ['./routes/*.js','./models/OTP.js'],
66 |
67 | };
68 | const swaggerSpec = swaggerJSDoc(options);
69 | app.get('/swagger.json', (req, res) => {
70 | res.setHeader('Content-Type', 'application/json');
71 | res.send(swaggerSpec);
72 | });
73 |
74 | app.get('/docs', (req, res) => {
75 | res.sendFile(path.join(__dirname, 'redoc.html'));
76 | });
77 |
78 |
79 | //Importing Routes
80 | const sendOTP_to_phone = require('./routes/sendOTP_to_phone');
81 | const verify_otp = require('./routes/verifyOTP')
82 | const sendOTP_to_email = require('./routes/sendOTP_to_email')
83 |
84 |
85 | //Using imported Routes
86 | app.use('/api/v1', sendOTP_to_phone);
87 | app.use('/api/v1', verify_otp);
88 | app.use('/api/v1/', sendOTP_to_email);
89 |
90 |
91 |
92 |
93 | //==================================================================================================================================
94 |
95 | app.get('/', function (req, res) {
96 | console.log('route / is accessed.');
97 | res.send('Hi');
98 | });
99 |
100 | app.listen(port, function () {
101 | console.log(`Server is running on port ${port}`);
102 | });
103 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Node-js-OTP Service
2 |
3 | ### About
4 |
5 | It is an API that implements a OTP service in a scalable manner. In this, we do not need to store OTP with email or phone numbers rather a encrypted object is sent in response when OTP is requested which is decrypted and verified at the time of verification.
6 |
7 | ### Setup
8 |
9 | - Download postgreSQL from https://www.postgresql.org/download/ .
10 | - Setup postgres Database by using psql command line.
11 | - Get the Database Credentials.
12 | - Create a ```.env``` file in the project folder.
13 |
14 | ```
15 | PORT=
16 | DB_PORT=
17 | DB_NAME=
18 | DB_HOST=
19 | DB_USER=
20 | DB_PASSWORD=
21 | EMAIL_ADDRESS=
22 | EMAIL_PASSWORD=
23 | AWS_ACCESS_KEY_ID=
24 | AWS_SECRET_ACCESS_KEY=
25 | AWS_REGION=
26 | IV=
27 | CRYPT_PASSWORD=
28 | ```
29 | > Note : You have set a valid value for IV. Like:
30 | ```
31 | IV=28408e46
32 | ```
33 | - Use ` npm install` to install all the dependency for the project.
34 | - Database will be automatically migrated when the application starts.
35 | - Use ` npm start` to start the application.
36 |
37 | ## Usage
38 |
39 | #### To Send OTP to Emails
40 |
41 | - `/api/v1/email/otp`
42 | - _Allowed Methods_ : `POST`
43 | - `Description`: In this endpoint, we will take the email and type of the service request from any service using this OTP service and send the status and encrypted details in the response.
44 | - Request Object :
45 | ```json
46 | {
47 | "email":"",
48 | "type":""
49 | }
50 | ```
51 | > Note: Type can have 3 values that are : VERIFICATION, FORGET, 2FA. This is used to choose message template for email.
52 |
53 | - Response :
54 | - Status Code:
55 | - 200:
56 | ```json
57 | {
58 | "Status": "Success",
59 | "Details": "",
79 | "type":""
80 | }
81 | ```
82 | > Note: Type can have 3 values that are : VERIFICATION, FORGET, 2FA. This is used to choose message template for email.
83 |
84 | - Response :
85 | - Status Code:
86 | - 200:
87 | ```json
88 | {
89 | "Status": "Success",
90 | "Details": "",
110 | "verification_key": "",
111 | "check": ""
112 | }
113 | ```
114 | > Note: Type can have 3 values that are : VERIFICATION, FORGET, 2FA. This is used to choose message template for email.
115 |
116 | - Response :
117 | - Status Code:
118 | - 200:
119 | ```json
120 | {
121 | "Status": "Success",
122 | "Details": "OTP Matched",
123 | "Check": ""
124 | }
125 | ```
126 | - 400:
127 | ```json
128 | {
129 | "Status": "Failure",
130 | "Details": " {
69 | try{
70 | const {email,type} = req.body;
71 | let email_subject, email_message
72 | if(!email){
73 | const response={"Status":"Failure","Details":"Email not provided"}
74 | return res.status(400).send(response)
75 | }
76 | if(!type){
77 | const response={"Status":"Failure","Details":"Type not provided"}
78 | return res.status(400).send(response)
79 | }
80 |
81 | //Generate OTP
82 | const otp = otpGenerator.generate(6, { alphabets: false, upperCase: false, specialChars: false });
83 | const now = new Date();
84 | const expiration_time = AddMinutesToDate(now,10);
85 |
86 |
87 | //Create OTP instance in DB
88 | const otp_instance = await OTP.create({
89 | otp: otp,
90 | expiration_time: expiration_time
91 | });
92 |
93 | // Create details object containing the email and otp id
94 | var details={
95 | "timestamp": now,
96 | "check": email,
97 | "success": true,
98 | "message":"OTP sent to user",
99 | "otp_id": otp_instance.id
100 | }
101 |
102 | // Encrypt the details object
103 | const encoded= await encode(JSON.stringify(details))
104 |
105 | //Choose message template according type requestedconst encoded= await encode(JSON.stringify(details))
106 | if(type){
107 | if(type=="VERIFICATION"){
108 | const {message, subject_mail} = require('../templates/email/email_verification');
109 | email_message=message(otp)
110 | email_subject=subject_mail
111 | }
112 | else if(type=="FORGET"){
113 | const {message, subject_mail} = require('../templates/email/email_forget');
114 | email_message=message(otp)
115 | email_subject=subject_mail
116 | }
117 | else if(type=="2FA"){
118 | const {message, subject_mail} = require('../templates/email/email_2FA');
119 | email_message=message(otp)
120 | email_subject=subject_mail
121 | }
122 | else{
123 | const response={"Status":"Failure","Details":"Incorrect Type Provided"}
124 | return res.status(400).send(response)
125 | }
126 | }
127 |
128 | // Create nodemailer transporter
129 | const transporter = nodemailer.createTransport({
130 | host: 'smtp.zoho.in',
131 | port: 465,
132 | secure: true,
133 | auth: {
134 | user: `${process.env.EMAIL_ADDRESS}`,
135 | pass: `${process.env.EMAIL_PASSWORD}`
136 | },
137 | });
138 |
139 |
140 | const mailOptions = {
141 | from: `"Divyansh Agarwal"<${process.env.EMAIL_ADDRESS}>`,
142 | to: `${email}`,
143 | subject: email_subject,
144 | text: email_message ,
145 | };
146 |
147 | await transporter.verify();
148 |
149 | //Send Email
150 | await transporter.sendMail(mailOptions, (err, response) => {
151 | if (err) {
152 | return res.status(400).send({"Status":"Failure","Details": err });
153 | } else {
154 | // console.log('here is the res: ', response);
155 | return res.send({"Status":"Success","Details":encoded});
156 | }
157 | });
158 | }
159 | catch(err){
160 | const response={"Status":"Failure","Details": err.message}
161 | return res.status(400).send(response)
162 | }
163 | });
164 |
165 |
166 | module.exports = router;
167 |
--------------------------------------------------------------------------------
/routes/sendOTP_to_phone.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | const {OTP} = require('../sequelize');
3 | const router = require("express").Router();
4 | const {encode} = require("../middlewares/crypt")
5 | var otpGenerator = require('otp-generator');
6 | var AWS = require('aws-sdk');
7 | const crypto = require('crypto');
8 |
9 |
10 | /**
11 | * @swagger
12 | * /phone/otp:
13 | * post:
14 | * tags:
15 | * - OTP
16 | * name: Send OTP to Phone
17 | * summary: Send OTP to Phone
18 | * produces:
19 | * - application/json
20 | * consumes:
21 | * - application/json
22 | * parameters:
23 | * - name: body
24 | * in: body
25 | * schema:
26 | * type: object
27 | * properties:
28 | * phone_number:
29 | * type: string
30 | * type:
31 | * type: string
32 | * required:
33 | * - phone_number
34 | * - type
35 | * responses:
36 | * '200':
37 | * description: OTP sent successfully
38 | * content:
39 | * application/json:
40 | * schema:
41 | * $ref: '#/definitions/Details'
42 | * type: object
43 | * properties:
44 | * Status:
45 | * type: string
46 | * Details:
47 | * type: string
48 | * '400':
49 | * description: Number is not provided or Type is not provided
50 | * content:
51 | * application/json:
52 | * schema:
53 | * $ref: '#/definitions/Details'
54 | * type: object
55 | * properties:
56 | * Status:
57 | * type: string
58 | * Details:
59 | * type: string
60 | * '503':
61 | * description: OTP service not available for phone number as credentials are not set
62 | * content:
63 | * application/json:
64 | * schema:
65 | * $ref: '#/definitions/Details'
66 | * type: object
67 | * properties:
68 | * Status:
69 | * type: string
70 | * Details:
71 | * type: string
72 | */
73 |
74 | // To add minutes to the current time
75 | function AddMinutesToDate(date, minutes) {
76 | return new Date(date.getTime() + minutes*60000);
77 | }
78 |
79 |
80 | router.post('/phone/otp', async (req, res, next) => {
81 |
82 | try{
83 |
84 | if(!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY){
85 | const response={"Status":"Failure","Details":"OTP for phone is not available right now"}
86 | return res.status(503).send(response)
87 | }
88 |
89 | const {phone_number,type} = req.body;
90 |
91 | let phone_message
92 |
93 | if(!phone_number){
94 | const response={"Status":"Failure","Details":"Phone Number not provided"}
95 | return res.status(400).send(response)
96 | }
97 | if(!type){
98 | const response={"Status":"Failure","Details":"Type not provided"}
99 | return res.status(400).send(response)
100 | }
101 |
102 | //Generate OTP
103 | const otp = otpGenerator.generate(6, { alphabets: false, upperCase: false, specialChars: false });
104 | const now = new Date();
105 | const expiration_time = AddMinutesToDate(now,10);
106 |
107 |
108 | //Create OTP instance in DB
109 | const otp_instance = await OTP.create({
110 | otp: otp,
111 | expiration_time: expiration_time
112 | });
113 |
114 | // Create details object containing the phone number and otp id
115 | var details={
116 | "timestamp": now,
117 | "check": phone_number,
118 | "success": true,
119 | "message":"OTP sent to user",
120 | "otp_id": otp_instance.id
121 | }
122 |
123 | // Encrypt the details object
124 | const encoded= await encode(JSON.stringify(details))
125 |
126 | //Choose message template according type requested
127 | if(type){
128 | if(type=="VERIFICATION"){
129 | const message = require('../templates/sms/phone_verification');
130 | phone_message=message(otp)
131 | }
132 | else if(type=="FORGET"){
133 | const message = require('../templates/sms/phone_forget');
134 | phone_message=message(otp)
135 | }
136 | else if(type=="2FA"){
137 | const message = require('../templates/sms/phone_2FA');
138 | phone_message=message(otp)
139 | }
140 | else{
141 | const response={"Status":"Failure","Details":"Incorrect Type Provided"}
142 | return res.status(400).send(response)
143 | }
144 | }
145 |
146 | // Settings Params for SMS
147 | var params = {
148 | Message: phone_message,
149 | PhoneNumber: phone_number
150 | };
151 |
152 | //Send the params to AWS SNS using aws-sdk
153 | var publishTextPromise = new AWS.SNS({ apiVersion: '2010-03-31' }).publish(params).promise();
154 |
155 | //Send response back to the client if the message is sent
156 | publishTextPromise.then(
157 | function (data) {
158 | return res.send({"Status":"Success","Details":encoded});
159 | }).catch(
160 | function (err) {
161 | return res.status(400).send({"Status":"Failure","Details": err });
162 | });
163 | }
164 | catch(err){
165 | const response={"Status":"Failure","Details": err.message}
166 | return res.status(400).send(response)
167 | }
168 | });
169 |
170 |
171 | module.exports = router;
172 |
--------------------------------------------------------------------------------
/routes/verifyOTP.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | const {OTP} = require('../sequelize');
3 | const router = require("express").Router();
4 | const {decode} = require("../middlewares/crypt")
5 |
6 |
7 |
8 | /**
9 | * @swagger
10 | * /verify/otp:
11 | * post:
12 | * tags:
13 | * - OTP
14 | * name: Verify OTP
15 | * summary: Verify OTP
16 | * produces:
17 | * - application/json
18 | * consumes:
19 | * - application/json
20 | * parameters:
21 | * - name: body
22 | * in: body
23 | * schema:
24 | * type: object
25 | * properties:
26 | * otp:
27 | * type: string
28 | * verification_key:
29 | * type: string
30 | * check:
31 | * type: string
32 | * required:
33 | * - otp
34 | * - verification_key
35 | * - check
36 | * responses:
37 | * '200':
38 | * description: OTP Matched
39 | * content:
40 | * application/json:
41 | * schema:
42 | * $ref: '#/definitions/VerificationDetails'
43 | * type: object
44 | * properties:
45 | * Status:
46 | * type: string
47 | * Details:
48 | * type: string
49 | * Check:
50 | * type: string
51 | * '400':
52 | * description: OTP cannot be verified
53 | * content:
54 | * application/json:
55 | * schema:
56 | * $ref: '#/definitions/Details'
57 | * type: object
58 | * properties:
59 | * Status:
60 | * type: string
61 | * Details:
62 | * type: string
63 | */
64 |
65 | // Function to Compares dates (expiration time and current time in our case)
66 | var dates = {
67 | convert:function(d) {
68 | // Converts the date in d to a date-object. The input can be:
69 | // a date object: returned without modification
70 | // an array : Interpreted as [year,month,day]. NOTE: month is 0-11.
71 | // a number : Interpreted as number of milliseconds
72 | // since 1 Jan 1970 (a timestamp)
73 | // a string : Any format supported by the javascript engine, like
74 | // "YYYY/MM/DD", "MM/DD/YYYY", "Jan 31 2009" etc.
75 | // an object : Interpreted as an object with year, month and date
76 | // attributes. **NOTE** month is 0-11.
77 | return (
78 | d.constructor === Date ? d :
79 | d.constructor === Array ? new Date(d[0],d[1],d[2]) :
80 | d.constructor === Number ? new Date(d) :
81 | d.constructor === String ? new Date(d) :
82 | typeof d === "object" ? new Date(d.year,d.month,d.date) :
83 | NaN
84 | );
85 | },
86 | compare:function(a,b) {
87 | // Compare two dates (could be of any type supported by the convert
88 | // function above) and returns:
89 | // -1 : if a < b
90 | // 0 : if a = b
91 | // 1 : if a > b
92 | // NaN : if a or b is an illegal date
93 | // NOTE: The code inside isFinite does an assignment (=).
94 | return (
95 | isFinite(a=this.convert(a).valueOf()) &&
96 | isFinite(b=this.convert(b).valueOf()) ?
97 | (a>b)-(a {
119 | try{
120 | var currentdate = new Date();
121 | const {verification_key, otp, check} = req.body;
122 |
123 | if(!verification_key){
124 | const response={"Status":"Failure","Details":"Verification Key not provided"}
125 | return res.status(400).send(response)
126 | }
127 | if(!otp){
128 | const response={"Status":"Failure","Details":"OTP not Provided"}
129 | return res.status(400).send(response)
130 | }
131 | if(!check){
132 | const response={"Status":"Failure","Details":"Check not Provided"}
133 | return res.status(400).send(response)
134 | }
135 |
136 | let decoded;
137 |
138 | //Check if verification key is altered or not and store it in variable decoded after decryption
139 | try{
140 | decoded = await decode(verification_key)
141 | }
142 | catch(err) {
143 | const response={"Status":"Failure", "Details":"Bad Request"}
144 | return res.status(400).send(response)
145 | }
146 |
147 | var obj= JSON.parse(decoded)
148 | const check_obj = obj.check
149 |
150 | // Check if the OTP was meant for the same email or phone number for which it is being verified
151 | if(check_obj!=check){
152 | const response={"Status":"Failure", "Details": "OTP was not sent to this particular email or phone number"}
153 | return res.status(400).send(response)
154 | }
155 |
156 | const otp_instance= await OTP.findOne({where:{id: obj.otp_id}})
157 |
158 | //Check if OTP is available in the DB
159 | if(otp_instance!=null){
160 |
161 | //Check if OTP is already used or not
162 | if(otp_instance.verified!=true){
163 |
164 | //Check if OTP is expired or not
165 | if (dates.compare(otp_instance.expiration_time, currentdate)==1){
166 |
167 | //Check if OTP is equal to the OTP in the DB
168 | if(otp===otp_instance.otp){
169 | otp_instance.verified=true
170 | otp_instance.save()
171 | const response={"Status":"Success", "Details":"OTP Matched", "Check": check}
172 | return res.status(200).send(response)
173 | }
174 | else{
175 | const response={"Status":"Failure","Details":"OTP NOT Matched"}
176 | return res.status(400).send(response)
177 | }
178 |
179 | }
180 | else{
181 | const response={"Status":"Failure","Details":"OTP Expired"}
182 | return res.status(400).send(response)
183 | }
184 | }
185 | else{
186 | const response={"Status":"Failure","Details":"OTP Already Used"}
187 | return res.status(400).send(response)
188 | }
189 | }
190 | else{
191 | const response={"Status":"Failure","Details":"Bad Request"}
192 | return res.status(400).send(response)
193 | }
194 | }
195 | catch(err){
196 | const response={"Status":"Failure","Details": err.message}
197 | return res.status(400).send(response)
198 | }
199 | });
200 |
201 |
202 | module.exports = router;
203 |
--------------------------------------------------------------------------------