Skip to content

Commit

Permalink
Accept both api key and JWT from API
Browse files Browse the repository at this point in the history
  • Loading branch information
lekkas committed May 16, 2017
1 parent 1b6202f commit 2f6e406
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 2 deletions.
1 change: 1 addition & 0 deletions automation/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ test_id=$(docker run \
-e VPN_API_PORT=80 \
-e VPN_CONNECT_PROXY_PORT=3128 \
-e BLUEBIRD_DEBUG=1 \
-e JSON_WEB_TOKEN_SECRET=jwtsecret \
-e API_SERVICE_API_KEY=test_api_service_key \
-v $DIR/env-backend.conf:/etc/systemd/system/confd.service.d/env-backend.conf \
$IMAGE_NAME)
Expand Down
1 change: 1 addition & 0 deletions config/confd/conf.d/env.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ keys = [
"/resin/api/api-key",
"/resin/vpn/api-key",
"/resin/proxy/api-key",
"/resin/api/jwt/secret",
]
2 changes: 2 additions & 0 deletions config/confd/templates/env.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ VPN_RESET_DELAY_MS=60000
VPN_HOST=127.0.0.1
CURL_EXTRA_FLAGS="--retry 5 --retry-delay 2 --retry-max-time 30"

JSON_WEB_TOKEN_SECRET={{getv "/resin/api/jwt/secret"}}

API_SERVICE_API_KEY={{getv "/resin/api/api-key"}}
PROXY_SERVICE_API_KEY={{getv "/resin/proxy/api-key"}}

Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
"event-stream": "^3.1.7",
"express": "^4.10.6",
"generic-pool": "^3.1.6",
"jsonwebtoken": "^7.4.0",
"lodash": "^4.0.0",
"middleware-handler": "~0.2.0",
"morgan": "^1.5.1",
"node-tunnel": "0.2.2",
"passport": "~0.2.2",
"passport-http-bearer": "^1.0.1",
"passport-jwt": "^2.2.1",
"pinejs-client": "^2.1.1",
"request": "^2.51.0",
"tmp": "~0.0.25",
Expand Down
16 changes: 15 additions & 1 deletion src/api.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ request = Promise.promisify(require('request'), multiArgs: true)
_ = require 'lodash'
passport = require 'passport'
BearerStrategy = require 'passport-http-bearer'
JWTStrategy = require('passport-jwt').Strategy
ExtractJwt = require('passport-jwt').ExtractJwt

passport.use new JWTStrategy
secretOrKey: process.env.JSON_WEB_TOKEN_SECRET
jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('Bearer')
(jwtPayload, done) ->
if not jwtPayload?
return done(null, false)

# jwt should have a service property with value 'api'
if jwtPayload.service is 'api'
return done(null, true)
done(null, false)

passport.use new BearerStrategy (token, done) ->
if token is process.env.API_SERVICE_API_KEY
Expand All @@ -27,7 +41,7 @@ module.exports = (vpn) ->
api.use(passport.initialize())
api.use(bodyParser.json())

api.get '/api/v1/clients/', passport.authenticate('bearer', session: false), (req, res) ->
api.get '/api/v1/clients/', passport.authenticate(['jwt', 'bearer'], session: false), (req, res) ->
vpn.getStatus()
.then (results) ->
res.send(_.values(results.client_list))
Expand Down
13 changes: 12 additions & 1 deletion test/app.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ http = require 'http'
requestAsync = Promise.promisify(require('request'), multiArgs: true)
path = require 'path'
vpnClient = require 'openvpn-client'
jsonwebtoken = require 'jsonwebtoken'

createJwt = (payload, secret = process.env.JSON_WEB_TOKEN_SECRET) ->
jsonwebtoken.sign(payload, secret)

vpnHost = process.env.VPN_HOST ? '127.0.0.1'
vpnPort = process.env.VPN_PORT ? '443'
Expand Down Expand Up @@ -61,12 +65,19 @@ describe '/api/v1/clients/', ->
.expect(401, done)

describe 'When no clients are connected', ->
it 'should return empty client list', (done) ->
it 'should return empty client list with api key-based API service authentication', (done) ->
supertest('http://localhost')
.get('/api/v1/clients/')
.set('Authorization', "Bearer #{process.env.API_SERVICE_API_KEY}")
.expect(200, '[]', done)

describe 'When no clients are connected', ->
it 'should return empty client list with JWT-based API service authentication', (done) ->
supertest('http://localhost')
.get('/api/v1/clients/')
.set('Authorization', 'Bearer ' + createJwt({ service: 'api' }))
.expect(200, '[]', done)

describe 'When a client connects and disconnects', ->
it 'should send the correct data', (done) ->
Promise.using vpnClient.connect({ user: 'user1', pass: 'pass' }), ->
Expand Down

0 comments on commit 2f6e406

Please sign in to comment.