MAJOR: Updates for Authenticated Web UI and CLI #30
| @ -685,6 +685,7 @@ function parseConfig(err, text) { | |||||||
|       , protected: { |       , protected: { | ||||||
|           // alg will be filled out automatically
 |           // alg will be filled out automatically
 | ||||||
|           jwk: state.pub |           jwk: state.pub | ||||||
|  |         , kid: false | ||||||
|         , nonce: nonce |         , nonce: nonce | ||||||
|         , url: newAccountUrl |         , url: newAccountUrl | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -590,9 +590,14 @@ function jwtEggspress(req, res, next) { | |||||||
| 
 | 
 | ||||||
|   // TODO verify if possible
 |   // TODO verify if possible
 | ||||||
|   console.warn("[warn] JWT is not verified yet"); |   console.warn("[warn] JWT is not verified yet"); | ||||||
|  |   // A failed JWS should cause a failed JWT
 | ||||||
|  |   if (false !== req.trusted) { | ||||||
|  |     req.trusted = true; | ||||||
|  |   } | ||||||
|   next(); |   next(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // TODO switch to Keypairs.js / Keyfetch.js
 | ||||||
| function verifyJws(jwk, jws) { | function verifyJws(jwk, jws) { | ||||||
|   return keypairs.export({ jwk: jwk }).then(function (pem) { |   return keypairs.export({ jwk: jwk }).then(function (pem) { | ||||||
|     var alg = 'SHA' + jws.header.alg.replace(/[^\d]+/i, ''); |     var alg = 'SHA' + jws.header.alg.replace(/[^\d]+/i, ''); | ||||||
| @ -632,9 +637,8 @@ function jwsEggspress(req, res, next) { | |||||||
|   } |   } | ||||||
|   if (req.jws.header.jwk) { |   if (req.jws.header.jwk) { | ||||||
|     if (kid) { |     if (kid) { | ||||||
|       // TODO kid and jwk are mutually exclusive
 |       res.send({ error: { message: "jws protected header must not include both 'kid' and 'jwk'" } }); | ||||||
|       //res.send({ error: { message: "jws protected header must not include both 'kid' and 'jwk'" } });
 |       return; | ||||||
|       //return;
 |  | ||||||
|     } |     } | ||||||
|     kid = req.jws.header.jwk.kid; |     kid = req.jws.header.jwk.kid; | ||||||
|     p = Keypairs.thumbprint({ jwk: req.jws.header.jwk }).then(function (thumb) { |     p = Keypairs.thumbprint({ jwk: req.jws.header.jwk }).then(function (thumb) { | ||||||
| @ -699,6 +703,10 @@ function jwsEggspress(req, res, next) { | |||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|   }).then(function () { |   }).then(function () { | ||||||
|  |     // a failed JWT should cause a failed JWS
 | ||||||
|  |     if (false !== req.trusted) { | ||||||
|  |       req.trusted = req.jws.trusted; | ||||||
|  |     } | ||||||
|     next(); |     next(); | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
| @ -1038,10 +1046,19 @@ function handleApi() { | |||||||
|   app.head('/acme/new-nonce', controllers.newNonce); |   app.head('/acme/new-nonce', controllers.newNonce); | ||||||
|   app.get('/acme/new-nonce', controllers.newNonce); |   app.get('/acme/new-nonce', controllers.newNonce); | ||||||
|   app.post('/acme/new-acct', controllers.newAccount); |   app.post('/acme/new-acct', controllers.newAccount); | ||||||
|   app.use(/\b(relay)\b/, controllers.relay); |   function mustTrust(req, res, next) { | ||||||
|   app.get(/\b(config)\b/, getConfigOnly); |     // TODO public routes should be explicitly marked
 | ||||||
|   app.use(/\b(init|config)\b/, initOrConfig); |     // trusted should be the default
 | ||||||
|   app.use(/\b(restart)\b/, restart); |     if (req.trusted) { next(); } | ||||||
|  |     res.statusCode = 400; | ||||||
|  |     res.send({"error":{"message": "this type of requests must be encoded as a jws payload" | ||||||
|  |       + " and signed by a trusted account holder"}}); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   app.use(/\b(relay)\b/, mustTrust, controllers.relay); | ||||||
|  |   app.get(/\b(config)\b/, mustTrust, getConfigOnly); | ||||||
|  |   app.use(/\b(init|config)\b/, mustTrust, initOrConfig); | ||||||
|  |   app.use(/\b(restart)\b/, mustTrust, restart); | ||||||
| 
 | 
 | ||||||
|   // Position is important with eggspress
 |   // Position is important with eggspress
 | ||||||
|   // This should stay here, right before the other methods
 |   // This should stay here, right before the other methods
 | ||||||
| @ -1050,14 +1067,14 @@ function handleApi() { | |||||||
|   //
 |   //
 | ||||||
|   // With proper config
 |   // With proper config
 | ||||||
|   //
 |   //
 | ||||||
|   app.use(/\b(http)\b/, controllers.http); |   app.use(/\b(http)\b/, mustTrust, controllers.http); | ||||||
|   app.use(/\b(tcp)\b/, controllers.tcp); |   app.use(/\b(tcp)\b/, mustTrust, controllers.tcp); | ||||||
|   app.use(/\b(save|commit)\b/, saveAndCommit); |   app.use(/\b(save|commit)\b/, mustTrust, saveAndCommit); | ||||||
|   app.use(/\b(ssh)\b/, controllers.ssh); |   app.use(/\b(ssh)\b/, mustTrust, controllers.ssh); | ||||||
|   app.use(/\b(enable)\b/, enable); |   app.use(/\b(enable)\b/, mustTrust, enable); | ||||||
|   app.use(/\b(disable)\b/, disable); |   app.use(/\b(disable)\b/, mustTrust, disable); | ||||||
|   app.use(/\b(status)\b/, getStatus); |   app.use(/\b(status)\b/, mustTrust, getStatus); | ||||||
|   app.use(/\b(list)\b/, listSuccess); |   app.use(/\b(list)\b/, mustTrust, listSuccess); | ||||||
|   app.use('/', function (req, res) { |   app.use('/', function (req, res) { | ||||||
|     res.send({"error":{"message":"unrecognized rpc"}}); |     res.send({"error":{"message":"unrecognized rpc"}}); | ||||||
|   }); |   }); | ||||||
|  | |||||||
| @ -160,6 +160,7 @@ module.exports.create = function (state) { | |||||||
|     , protected: { |     , protected: { | ||||||
|         // alg will be filled out automatically
 |         // alg will be filled out automatically
 | ||||||
|         jwk: state.pub |         jwk: state.pub | ||||||
|  |       , kid: false | ||||||
|       , nonce: require('crypto').randomBytes(16).toString('hex') // TODO get from server
 |       , nonce: require('crypto').randomBytes(16).toString('hex') // TODO get from server
 | ||||||
|         // TODO make localhost exceptional
 |         // TODO make localhost exceptional
 | ||||||
|       , url: RC.resolve(reqOpts.path) |       , url: RC.resolve(reqOpts.path) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user