Skip to content

Instantly share code, notes, and snippets.

@twilson63
Last active February 28, 2019 17:24
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save twilson63/12020bb70a77813a7740 to your computer and use it in GitHub Desktop.
Save twilson63/12020bb70a77813a7740 to your computer and use it in GitHub Desktop.
Offline First Native Web Applications with couchdb or pouchdb

Building Offline First Native Web Applications

Creating Offline First Native Web Applications using PouchDB and CouchDB and replication is a nice approach to remove the challenges keeping the client database insync with the server database.

One thing that always comes up is security, and security is very important and should not be taken lightly. Using implementations like JWT or JsonWebToken and external authentication services like Auth0 and StormPath can create a solid pattern to keep your secrets off of your client.

Using JWT, when the user authenticates with the JWT Server, they receive a token, this token can be used to access the remote couchdb server or pouchdb server for replication. You can implement jwt support in couchdb itself or you can use a gateway.

A gateway will perform the jwt authentication and proxy to the server.

https://github.com/twilson63/express-pouchdb-jwt is a gateway microservice that will cache the remote server db on the app server, so that requests only have to go one way and the reads and writes are very fast.

You can setup one up in nodejs like so:

var app = express()
var corsSettings = cors({
  origin: origin,
  credentials: true
})
app.options('*', corsSettings)
app.use(corsSettings)
app.use(jwt({secret: new Buffer(process.env.JWT_SECRET, 'base64') }))
app.use('/', require('express-pouchdb')(MemPouchDB))
var local = MemPouchDB(localDb)
PouchDB.sync(local, remoteDb, {
  live: true,
  retry: true
})

app.listen(process.env.PORT || 8080)

By using a Auth Service and a Database Gateway, we can create a offline native app without having to store any secrets on the client.

When using a gateway server for pouchdb replication, it is important to setup your ajax headers to use the jwt token

remoteDb = PouchDB(event.object.remoteDb, {
      ajax:{
        headers: {
          Authorization: 'Bearer ' + event.object.token
        }
      }
    })
@schamp
Copy link

schamp commented Mar 8, 2016

that looks great for authentication, but how would you suggest implementing an authorization layer, to make sure a user's access constraints? could you do some kind of filtered replication, based on (say) scope provided in the JWT? and how would you protect the data in the DB once it's replicated to the client (e.g., after token expiration / revocation, etc.)?

@twilson63
Copy link
Author

that looks great for authentication, but how would you suggest implementing an authorization layer, to make sure a user's access constraints?

Filtered replication or One Database per Account and CouchDB Security Roles

could you do some kind of filtered replication, based on (say) scope provided in the JWT?

Yes

how would you protect the data in the DB once it's replicated to the client (e.g., after token expiration / revocation, etc.)?

I am not sure I follow this one, protecting the data on client depends on the client datastore, for pouch you could use the pouchdb encryption as well as name each database by a unique id tied to that user or account.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment