I have a project that uses MQTT and Redis to process message queue. Use authentication through the database with username and password.
But the username, password information is completely correct, but I get the error when client connect to MQTT. This error occurs on staging server but not on development.
I have spent 3 days trying to figure out the cause but have not found the reason.
Can someone help me please? I'm completely stuck. below is my MQTT authentication code
#MessagePattern('mqtt-auth-81DPKQnMr7bd4Op63dDB/staging')
async getNotificationsStaging(#Payload() userInfo: RedisCheckUserDto, #Ctx() context: RedisContext) {
const channelName = context.getChannel();
if (!channelName.includes(process.env.GIT_BRANCH)) return false;
return this.mqttAuth(userInfo);
return true;
}
private async mqttAuth(userInfo: RedisCheckUserDto) {
//Sunmi app
if (userInfo.clientId.startsWith('sunmi')) {
const outlet = await this.outletService.findOne(userInfo.username);
console.log(!outlet)
if (!outlet) return false;
const isValidPassword = userInfo.password === outlet.outletPin;
console.log(isValidPassword)
return isValidPassword;
}
return false;
}
this is code MQTT send to backend to authentication:
if (clientId.includes('staging'))
return await this.client
.send('mqtt-auth-81DPKQnMr7bd4Op63dDB/staging', {
clientId,
username,
password: passwordString,
})
.toPromise();
this code is connect with MQTT:
const _mqttClient = mqtt.connect(process.env.NEXT_PUBLIC_MQTT_URL, {
clientId: `sunmi-${process.env.NEXT_PUBLIC_ENV}-${randomId}-${outletId}`,
username: codeName,
password: outletPin,
});
someone please help me, I'm really stuck!!!
Related
I am using azure communication services in my react app to send email.
But It is giving CORS error
import { EmailClient } from "#azure/communication-email";
function App() {
const connectionString =
"**************************************************************************************";
const client = new EmailClient(connectionString);
const sender = "1000055393#hexaware.com";
const emailContent = {
subject: "Send email quick start test- JS sample",
plainText:
"Test Email from JS Send Email Sample Application\n\n This email is part of testing of email communication service. \\n Best wishes",
html: "<html><head><title>ACS Email as a Service</title></head><body><h1>ACS Email as a Service - Html body</h1><h2>This email is part of testing of email communication service</h2></body></html>",
};
const toRecipients = {
to: [{ email: "krnsda04#gmail.com", displayName: "Karan S" }],
};
async function main() {
try {
const emailMessage = {
sender: sender,
content: emailContent,
recipients: toRecipients,
};
console.log(sender,"sender");
const sendResult = await client.send(emailMessage);
console.log(sendResult,"result");
if (sendResult && sendResult.messageId) {
// check mail status, wait for 5 seconds, check for 60 seconds.
const messageId = sendResult.messageId;
if (messageId === null) {
console.log("Message Id not found.");
return;
}
console.log("Send email success, MessageId :", messageId);
let counter = 0;
const statusInterval = setInterval(async function () {
counter++;
try {
const response = await client.getSendStatus(messageId);
if (response) {
console.log(
`Email status for {${messageId}} : [${response.status}]`
);
if (response.status.toLowerCase() !== "queued" || counter > 12) {
clearInterval(statusInterval);
}
}
return;
} catch (e) {
console.log("Error in checking send mail status: ", e);
}
}, 5000);
} else {
console.error(
"Something went wrong when trying to send this email: ",
sendResult
);
}
return;
} catch (e) {
console.log(
"################### Exception occoured while sending email #####################",
e
);
}
}
main();
return <h3>hello ${connectionString}</h3>;
}
export default App;
But when running this code, I m getting this error.
Access to XMLHttpRequest at 'https://************************/emails:send?' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
In Azure docs, they have given the code in Node.js.
Since Iam using that code in react and accessing from front end, is it showing CORS error?
How to solve this issue?
As you can see in the SDKs and REST APIs docs, ACS Email library is meant to be used in a trusted service environment. This is because there is no reasonable way to protect your connection string in the browser.
In your case, building a Node.js backend and letting your React app talk to it would be a good and preferred solution.
I need to query mongo inside my Cypress tests to basically see if my POST is updating some fields, but I don't see a npm package for it like there is for sql server. Googling it I only see documentation and examples on how to seed the db.
Any thoughts, comments?
Thank you
Take a look at this post: https://glebbahmutov.com/blog/testing-mongo-with-cypress/
The gist of it:
-- plugins/index.js
/// <reference types="cypress" />
const { connect } = require('../../db')
module.exports = async (on, config) => {
const db = await connect()
const pizzas = db.collection('pizzas')
on('task', {
async clearPizzas() {
console.log('clear pizzas')
await pizzas.remove({})
return null
},
})
}
-- db.js
const { MongoClient } = require('mongodb')
const uri = process.env.MONGO_URI
if (!uri) {
throw new Error('Missing MONGO_URI')
}
const client = new MongoClient(uri)
async function connect() {
// Connect the client to the server
await client.connect()
return client.db('foods')
}
async function disconnect() {
// Ensures that the client will close when you finish/error
await client.close()
}
module.exports = { connect, disconnect }
Change the line await pizzas.remove({}) to whatever query you want to run, I'll assume you know how to get the result of the query and assert it.
I'm trying to authenticate users locally with Passport.js while not keeping session and using my own JWTokens.
I was following this tutorial:
Learn using JWT with Passport authentication
While also reading Passport.js documentation. I don't know what went wrong, but passport doesn't seem to notice that some functions are indeed functions.
I've got a Load function to select a User from the DB(mongo) given certain criteria(a user might logIn with e-mail or phone number).
load: function(options, cb) {
options.select = options.select || 'email phone';
return this.findOne(options.criteria)
.select(options.select)
.exec(cb);
}
I'm calling passport.authenticate in my routes:
// Controllers //
const Users = require('../../app/controllers/users');
...
...
app.post('/api/login', passport.authenticate('local', { failureRedirect: '/api/login' }), Users.login);
And here's my local strategy:
const mongoose = require('mongoose');
const User = mongoose.model('User');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(
{
usernameField: 'email',
phoneField: 'phone',
passwordField: 'password',
session: false
},
function(email, phone, password) {//cb == callback
const options = {
criteria: { email: email, phone: phone },
select: 'name username email hashed_password salt'
};
User.load(options, function(err, user) {
if (err || !user){
return res.status(400).json({
type: 'failure',
message: "User creation failed",
data: [err]
});
};
if (!user.authenticate(password)) {
return res.status(400).json({
type: 'failure',
message: "User creation failed",
data: [err]
});
};
req.login(user, {session: false}, (err) => {
if (err) {
res.send(err);
}
// generate a signed son web token with the contents of user object and return it in the response
const token = jwt.sign(user.id, 'your_jwt_secret');
return res.json({user, token});
});
});
}
));
I'm getting the following error:
TypeError: res.status is not a function
Before trying to get stuff back from passport with responde. I was trying to do it with cb(callback), as done in the tutorial, but I keep getting the same error.
Thanks in advance for any help!
There are a few issues with how you are implementing Passport's local strategy that are causing problems.
You are trying to use two fields as the username when Passport's local startegy only accepts one. (see: http://www.passportjs.org/packages/passport-local/)
function(username, password, done){}
If you want to use both as a username, you might want to consider creating your own custom strategy. This is going to be a little more in-depth, but you can start learning on the Passport Github page (https://github.com/jaredhanson/passport-strategy)
The second issue is that you are trying to get Passport to send a response in the local strategy which is not what it is intended to do. Instead, you should be passing the errors and return values to Passport's done() function, which will process them accordingly.
Here is an example of what your local strategy should look like:
passport.use(
new LocalStrategy(async (email, phone, password, done) => {
const options = {
criteria: { email, phone },
select: 'name username email hashed_password salt',
};
try {
const user = await User.load(options);
/**
* If null is returned meaning there was no user found, send the done call
* with the false flag. This tells passport to redirect to the failure URL.
*/
if (!user) {
return done(null, false);
}
/**
* If the user's password is incorrect, also return the done function with the false
* flag. This tells passport to redirect to the failure URL.
*/
if (!user.authenticate(password)) {
return done(null, false);
}
/**
* If a user is found and their password is verified, send the user object to
* the done function. This will tell Passport to call the next middelware attaching
* the user object.
*/
return done(null, user);
} catch (err) {
/**
* If there is an error with the DB call, return generic message
* for security purposes.
*/
return done('There was an internal server error.');
}
})
);
and an example of what your load function should look like:
load: options => {
return new Promise(async (resolve, reject) => {
options.select = options.select || 'email phone';
try {
const user = await this.findOne(options.criteria)
.select(options.select)
.exec();
resolve(user);
} catch (err) {
reject(err);
}
});
};
As a general best practice, I changed your callbacks to the newer method of promises (https://developers.google.com/web/fundamentals/primers/promises).
This should work in the way you are intending to use Passport.
I'm trying to send an email from my own domain without using an external SMTP server. I'm using NodeMailer's SMTP connection:
let options = {
secure: true,
port: consts.portOut,//465
host: consts.host, //mydomain.com
transactionLog: true,
debug: true,
requireTLS: true,
authMethod: 'PLAIN',
};
let connection = new SMTPConnection(options);
connection.connect(function() {
let auth = {
user: 'abc',
pass: 'def'
};
connection.login(auth, function(err) {
if (err) {
console.log("Authentication failed!", err);
}
console.log("Authentication to SMTP server successful.");
let envelope = {
from: 'fee#mydomain.com',
to: 'myemail#gmail.com'
};
let message = 'message hello world';
connection.send(envelope, message, function(err, info) {
if (err) {
console.log("err:::", err);
} else {
console.log('info?', info);
//connection.quit();
}
});
connection.quit();
});
});
connection.on("error", function(err) {
console.log(err);
});
My server code using NodeMailer's SMTP Server:
const options = {
secure: true,
size: 25000000, //25MB
authMethods: ['PLAIN'],
key: hskey,
cert: hscert,
ca: [hschain],
onAuth(auth, session, callback) {
if(auth.username !== 'abc' || auth.password !== 'def') {
return callback(new Error('Invalid username or password'));
}
callback(null, {user: 123}); // where 123 is the user id or similar property
},
onConnect(session, callback) {
console.log("the address is:", session.remoteAddress)
if (session.remoteAddress === consts.ip) {
return callback(); // Accept the address
} else {
return callback(new Error('Only connections from %s allowed', consts.ip));
}
},
onData(stream, session, callback) {
simpleParser(stream, (err, parsed) => {
if(err) {
console.error(err);
} else {
console.log(parsed);
}
});
stream.on('end', function () {
let err;
if(stream.sizeExceeded){
err = new Error('Message exceeds fixed maximum message size');
err.responseCode = 552;
return callback(err);
}
callback(null, 'Message queued as abcdef');
});
}
};
const emailServer = new SMTPServer(options);
emailServer.listen(consts.portOut, function () {
processSMTPConnection(consts, hskey);
});
emailServer.on("error", function (err) {
console.error("Error %s", err.message);
});
So after my client connects to my local SMTP server, the last message I get is 'Message queued as abcdef' and nothing ever sends (nothing ever arrives in my gmail inbox or any other email testing services)...
No incorrect ports are blocked, so I must be missing something(?).
Is this not how to correctly use NodeMailer?
Should I be able to send emails from my local domain using NodeMailer?
Documentation here has a note that states:
This module does not make any email deliveries by itself. smtp-server
allows you to listen on ports 25/24/465/587 etc. using SMTP or LMTP
protocol and that’s it. Your own application is responsible of
accepting and delivering the message to destination.
(emphasis mine)
Your server seems to accept the email (that's why it's showing that the message has been queued) but it doesn't delivers to destination.
To expand a little bit on how to send the message once it arrives to your SMTP server. If the TO address is local, just put the message in their mailbox. But if you want to "remail" the message, you need to contact the TO mail exchange with the message.
Something like:
const toExchange = getMX(parsed.to);
const outMessage = createMessageFromParsed(parsed);
const transporter = createTransport({
port: 25,
host: toExchange,
name: os.hostname(),
});
transporter.sendMail(outMessage);
I want to connect to rest API with auth in Meteor but when I run through their docs cant see anything stuff for connecting to rest API. All I can see it that the HTTP request. So, I tried using it. I need to connect to this:
URL: http://lpgp-dev.mrkt.it/test/oauth/rest/testview2
key: 'mykey'
secret: 'my secret'
For now I have this lines of code:
from server:
Meteor.methods({
getArticles: function () {
check(q, String);
this.unblock();
try {
var result = HTTP.call("GET", "http://lpgp-dev.mrkt.it/test/oauth/rest/testview2",
{params: {key: 's86MopNFA6pwmBXQoEw8k5yBVAVjN8vz', secret: 'cKC2tpXP3ZRQvqAsobCPeK2jB4kjsDos'}});
return result;
} catch (e) {
// Got a network error, time-out or HTTP error in the 400 or 500 range.
return false;
}
}
});
from client which I called the method:
var getResponse = function(){
Meteor.call('getArticles', function (error, result) {
if (!error) {
var res = JSON.parse(result.content);
/*var _res = _(res.response.docs).toArray();*/
/*Session.set('numCount', res.response.numFound);
Session.set('news', _res);*/
console.log(res);
}else{
console.log(error);
}
});
}
When I run it return this error:
errorClass: Internal server error [500] of undefined
hope you can help me. Thanks...