Retrieve Subject Alt Name from x509 in Node - javascript

I am trying to retrieve the SAN from a DoD Smart Card and running into an issue where the subject alternative name is returning othername:<unsupported>. I haven't found many examples of parsing this but I would have assumed X509 li in node would parse it. Looking for any direction on best way to get the email address.
app.use((req, res, next) => {
const cert = req.socket.getPeerCertificate();
app.set("user", cert);
const x509 = new X509Certificate(cert.raw);
console.log(x509.toJSON());
next();
});
Tried a library from F5 that they used for nginx but wasn't able to find the correct properties to pass for it to parse the email address.
https://clouddocs.f5.com/training/community/nginx/html/class3/module1/module17.html

Related

Approach to modify the database without logging the user?

I have a React frontend with a Node + MySQL backend, I'm sending an email to an user with two buttons to accept or decline a quote. What I'm trying to achieve is to make the buttons in the email modify the database securely without the user having to log into his account. My idea is to have two routes, one that sends the email containing the buttons which will have a url to my website with the jwt token on its parameters, and another for verifying said token and making the changes to the db. Here's some pseudo-code:
app.post("/email-quote", async function (req, res) {
const payload = {
uid: req.body.user.id,
quoteId: req.body.quote.id,
accepted: // true for the accept button, false for the decline button
}
const secret = ?
const token = jwt.sign(payload, secret);
// ...
// Generate and send email with buttons containing the url + the token
});
When the user clicks one of the buttons, I re-direct him to my website and there I can extract the token and verify its validity:
app.get("/verify-email-quote/:token", async function (req, res) {
const decodedJwt = jwt.decode(req.params.token);
const secret = ?
const verifiedJwt = jwt.verify(req.params.token, secret);
if (verifiedJwt) {
// Make the changes to the db
}
});
I wasn't able to find any examples trying to achieve something similar on the web, so I have these questions:
Would a jwt token be a good approach to achieve this?
If yes, what secret should I use to create the token?
If no, what other solutions could I look into?
Yes, you can do it this way.
The secret does not matter. As long as the secret is secret
It doesn't need to be a jwt token. It can just be a normal token. The incentive to using jwt is that you can embed a payload into the token. For your case, it looks like it is exclusively for verification purposes. It doesn't matter in the grand scheme of things, but if you don't have jwt already implemented, there's no need to go through all that extra work just for this use case.

Should I using separated express server for different type of user

I'm trying to use node.js+express.js to build web server.And their are two type of users in my site: normal user and manager. Manager have the right to write data in some field of my database, but normal user can only read them.
So my question is : should I using separated instantiation of express server for manager and normal user ? So they using different port and won't disturb each other?
There are many approaches to setting up user permissions for your backend Node.js server, but setting up separate instances of the server based on the role should not be one of them. There are many packages already out in the NPM ecosystem that could assist you in solving your problem, but depending it may be something as simple as a middleware you can write yourself for Express.js to solve your issue. Example:
export default function permit(...allowed) {
const isAllowed = role => allowed.indexOf(role) > -1;
// return a middleware
return (req, res, next) => {
if (req.user && isAllowed(req.user.role))
next(); // role is allowed, so continue on the next middleware
else {
response.status(403).json({message: "Forbidden"}); // user is forbidden
}
}
}
// Use as so
app.use("/api/private", permit("admin"));
app.use(["/api/foo", "/api/bar"], permit("owner", "employee"));
See middleware.

Twilio to OnSip app error: Dial->Sip: SIP URI DNS does not resolve or resolves to an non-public IP address

I'm using Twilio to build a SIP dialing solution for my company, and I'm receiving an error "Dial->Sip: SIP URI DNS does not resolve or resolves to an non-public IP address". I have a trial account at onsip to test the functionality, and when I call this account number it fails. The relevant TwiML is:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial callerId="+15555555555">
<Sip>sip:example#example.onsip.com</Sip>
</Dial>
</Response>
As far as googling has gotten me, I believe that I might need to whitelist my application. I also wondered that because I was using my application on localhost that was the issue, but I've used ngrok, and still receive the error.
It is impossible for Twilio to interact with OnSip because of the known issue laid out in this issue: https://support.onsip.com/hc/en-us/articles/204599674-Twillio-and-SRV
Hope this spares someone else a headache.
There is a way around this issue using Twilio's newly implemented functions.
Something like this should work--
const dns = require('dns');
let sipUri = 'xxxxx#onsip.com';
let protocol = 'udp';
let region = 'us2' ;
exports.handler = function(context, event, callback) {
var user = sipUri.split('#')[0];
var host = sipUri.split('#')[1];
// generate the TwiML to tell Twilio how to forward this call
let twiml = new Twilio.twiml.VoiceResponse();
const dial = twiml.dial();
dns.resolveSrv('_sip._'+protocol+'.'+host, (err, addresses) => {
var resolvedhost = addresses[0].name+':'+addresses[0].port;
dial.sip('sip:'+user+'#'+resolvedhost+';region='+region);
console.log(twiml.toString());
// return the TwiML
callback(null, twiml);
});
};
This manually queries the hostname for SRV records and then uses the first result returned. Does not take weight and priorities into account.
Nodejs docs

