authentic-client
Version:
The client component of Authentic. This helps interact with an `authentic-server` so that you can easily signup, confirm, login, and change-password for users. It will also help send tokens to microservices that require authentication.
207 lines (173 loc) • 5.54 kB
JavaScript
var fs = require('fs')
var tape = require('tape')
var http = require('http')
var path = require('path')
var levelmem = require('level-mem')
var authenticClient = require('../')
var authenticServer = require('authentic-server')
var authenticService = require('authentic-service')
var client
var lastEmail
var service
var serviceUrl
var server
var serverUrl
var throwsWhen = [
{
arg: undefined,
message: 'opts are required argument'
},
{
arg: {},
message: 'opts.server must be url'
}
]
throwsWhen.map(function (obj) {
tape(`throws when arg is ${obj.arg}`, function (t) {
t.plan(1)
t.throws(function () {
authenticClient(obj.arg)
}, obj.message)
})
})
tape('init', function (t) {
server = createServer()
server.listen(0, function (err) {
if (err) return console.error(err)
serverUrl = 'http://localhost:' + this.address().port
client = authenticClient({server: serverUrl})
service = createService(serverUrl)
service.listen(0, function (err) {
if (err) return console.error(err)
serviceUrl = 'http://localhost:' + this.address().port
t.end()
})
})
})
tape('no token, verify errors', function (t) {
client.verifyToken(function (err) {
t.equal(err.message, 'jwt must be provided', 'error matches')
t.end()
})
})
tape('request microservice without token', function (t) {
client.get(serviceUrl, function (err, data) {
t.equal(err.message, 'forbidden', 'should get forbidden error')
t.equal(err.statusCode, 403, 'should get 403 status code')
t.deepEqual(err.body, {error: 'forbidden'})
t.end()
})
})
tape('bad token, verify errors', function (t) {
client.setAuthToken('1234')
client.verifyToken(function (err) {
t.equal(err.message, 'jwt malformed', 'error matches')
t.end()
})
})
tape('signup, confirm, login', function (t) {
var signOpts = {
email: 'chet@scalehaus.io',
password: 'notswordfish',
confirmUrl: 'http://admin.scalehaus.io/confirm'
}
client.signup(signOpts, function (err, resp) {
t.ifError(err, 'should not error')
t.equal(resp.success, true, 'should succeed')
var confirmToken = lastEmail.confirmToken
t.equal(confirmToken.length, 60, 'should get confirmToken')
var confirmOpts = {
email: signOpts.email,
confirmToken: confirmToken
}
client.confirm(confirmOpts, function (err, resp) {
t.ifError(err, 'should not error')
t.equal(resp.success, true, 'should succeed')
t.ok(resp.data.authToken.length > 800, 'should get authToken')
t.equal(resp.data.authToken, client.authToken, 'should store token')
t.end()
})
})
})
'get delete'.split(' ').map(function (method) {
tape('microservice ' + method.toUpperCase() + ' with token', function (t) {
client.get(serviceUrl, function (err, data) {
t.ifError(err, 'should not error')
t.equal(data.email, 'chet@scalehaus.io', 'should have auth email')
t.end()
})
})
})
'post put'.split(' ').map(function (method) {
tape('microservice ' + method.toUpperCase() + ' with token', function (t) {
var postData = {dummy: 'data'}
client[method](serviceUrl, postData, function (err, data) {
t.ifError(err, 'should not error')
t.equal(data.authData.email, 'chet@scalehaus.io', 'should have auth email')
t.deepEqual(data.postData, postData, 'should get postData')
t.end()
})
})
})
tape('microservice MAGIC-REQUEST', function (t) {
var magicRequestOpts = {
email: 'chet@scalehaus.io'
}
client.magicRequest(magicRequestOpts, function (err, resp) {
t.ifError(err, 'should not error')
t.equal(resp.success, true, 'should succeed')
var magicToken = lastEmail.magicToken
t.equal(magicToken.length, 60, 'should get magicToken')
var magicLoginOpts = {
email: magicRequestOpts.email,
magicToken: magicToken
}
client.magicLogin(magicLoginOpts, function (err, resp) {
t.ifError(err, 'should not error')
t.equal(resp.success, true, 'should succeed')
t.ok(resp.data.authToken.length > 800, 'should get authToken')
t.equal(resp.data.authToken, client.authToken, 'should store token')
t.end()
})
})
})
tape('cleanup', function (t) {
server.close()
service.close()
t.end()
})
function createServer () {
return http.createServer(authenticServer({
db: levelmem('mem', {valueEncoding: 'json'}),
publicKey: fs.readFileSync(path.join(__dirname, '/rsa-public.pem'), 'utf-8'),
privateKey: fs.readFileSync(path.join(__dirname, '/rsa-private.pem'), 'utf-8'),
sendEmail: function (emailOpts, cb) {
lastEmail = emailOpts
setImmediate(cb)
}
}))
}
function createService (serverUrl) {
var decrypt = authenticService({server: serverUrl})
return http.createServer(function (req, res) {
decrypt(req, res, function (err, authData) {
if (err) return console.error(err)
if (!authData || !authData.email) {
res.writeHead(403, {'Content-Type': 'application/json'})
return res.end(JSON.stringify({error: 'forbidden'}))
}
res.writeHead(200, {'Content-Type': 'application/json'})
if (req.method === 'GET' || req.method === 'DELETE') {
return res.end(JSON.stringify(authData))
}
var buf = ''
req.on('data', function (chunk) { buf += chunk })
req.on('end', function () {
res.end(JSON.stringify({
authData: authData,
postData: JSON.parse(buf)
}))
})
})
})
}