I'm using Infobip free trial account and trying to implement the two-factor authentication SMS feature (following this Infobip SMS2FA) in my node js app. So, I am facing an error which I'm guesing is an issue that it cant't get to the API. But my API credentials and URL are okay:
{
requestError: {
serviceException: { messageId: 'UNAUTHORIZED', text: 'Invalid login details' }
}
}
Here's the code. Check inside the signup router post:
const express = require("express");
const { createNewUser, authenticateUser } = require("./controller");
const router = express.Router();
const auth = require("../../middleware/auth");
const fetch = require('node-fetch');
const SENDER = 'InfoSMS_1';
const MESSAGE_TEXT = 'Here is the PIN';
const API_KEY = '<>';
const API_BASE_URL = '<>';
const API_2FA_BASE_URL = '<>';
const API_PIN_URL = '<>';
// protected route
router.get("/private_data", auth, (req, res) => {
res.status(200).send(`You're in the private territory of ${req.currentUser.phone}`);
});
// Signin
router.post("/", async (req, res) => {
try {
let { phone, password } = req.body;
phone = phone.trim();
password = password.trim();
if (!(phone && password)) {
throw Error("Empty credentials");
}
const authenticatedUser = await authenticateUser({ phone, password });
res.status(200).json(authenticatedUser);
} catch (error) {
res.status(400).send(error.message);
}
});
// Signup
router.post("/signup", async (req, res) => {
try {
let { name, phone, password } = req.body;
name = name.trim();
phone = phone.trim();
password = password.trim();
if (!(name && phone && password)) {
throw Error("Empty input fields!");
} else if (!/^[a-zA-Z]*$/.test(name)) {
throw Error("Invalid Name entered");
} else if (!(/^\d{7,}$/).test(phone.replace(/[\s()+\-\.]|ext/gi, ''))) {
throw Error("Invalid Phone number");
} else if (password.length < 8) {
throw Error("Password is too short");
} else {
// Good credentials
// Create new user
const newUser = await createNewUser({
name,
phone,
password,
});
// Call Infobip API to create a new 2FA application
const infobipSettings = {
method: 'POST',
headers: {
'Authorization': API_KEY,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
name: '2fa SMS demo application',
enabled: true,
configuration: {
pinAttempts: 5,
allowMultiplePinVerifications: true,
pinTimeToLive: '10m',
verifyPinLimit: '2/4s',
sendPinPerApplicationLimit: '5000/12h',
sendPinPerPhoneNumberLimit: '2/1d'
}
})
};
const response = await fetch(API_2FA_BASE_URL, infobipSettings);
const data = await response.json();
const applicationId = data.id; // Get the application ID from Infobip API response
console.log(`Application ID: ${applicationId}`);
// Message template
const messageTemplateSettings = {
method: 'POST',
headers: {
'Authorization': API_KEY,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
pinType: 'NUMERIC',
messageText: 'Your pin is {{pin}}',
pinLength: 4,
language: 'en',
senderId: 'Infobip 2FA',
repeatDTMF: '1#',
speechRate: 1
})
};
const messageTemplateResponse = await fetch(API_2FA_BASE_URL + `${applicationId}/messages`, messageTemplateSettings);
const messageTemplateData = await messageTemplateResponse.json();
const messageId = messageTemplateData.id;
console.log(`Message ID: ${messageId}`);
const sendPINSettings = {
method: 'POST',
headers: {
'Authorization': API_KEY,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
applicationId: applicationId,
messageId: messageId,
from: 'InfoBib SMS TEST PIN :0',
to: '<phone Number here>',
placeholders: {
firstName: 'LISA'
}
})
};
const sendPinResponse = await fetch(API_PIN_URL + '?ncNeeded=false', sendPINSettings);
const sendPinData = await sendPinResponse.json();
console.log(sendPinData);
res.status(200).json(newUser);
}
} catch (error) {
res.status(400).send(error.message);
}
});
router.post("/test/sendSMS", async (req, res) => {
const phoneNumber = '<>';
try {
console.log("Test");
const configuration = {
basePath: process.env.API_BASE_URL,
apiKeyPrefix: 'App',
apiKey: process.env.API_KEY
};
const smsMessage = {
from: SENDER,
destinations: [{ to: phoneNumber }],
text: MESSAGE_TEXT
};
const smsRequest = {
messages: [smsMessage]
};
const response = await fetch(`${process.env.API_BASE_URL}/sms/1/text/advanced`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `App ${process.env.API_KEY}`
},
body: JSON.stringify(smsRequest)
});
const data = await response.json();
res.json({ response: data.messages[0] });
} catch (error) {
res.status(500).json({ error: error.message });
console.log('Not Working :(');
}
});
module.exports = router;
I don't know what the issue is. I'd really appreciate it if anyone could help!