How to go about creating temporary authentication for a website?

I'm new to authentication with websites, and I've been doing a lot of reading on the different kinds of user authentication (for example session vs token authentication) you can use. However, a lot of it seems more than what I need, and I'm not sure which ones will be suitable for my cause.
My idea is to generate temporary user accounts and passwords that will expire after the first use. I want this integrated with my website, so they have one chance to view restricted pages, after which they will not allowed access to those parts again (unless provided with new credentials).
Any direction in the right step will be appreciated.
Update: I'm using Javascript(Node) as my server side language
Session-based authentication is actually incredibly lightweight if you're using a Node backend, due to most (if not all) webserver libraries supporting "middleware", which modify requests before they hit your route functions. The Express-compatable middleware client-sessions is fantastic for this, and I used it previously in a project with great success. It adds a cookie on the first request a user makes to your site which identifies them, and if at some point they log in, you can flag that session as authenticated, store session information, and other data related to them specifically.
Assuming you want both login & logout, the simplest way would to be to use POSTs over HTTPS to login & logout routes. Inside of the resolution for the login route, you would simply "mark for deletion" inside whatever database you're working with.
An example might look like this:
var app = express();
function authenticate(user, pw){
//do your application specific login verification here
}
function deleteAccount(user){
//do your application specific user removal here
}
app.use(require("express-session")({
secret : "YOUR-SECRET-KEY-HERE"
cookieName : "Session"
//any other desired config options go here
})
app.post("/login", function(req, res){
var user = req.body.user;
var pw = req.body.pw;
req.Session.isAuthenticated = authenticate(user, pw)
if(req.Session.isAuthenticated){
markForDeletion(user, pw);
}
res.write("logged in as: " + user);
res.end();
});
app.post("/logout", function(req, res){
deleteAccount(req.Session.username);
req.Session.username = "";
req.Session.isAuthenticated = false;
res.write("logged out!");
res.end();
});

ldapjs authentification (user login setup)

So I'm currently running node.js, which has ldapjs installed. My aim is to have a system that uses ldapjs to allow users to login with a username and password.
I have been reading over the http://ldapjs.org documentation for awhile now but am struggling to understand the whole idea of ldap and ldapjs's implementation of it.
I currently have this from the documentation
var ldap = require('ldapjs');
var server = ldap.createServer();
server.bind('cn=root', function(req, res, next) {
if (req.dn.toString() !== 'cn=root' || req.credentials !== 'secret')
return next(new ldap.InvalidCredentialsError());
res.end();
return next();
});
server.listen(1389, function() {
console.log('LDAP server up at: %s', server.url);
});
Which allows me to run the below and successfully bind to the server.
ldapsearch -H ldap://localhost:1389 -x -D cn=root -w secret -LLL -b "o=myhost" objectclass=*
But I'm really unsure of where to go from here or even if this is the correct approach...
The ideal setup would be to have a range of users and passwords, and on a successful ldap connection confirm the details are correct and respond with a true, or false if the username/pass was incorrect.
Does anyone know of any good resources for finding out more about this, or better yet can suggest some basic client/server side code to give me an idea of where to go next!
Any replies would be really appreciated.
Many Thanks
I never used ldapjs, but based on what I just quickly read in its seemingly incomplete document, it can be used to implement an LDAP server or an LDAP client, which seems to be what you're trying to do (i.e., I'm assuming you want to authenticate users in your application against an existing LDAP server). Most of the examples in its document focus on creating an LDAP server that listens on a certain port and interacts with a back-end database. If you're not trying to put an LDAP-based interface between your back-end database or store of users and passwords, then you probably don't need the server API. If you already have an LDAP server running, then you will need to use its client API to do something like this:
1.Bind anonymously to the LDAP server that provides the directory services including the authentication services. It looks like you can just do this with:
var ldap = require('ldapjs');
var client = ldap.createClient({
url: 'ldap://my.ldap.server'
});
2.Search by the username (e.g., e-mail address) for the corresponding entry's DN
var opts = {
filter: '(mail=USERNAME)',
scope: 'sub'
};
client.search('ou=users,o=acme.com', opts, function(err, res) {
assert.ifError(err);
res.on('searchEntry', function(entry) {
console.log('entry: ' + JSON.stringify(entry.object));
});
res.on('searchReference', function(referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function(err) {
console.error('error: ' + err.message);
});
res.on('end', function(result) {
console.log('status: ' + result.status);
});
});
3.Grab the DN of the returned entry ( entry.object ). The documentation of this library doesn't talk much about how these objects can be used (e.g., what their methods, properties, etc. are). So, you will have to figure out how to actually get the DN or string representation of the DN of the entry you just retrieved from the directory server. [See the comment(s) below this answer]
4.Rebind to the server using that DN:
client.bind(DN_RETRIEVED, PASSWORD_USER_ENTERED, function(err) {
assert.ifError(err);
});
5.The result of the bind above is what you will need to use to determine whether or not the authentication was successful.
If you are trying to implement an LDAP server in front of your user/password data store for LDAP-based authentication, then you will need to follow their server examples. I personally think this is an overkill and could be problematic in terms of security.

Categories

Resources