Is it possible to use Auth0 with CouchDB or Cloudant? If so, does anyone know a tutorial, code sample or github project for examples?
This question was already asked in the Auth0-Forum (not by me) but with no response: https://auth0.com/forum/t/can-you-use-auth0-with-couchdb-or-cloudant/3127
In my special case i want to connect a Ionic 2 App with Auth0 to a CouchDB instance without a middle (API) layer.
Any help would be appreciated!
There's the couch_jwt_auth plugin which allows users to authenticate via JWT tokens and hence allows this kind of scenario. There's even an example project on how to use it with pouchdb and Auth0, so guess this could be kind of useful for you.
I'm using the same plugin to authenticate users and it works flawlessly. I actually maintain a fork of it which allows JWT signature verification with asymmetric keys (RS256) - And yeah once I feel confident enough there'll be a pull request.
Will the user have its own database in couchdb?
Cause without a server side middleware you won't be able to limit access to only the users data.
If thats the case you could consider using oauth for it.
I am not deep into Auth0 but it seems to support it https://auth0.com/docs/oauth2-examples
as CouchDB too http://docs.couchdb.org/en/stable/api/server/authn.html#oauth-authentication
CouchDB 3.1 supports JWT auth out of the box.
The Couch docs on JWT auth are here.
Basically, update the [chttpd] section of the configuration to include the JWT section below. Well, you can delete default and/or cookie, but they're quite useful to keep around:
[chttpd]
authentication_handlers = {chttpd_auth, cookie_authentication_handler}, {chttpd_auth, jwt_authentication_handler}, {chttpd_auth, default_authentication_handler}
Then add this section, which is mentioned without example in the docs:
[jwt_auth]
; List of claims to validate
; As of couch 3.1, can NOT require issuer:
; required_claims = {iss, "http://issuer"} <-- does not work
; I left it blank and it's fine
required_claims =
and then add or uncomment this section:
[jwt_keys]
; Configure at least one key here if using the JWT auth handler.
; I found I had to inclue the 'kid' claim, even if it is just "_default".
; REMINDER: BASE64 ENCODED!
hmac:_default = aGVsbG8=
hmac:demo = aGVsbG8=
That's "hello", base64-encoded.
To get a JWT for this, do something like:
// once off...
const secret = 'hello'
// then, in an express-jwt handler somewhere...
const token = sign(data, secret, { subject: user.name, audience, algorithm, keyid: 'demo' });
return res.send({ error: null, token })
I found that subject (sub), audience (aud), algorithm (alg) and keyid (kid) all had to be included as JWT claims or CouchDB wouldn't accept the auth.
Try this: https://github.com/softapalvelin/couch_jwt_auth This plugin allows users to authenticate via JWT Tokens.
Related
I´m pretty new at nodejs, so I tried to implement an REST API with the loopback framework to try to simplify a bit the building process. I did correctly the models, also cusomized some endpoints, but, when connecting with the frontend (AngularJS), all the code I find, also the code I know to build, requires an JWT token to do any task that requires authorization/authentication, but it seems that loopback sends an uid2 token when I log in. I searched a lot, in stackoverflow and Github, the nearest thing I found is this (https://github.com/strongloop/loopback/issues/1905#issuecomment-310382322) but the code seems to fail here:
const data = jwt.verify(id, secretKey);
cb(null, {userId: data.id});
Any idea?
In simple words, you need to know who is making the call. If you'd use the default loopback authentication you would see that in the req object there is accessToken property which identifies the user. If you want to use JWT there are plenty of ready modules you could use, eg. loopback-jwt or loopback-jwt-advanced.
In general, what you need to do is to apply a middleware that will be responsible for authorization of your user( I strongly recommend you to get familiar with the middleware term). In simple words, middleware is a layer that your requests are going through and you can modify it's a body or reject the request.
In abstract steps, in your middleware you would have to:
get the token from the request
verify the token
identify the user based on the token
create the loopback AccessToken entity for that given user
put the token in the req.accessToken so now loopback will know who you are and you could use the ACL.
So this is more or less what those extensions are doing.
I develop an app with Ionic where each user got its own PouchDB database synchronise with its own remote CouchDB database. I use couch_peruser=true so any user that want to access its database need to authenticate.
This system is easy to do if we store the username & password locally or if we ask the user to give them anytime a sync is needed but none of these options are good (security concern or non user-friendly).
I came with those two options, but none is working:
1) The best option that came to me was to use Cookie Authentication, just save the token locally and use it, but unfortunately to connect with the token couchdb ask to use the header :
Cookie: AuthSession={TOKEN}
But this is not possible because it is a non-authorized header (unsafe) and is rejected by the browser.
2) Second option is to use couchdb Proxy Authentication but it is the same as saving the username and password as the token is valid forever.
Is there any way other way of handling authentication ? I was thinking to use an alternative users database, generate a fake password & username then send this credential to be saved into the user app. In this case if the security is compromise the user can change its password so the server can change the second password too (in the same way we revoke a token), but then there is still a problem because with the stolen credential it is always possible to access directly to the couchdb database without being seen..
Thanks for your help, i was not able to use couchdb-auth-proxy so I ended up with the following solution that has the advantage to prevent direct access to couchdb :
1) Create a node server to authenticate the user, if auth successful then return couchdb token to the app for cookie authentication
2) Create a node server used only as a couchdb proxy using node-http-proxy
with the following code :
(it is required that this router code come very early in the express middleware otherwise it might change the response and pouchdb sync does not work, so place it before app.use(bodyParser.json())
)
router.all('/*', (req: Request, res: Response, next: NextFunction) {
let token = req.get('X-Auth-Cdb-Token');
let httpProxy = require('http-proxy');
const proxy = httpProxy.createProxyServer({
target: target,
});
req.headers['Cookie'] = 'AuthSession='+token
proxy.web(req, res);
});
3) In your app set the pouchdb remote database with the following header :
remoteDB = new PouchDB(url, {
skip_setup: true,
ajax: {
headers: {
'X-Auth-Cdb-Token': couchdbToken
},
withCredentials: false
}
})
If you write a Progressive Web App, the Cookie Authentication is great for this, because the browser handles it for you. Use the pouchdb-authentication to log in directly to CouchDB.
On the CouchDB side, configure the Cookies as persistent, and put some longer lifetime on it. You can set it to 2 weeks, for example, so your users will only be asked for the password if they haven't logged in for two weeks.
The cookie TTL is automatically refreshed once a certain threshold is reached (I recall it's at half of the cookie TTL, so it would be refreshed if the cookie is more than a week old).
CouchDB is built for the web, so you can take advantage of it. ;-)
I'm currently working on a simple API that's going to be the backend of my app. I'm designing my data structures right now and have some questions about security best practises.
Project background
The project is written in node.js
Since this is going to be an API (with a couple of protected methods) I think it's best to use an access token based authentication system. (user logs in and retrieves their token, which can then be used to access the protected methods)
The data is structured in such a way that every user has both a unique username and a unique token. For the purpose of this question (and my project) let's assume that this token never ever changes. However it is stored in plain text in the database.
To make sure that people with access to the database don't have direct access to the API by just copying this token I encode the token before I send it out. This way the actual authentication token is not the same as the token stored in the database but the server can decode the auth_token to recreate the token and blah blah..
However people with access to the database can just encode the token themselves... And I'm trying to find out if there's a workaround to this problem.
My question:
I'm trying to find out if there's an even safer way to do this. So please give me all of your ideas and best practise rules etc.
BTW, I considered using a salted hash as encryption but this creates the exact same problem, to match the stored token with the actual access token you'll need to also store the salt, since you can't revert an encryption like that. And storing the salt gives people with access to the database a way to create the actual access token...
PS:
I'm trying to create the entire authentication process myself, so please don't suggest things like passport.js. I mean there are great helper tools out there, I just want to do this all manually.
[Update] project background
Down here I'll attempt to sketch some more background to this project.
It is indeed a project for high school informatics. (as mentioned below)
The idea is simple: a TODO app, you might have heard of node-todo, that's basically it.
This is a group assignment and the levels of expertise among the group members highly varies. (Some have only ever done HTML and (some) CSS, others have done some JS) I've taken the responsibility of creating the backside of the application (the API to interact with the database) since none of the other group members know how. Since the other group members are not all as experienced I have no clue what the front end is going to look like. (My best guess it'll start off a web app)
So basically I want to create a backend that works for every client, and it should be independent. That is, the client is not going to be hosted on the same server (most likely the test are going to be locally only).
API-oriented. Modern applications compose and expose APIs everywhere. They build on open web techniques and use REST, XML and JSON to make it easy for all types of devices and clients to easily consume data. Any visible service or piece of data has a "headless" API counterpart, so that alternative views can be provided. In many cases, the APIs that a modern application exposes form the basis for a public, 3rd party developer community that enables mash-ups, plug-ins and innovation on a core set of data and services that drive a company's business
~ zdnet.com
If you do not mind saving state on your server, you could use a hashtable to save tokens:
Once the user logs in, you generate a random hash. This hash is used as key in the table. You can verify incoming requests by validating that the used token is indeed a key in your table.
To be able to identify which user is logged in, you should add a user identifier (like user email) to the saved object. You might also want to add the used IP-address and an expiration date to this object to further improve security.
By using this technique, you do not need to save tokens in your database :) Only hashed passwords
(You might want to clean your hashtable now and again to delete expired entrees)
Good luck on your project and say hi to Ramon for me
I usually just use jwt with it's own salting process. I don't store the token at all in my db, but just use it to store the user's information and set an expiry of 8 hours or so.. This way, you don't need to store tokens in the db, you just decode the token on each request and access the userID stored within its payload. The only downside is if someone steals someone elses token, but you can add in an IP address to the payload and make sure the clients ip is the same as the one stored in the token.
I'm not using passport, but I am using bcrypt for password encrption and JWT for my tokens. Sorry if this isn't what your looking for. Cheers.
Here is my auth library:
(function() {
var bcrypt = require('bcrypt-nodejs'),
jwt = require('jsonwebtoken'),
helpers = require('../lib/helpers.lib.js');
var JWT_SECRET = 'XXXXX';
module.exports = function() {
var self = this;
//Returns true if valid token given, false otherwise
self.validToken = function(token) {
if (token) {
try {
var decoded = jwt.verify(token, JWT_SECRET);
return true;
} catch (err) {
// console.log(err)
return false;
}
} else {
return false;
}
};
self.decodeToken = function(token) {
if (!token) {
return null;
}
try {
var decoded = jwt.verify(token, JWT_SECRET);
return decoded;
} catch (err) {
// console.log(err)
if (err.name == "TokenExpiredError") {
return 'expired';
}
return null;
}
};
self.createToken = function(payload, expires) {
options = { "expiresIn": ((expires) ? '2d' : '14d') };
return jwt.sign(payload, JWT_SECRET, options);
};
self.hashPassword = function(password) {
return bcrypt.hashSync(password)
};
self.comparePassword = function(plainTextPassword, hashedPassword) {
return bcrypt.compareSync(plainTextPassword, hashedPassword);
};
return self;
};
}());
multiple things come in mind:
- have you looked at Firebase?
- what about things like two factor authentication (e.g. speakeasy or authy)?
You do not give too many details on the project background, I understood from mr. Moorlag that it has to do with high school informatics. So in case you want to make a proof-of-concept (e.g. for a Profielwerkstuk (± high school thesis in Dutch schools)) you would have different requirements than 'just implementing an app' that you would want to publish in the Play / App Store of course.
Some minor students of mine did a workshop two weeks ago about Firebase and then you do not need to worry about such a things, works really great (note: Firebase is NoSQL so forget normalization ;)). If you want to do research on it I would find out the details about two factor authentication and also have a look at TLS / HTTPS (Let's Encrypt?! yay!).
I'm using JWT (jsonwebtoken) package with node for token handling.
Is there any way to "logout"/revoke/invalidate a token?
If you just want to log the current user out, like #Massimiliano said, it's often implemented by deleting the token from whatever client-side store you've been using to keep track of it (eg. cookies).
If you need revocation for security reasons, here's an article that talks about why you might not want to go with JWT's in the first place, and instead use regular, opaque Bearer tokens (implemented by storing them in a database, often using a secure random string as their ID).
https://www.dinochiesa.net/?p=1388
Basically, they aren't revocable without adding a database lookup (negating one of the main reasons to use JWT's to begin with). And in the case of needing to revoke via a user interface, you're going to want to be able to query for tokens by user_id or group_id or similar, so you'll want to be able to index tokens by that information, instead of having it be opaque in the JWT claims.
with jwt authentication there is no need to insert the token in a database, if you want to revoke/logout/invalidate a token, just delete it locally in the browser there where you have decided to store it (cookie or header), in that case at the next call of whatever route (protected by authentication) the server, if had a good programmer, should ask you authentication again.
Hope this help, ciao.
I like that had this problem, I decided it this way:
First i create model session for db, like this:
var SessionSchema = new Schema({
user_id: { type: String, required: true },
tokenHash: { type: String, required: true }
});
After create token i save session, when user do something in my "checkSession" midleware i search token in db, if he exist i verify him, if not exist send auth_error, if token exist in db but expired, i remove him from db and send auth_error, if i delete or block user i remove session from db to.
Try, maybe this help you.
I'm working with mean.js, and I have a little doubt about authentication and authorization here...
MEAN.js come with a out of the box passport.js implementation that seems to be working good enough for me just to know when a user is logged in. But at the moment of authorization some question pop up in my mind.. doing my research I reach some answers and I don’t know what is the best way of implementing security API calls in my app.
So far, I'm taking this solution:
Using express.all() function to set in one file all my authorization functions ( I guess it is a good practice right ? ).. creating a file with the following code example:
'use strict';
var passport = require('passport');
module.exports = function(app) {
app.route('/private/p/*').all(function(req, res, next){
if(!req.isAuthenticated()){
res.send(401);
}else{
next();
}
});
app.route('/private/byRoles/*').all(function(req, res, next){
if(!req.isAuthenticated()){
res.send(401);
}else{
var urlRoles = ['admin', 'godlike'];
// ROLE LOGICS THAT ARE GOING TO BE ADDED TO MY USER
// GETTING MY USER ID BY THE DE-SERIALIZE PASSPORT FUNCTION AND GETTING MY
// MONGO MODEL FOR MY USER, WITH THE INFO OF ROLES IN THERE AND DOING
// SOME LOGICS HERE ABOUT THE ROLES AND URL PATTERN.
if ( hasRole(urlRoles, user.roles)){
next();
}else{
res.send(401);
}
}
});
};
So far this is the solution that I'm planning to implement, but I would like to be sure of what I'm doing here... is there a better way of implementing authorization in mean.js ? Is this authorization middle-ware wrong implemented with passport? I don't sure if is necessary to implement another strategy to this.. or if this implementation has a security lack ( sure it has to ).. is better to use Oauth or using api token ??? what should be the architecture to secure an app made in MEAN.js supporting roles and permissions ?? also in the future I would need to secure my socket.. I was looking at passport-socketio.. but not sure if is there a better solution.
I use JWT's for my angular apps. There are many articles out there about the benefits for using tokens instead of sessions or cookies Cookies vs Tokens. Getting auth right with Angular.JS.
You can do everything you want with JWT, roles for backend and frontend, securing sockets is also possible and there are packages for this functionality. You do not need passport if you using tokens. You check the the credentials one time and store the token in the browsers local storage. There are many packages for express and JWT Express-JWT
For a closer look at JWT jwt.io