node-clinic/test/authenticate.test.js
Renée Kooi 3cbe86ec5d
Next (#118)
* clinic ask (#66)

The `ask` command is used to upload on the private area, e.g.: 
```
clinic ask --upload-url=http://localhost:3000 11213.clinic-bubbleprof
```
This will:
- Start the authentication on upload server to obtain a JWT token
- Upload the data to the protected API `/protected/data` on upload server

On the server side, the API can extract the user email from the JWT token to correctly identify the "private" folder for the user

* Authenticate for public uploads and support private uploads without `ask`ing (#102)

`clinic upload xyz.clinic-doctor` now also requires authentication.

A new `clinic upload --private` flag uploads to your private area.

`clinic ask` does `clinic upload --private` and then calls a currently-noop function that can be implemented once we have a `/ask` endpoint on the server.

* Store auth tokens in ~/.node-clinic-rc (#108)

Stores the JWT in ~/.node-clinic-rc after logging in. ~/.node-clinic-rc is a JSON file with upload URLs as keys, JWTs as values.

Use `clinic login` to login manually. Optionally specify an `--upload-url`.
Use `clinic logout` to logout manually. Optionally specify an `--upload-url`. Add `--all` to log out of all Clinic Upload servers, this deletes the ~/.node-clinic-rc file.
Use `clinic user` to show a list of current sessions. Optionally specify an `--upload-url` to only show that session.

You can use the `CLINIC_CREDENTIALS` environment variable to point to a different file. I added this for tests, maybe it's also useful in programmatic environments and warrants docs?

`clinic upload` and `clinic ask` automatically do what `clinic login` does at the start.

* Feature/ask auth flag (#114)

* [666] - Add ask param flag to login URL when authenticating using ask command

* [666] - Factor user terms acceptance into CLI login when validating JWT payload against upload type

* Implement ask with placeholder message (#115)

Means we'll have to reply first to figure out what someone needs help with but it's better than not getting a message at all

* 3.0.0-beta.0@next

* Fix/private public auth redirect (#116)

* Re #99 - Pass flag for private uploads to login URL so app can differentiate intent

* Re #97 - Open new tab on upload callback and create flag to prevent this behaviour if desired

* Re #97 - Update browser open flag to use recommended minimist syntax

* Revert "Disable clinic upload in old CLI. (#117)"

This reverts commit 75f80771b4741a4927788a2d492566d04416e1b7.

* Update tool versions.

* remove weird test? unsure what this was for
2019-02-13 14:34:53 +01:00

140 lines
3.6 KiB
JavaScript

'use strict'
const http = require('http')
const test = require('tap').test
const websocket = require('websocket-stream')
const proxyquire = require('proxyquire')
let server, cliToken
let simulateTimeout = false
let simulateNoToken = false
test('Before all', function (t) {
server = http.createServer(() => {})
websocket.createServer({ server }, conn => {
conn.on('data', token => {
cliToken = token.toString('utf8')
if (simulateTimeout) {
conn.write('timeout\n')
} else if (simulateNoToken) {
conn.write('\n')
} else {
conn.write('jwtToken\n')
}
conn.end()
})
})
server.listen(0, function () {
t.plan(1)
t.ok(server)
})
})
test('authenticate', async function (t) {
let openedUrl = ''
const opnStub = url => {
openedUrl = url
}
const authenticate = proxyquire('../lib/authenticate', { 'opn': opnStub }) // mocking the browser opening
const jwtToken = await authenticate(`http://127.0.0.1:${server.address().port}`)
t.plan(2)
t.strictEqual(openedUrl.split('/auth/token/')[1].replace('/', ''), cliToken)
t.strictEqual(jwtToken, 'jwtToken')
})
test('authenticate for private upload', async function (t) {
let openedUrl = ''
const opnStub = url => {
openedUrl = url
}
const authenticate = proxyquire('../lib/authenticate', { 'opn': opnStub }) // mocking the browser opening
const jwtToken = await authenticate(`http://127.0.0.1:${server.address().port}`, {
private: true
})
const [token, askQuery] = openedUrl.split('/auth/token/')[1].split('?')
t.plan(3)
t.strictEqual(token.replace('/', ''), cliToken)
t.strictEqual(askQuery, 'private=1')
t.strictEqual(jwtToken, 'jwtToken')
})
test('authenticate using ask', async function (t) {
let openedUrl = ''
const opnStub = url => {
openedUrl = url
}
const authenticate = proxyquire('../lib/authenticate', { 'opn': opnStub }) // mocking the browser opening
const jwtToken = await authenticate(`http://127.0.0.1:${server.address().port}`, {
ask: true
})
const [token, askQuery] = openedUrl.split('/auth/token/')[1].split('?')
t.plan(3)
t.strictEqual(token.replace('/', ''), cliToken)
t.strictEqual(askQuery, 'ask=1&private=1')
t.strictEqual(jwtToken, 'jwtToken')
})
test('authenticate timeout', async function (t) {
const opnStub = url => url
const authenticate = proxyquire('../lib/authenticate', { 'opn': opnStub }) // mocking the browser opening
simulateTimeout = true
try {
await authenticate(`http://127.0.0.1:${server.address().port}`)
simulateTimeout = false
t.fail('it should reject')
} catch (err) {
t.plan(2)
t.ok(err)
t.ok(err.message.includes('Authentication timed out'))
simulateTimeout = false
}
})
test('authenticate no auth token', async function (t) {
const authenticate = proxyquire('../lib/authenticate', { 'opn': url => url }) // mocking the browser opening
simulateNoToken = true
try {
await authenticate(`http://127.0.0.1:${server.address().port}`)
simulateNoToken = false
t.fail('it should reject')
} catch (err) {
t.plan(2)
t.ok(err)
t.ok(err.message.includes('Authentication failed. No token obtained'))
simulateNoToken = false
}
})
test('authenticate failure', async function (t) {
const authenticate = proxyquire(
'../lib/authenticate',
{
'opn': url => url,
'split2': () => ({ on: () => [] })
})
try {
await authenticate(`http://127.0.0.1:${server.address().port}`)
t.fail('it should reject')
} catch (err) {
t.plan(1)
t.ok(err)
}
})
test('After all', function (t) {
t.plan(0)
server.close()
})