I am doing azure ad authentication in my node js bot.
in the last step it is showing a pop windows with magic code.
I want to close that magic window pop up automatically after 5 sec.
this is code
res.send('Welcome ' + req.user.displayName + '! Please copy this number and paste it back to your chat so your authentication can complete: ' + magicCode);
this line send a window pop with magic code. iwant to close this window after 5 sec automatically.
my code
server.get('/api/OAuthCallback/',
passport.authenticate('azuread-openidconnect', { failureRedirect: '/login' }),
(req, res) => {
console.log('OAuthCallback');
console.log(req);
const address = JSON.parse(req.query.state);
const magicCode = crypto.randomBytes(4).toString('hex');
const messageData = { magicCode: magicCode, accessToken: req.user.accessToken, refreshToken: req.user.refreshToken, userId: address.user.id, name: req.user.displayName, email: req.user.preferred_username };
magicNum = magicCode;
var continueMsg = new builder.Message().address(address).text(JSON.stringify(messageData));
console.log(continueMsg.toMessage());
test_name = JSON.parse(req.user._raw).preferred_username.split("#")[0]
bot.receive(continueMsg.toMessage());
res.send('Sign-in successful');
}
);
Thanks in advance
It looks like you are using botauth lib, if so, there should be a html page which you need to use to display magic code.
This html should contain a similar js script code like:
document.getElementById("magic_code").innerText = (window.location.hash || '').replace('#', '');
And you can add following code to close the window in 5 secs
setTimeout(() => {
window.close();
}, 5000);
The similar code sample at https://github.com/CatalystCode/node-authbot. And all use the OAuth 2.0 process, which once user success signin the authenticate provider, it will redirect to your return url you configed in your server.
In your code, your auth return route simply send a string in browser. Also, you can render a HTML page to your user, however, you will face the issue
Scripts may close only the windows that were opened by it.
The same as the question you provide in comment.
Unfortunately, there are several question for this on SO:
window.close() doesn't work - Scripts may close only the windows that were opened by it
window.close and self.close do not close the window in Chrome, and currently no good solution for this.
Related
I want to protect the api of the current user, I am starting to learn Node.js but I know that I can get the request information so I wrote this code in which I try to prevent sensitive data from appearing if someone takes the API link and puts it on the browser or postman.
My question: is this method correct to use?.
(sorry for the poor english)
module.exports.current_user_get = (req, res) => {
// If the API is opened by browser or postman
if (req.rawHeaders.indexOf("User-Agent") > -1) {
return res.json({ msg: "Not allowed" });
}
// return user data
};
I've been stuck on this problem for a day now and was wondering if there's a way I could go about this.
client side
Client side is going to be dynamic since it's an app type plugin.
The client side will open up a popup for oAuth purposes. Let's say its domain is www.google.com
I have the popup written like window.open('www.backend.com/api') in ReactJS.
The client button is something like this:
<button onClick={() => iveBeenClicked()}> sync up </button>
and then it runs this function
const iveBeenClicked = (e) => {
e.preventDefault()
const popupWindow = window.open('www.backend.com/api', "_blank")
}
oAuth and backend with ExpressJS
This is the backend which we'll say is www.backend.com/api
router.use("/api", (req, res) => {
if (req.query.code) {
res.send(res.query.code)
} else {
res.redirect(
`www.ApiRouteThatRedirectsWhenComplete.com`
);
}
});
Well I have the code I want, but how can I send that to the client from a different domain? If there's an alternative to window.open() where a user could press accept, please let me know.
So the big question is, how can client receive data from window.open's popup?
Thank you in advance!
#EDIT
So I finally got it thanks to #vishal-bartakke 's suggestion which I realized I implemented it wrong. I'm going to supply it here just in case it will help anyone that comes across this post.
for the ivebeenclicked() function in client side:
const iveBeenClicked = (e) => {
e.preventDefault()
const popupWindow = window.open('www.backend.com/api', "_blank")
//this is the part that was needed to receive the information of success
window.addEventListener('message', (e) => {
if (e.data) {
//do what you need to do with that key
}
})
}
in my expressjs's file:
router.use(['/api/', '/api/page?'], (req, res) => {
if (req.query.token) {
res.sendFile(path.join(__dirname +'/thatHTMLpage.html'))
} else {
res.redirect(`that route that does the oauth`)
}
})
In that html created upon success, I added this code to send in the data
window.onload = function () {
let urlParams = new URLSearchParams(window.location.search);
window.opener.postMessage(urlParams.get("code"), "*");
};
It is quite a messy setup but it works how I want it.
Thanks!
You can use postMessage (check here) to communicate between windows. In child window you can refer parent window as window.opener for posting message and in parent window you have popupWindow for posting
I'm using the express-socket.io-session on my app. I've integrated it and it works properly. There is only one case though.
Have a look at the following code:
io.use(...);
io.sockets.on("connection", function (socket) {
socket.onVerify = (msg, fn) => {
socket.on(msg, (data) => {
console.log(socket.handshake.session.passport);
if (typeof socket.handshake.session.passport === "undefined") {
socket.emit("auth failed emit", {
msg: "Please login via the website"
});
return false;
}
fn(data, socket.handshake.session);
});
}
socket.onVerify("chat message", function (req, session) {
Chat.publish(session.email, req.msg);
});
});
Basically, on each socket request, I verify socket.handshake.session.passport being defined, which means user is logged in.
It works in this case:
I open a browser tab, login with my credentials, get redirected to /game endpoint where my game loads and connects to socket.io
I click on "logout" button, get redirected to /game endpoint, game tells me "I need to authorize."
However, it doesn't work in this case:
I open a browser tab, login with my credentials, get redirected to /game endpoint where my game loads and connects to socket.io
I click on "logout" button ON A NEW TAB, and logout in that tab.
I switch back to main tab, and game is still online.
I added a debug in my code (console.log(socket.handshake.session.passport)) and it shows { user: 1 } although I logged out already so it must be undefined
For some reason, socket.io handshake/session doesn't recognize it, so I probably need to refresh it on certain cases.
Is there any way to do it with socket.io?
This is just a try to resolve your issue, i'm not really sure it would work. But you could try something like that :
app.get("/logout", function(req,res){
//do other logging out stuff
sockets.disconnectUser(req.session.user_id);
}
// Disconnect User function
sockets.disconnectUser = function(user_id){
sockets.socket(users[user_id]).disconnect();
}
Like described here : Destroying a handshake after logout. socket.io
I'm trying to get my first web app ever off the ground so I'm well aware this is a kind of beginner question.
I am using Node, express, and Mongo for the backend with Stormpath providing user login / authentication and jade for views. The login functionality works fine, It just that I want to hide the 'Upload New Schedule' button for users that are not managers:
// app.js
...
app.use(stormPathmiddleware);
app.get('/', function(req, res) {
res.render('home', {
title: 'Welcome'
});
);
app.get('/upload', stormpath.groupsRequired(['Enforced']), function(req, res) {
res.render('upload', {
title: 'Upload Excel File'
});
});
....
I have two groups of people that I want using this: managers and everyone else. So home.jade:
html
head
title=title
link(href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css', rel='stylesheet')
body
div.container
div.jumbotron
h1 Hello!
if user
p Welcome, #{user.fullName}
p
a.btn.btn-primary(href="/upload") Upload New Schedule
br
br
a.btn.btn-primary(href="/logout") Logout
else
p Login now to see this weeks schedule.
p
a.btn.btn-primary(href="/login") Login now
How can I make jade hide the upload button to people who are not logged in as the first group (managers)? The middleware works great, that is people who are not managers will get an error page if they try to click that button, but I'd rather just hide it.
what you'll need to do here is:
Pre-load the permission check you want to do in your route code.
Pass this into your template.
Use this variable in your template to display or not display stuff.
Here's how it could work for your use case:
app.get('/upload', function(req, res, next) {
var isManager = false;
// Search through this user's groups, for any group named 'managers'.
req.user.getGroups({ name: 'managers' }, function(err, groups) {
if (err) return next(err);
// If this user is a member of a 'managers' group, it means
// this user is a manager.
if (groups.items && groups.items[0].name === 'managers') {
isManager = true;
}
res.render('upload', {
title: 'Upload Excel File',
isManager: isManager // Pass in the membership information to Jade.
});
});
});
Now that we've defined a route and passed in the manager information, we can write a Jade file that does something like this:
if isManager
// display html code here for managers
else
// display NON manager html code here
Hopefully this was helpful! I'm the author of this library, and just stumbled across this =)
I'm currently looking at new ways to make this easier in the future, so hopefully it'll be quite a bit simpler in the next big release =)
I have managed to get file uploading work in Node.js with Express, and in the code i'm checking whether it's an image or not that the user is trying to upload.
If the file was successfully uploaded I want to show a message to the user, directly to the HTML page with the uploading form. The same should be if the file the user tried to upload wasn't an image, or something else happened during the upload.
The code below works (res.send...) but it opens up a new page containing only the message.
My question is: How can I change my code so that the message is sent directly to the HTML page instead? If it could be of any use, i'm using Jade.
Thanks in advance!
app.post('/file-upload', function(req, res, next) {
var fileType = req.files.thumbnail.type;
var divided = fileType.split("/");
var theType = divided[0];
if (theType === "image"){
var tmp_path = req.files.thumbnail.path;
var target_path = './public/images/' + req.files.thumbnail.name;
fs.rename(tmp_path, target_path, function(err) {
if (err) throw err;
fs.unlink(tmp_path, function() {
if (err) {
throw err;
res.send('Something happened while trying to upload, try again!');
}
res.send('File uploaded to: ' + target_path + ' - ' + req.files.thumbnail.size + ' bytes');
});
});
}
else {
res.send('No image!');
}
});
from what I understand you are trying to send a message to an already open browser window?
a few things you can do,
Ajax it, send the post, and process the return info.
Submit it as you are doing now, but set a flash message (look at http://github.com/visionmedia/express-messages) and either res.render the form page, or res.redirect to the form function
now.js or a similar solution. This would let clientside use serverside functions and serverside code to run clientside functions. So what you would do would be on submit, pass the post values to a serverside function, which will process it and trigger a clientside function (display a message)
For my money option #2 is probably the safest bet, as clients without javascript enabled will be able to use it. As for usability #1 or #3 would give a more streamlined appearance to the end user.
You can use WebSockets. I recommend using Socket.IO, it's very easy to work with. On the client-side you would have an event-handler which would use JavaScript to append the new information to that page.
You could then have the server for example say:
socket.emit('error', "Something happened while trying to upload, try again!");
and the client would use:
socket.on('error', function(data){
//alert?
alert(data);
});
http://socket.io/#how-to-use