开发者

Basic HTTP authentication in Node.JS?

开发者 https://www.devze.com 2023-03-05 07:33 出处:网络
I\'m trying to write a REST-API server with NodeJS like the one used by Joyent, and everything is ok except I can\'t verify a normal user\'s authentication. If I jump to a terminal and do curl -u user

I'm trying to write a REST-API server with NodeJS like the one used by Joyent, and everything is ok except I can't verify a normal user's authentication. If I jump to a terminal and do curl -u username:password localhost:8000 -X GET, I can't get the va开发者_运维知识库lues username:password on the NodeJS http server. If my NodeJS http server is something like

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(1337, "127.0.0.1");

, shouldn't I get the values username:password somewhere in the req object that comes from the callback ? How can I get those values without having to use Connect's basic http auth ?


The username:password is contained in the Authorization header as a base64-encoded string.

Try this:

const http = require('http');
 
http.createServer(function (req, res) {
  var header = req.headers.authorization || '';       // get the auth header
  var token = header.split(/\s+/).pop() || '';        // and the encoded auth token
  var auth = Buffer.from(token, 'base64').toString(); // convert from base64
  var parts = auth.split(/:/);                        // split on colon
  var username = parts.shift();                       // username is first
  var password = parts.join(':');                     // everything else is the password
 
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('username is "' + username + '" and password is "' + password + '"');
}).listen(1337, '127.0.0.1');

From HTTP Authentication: Basic and Digest Access Authentication - Part 2 Basic Authentication Scheme (Pages 4-5)

Basic Authentication in Backus-Naur Form

basic-credentials = base64-user-pass
base64-user-pass  = <base64 [4] encoding of user-pass,
                    except not limited to 76 char/line>
user-pass   = userid ":" password
userid      = *<TEXT excluding ":">
password    = *TEXT


If you're using express, you can use the connect plugin (included with express):

//Load express
var express = require('express');

//User validation
var auth = express.basicAuth(function(user, pass) {     
   return (user == "super" && pass == "secret");
},'Super duper secret area');

//Password protected area
app.get('/admin', auth, routes.admin);


You can use node-http-digest for basic auth or everyauth, if adding authorization from external services are in you roadmap.


I use this code for my own starter sites with auth.

It does several things:

  • basic auth
  • return index.html for / route
  • serve content without crashing and silent handle the error
  • allow port parameter when running
  • minimal amount of logging

Before using the code, npm install express

var express = require("express");
var app = express();

//User validation
var auth = express.basicAuth(function(user, pass) {     
     return (user == "username" && pass == "password") ? true : false;
},'dev area');

/* serves main page */
app.get("/", auth, function(req, res) {
try{
    res.sendfile('index.html')
}catch(e){}
});

/* add your other paths here */

/* serves all the static files */
app.get(/^(.+)$/, auth, function(req, res){ 
try{
    console.log('static file request : ' + req.params);
    res.sendfile( __dirname + req.params[0]); 
}catch(e){}
});

var port = process.env.PORT || 8080;
app.listen(port, function() {
    console.log("Listening on " + port);
});


It can be implemented easily in pure node.js with no dependency, this is my version which is based on this answer for express.js but simplified so you can see the basic idea easily:

const http = require('http');

http.createServer(function (req, res) {
    const userpass = Buffer.from(
        (req.headers.authorization || '').split(' ')[1] || '',
        'base64'
    ).toString();
    if (userpass !== 'username:password') {
        res.writeHead(401, { 'WWW-Authenticate': 'Basic realm="nope"' });
        res.end('HTTP Error 401 Unauthorized: Access is denied');
        return;
    }
    res.end('You are in! Yay!!');
}).listen(1337, '127.0.0.1');


The restify framework (http://mcavage.github.com/node-restify/) includes an authorization header parser for "basic" and "signature" authentication schemes.


You can use http-auth module

// Authentication module.
var auth = require('http-auth');
var basic = auth.basic({
    realm: "Simon Area.",
    file: __dirname + "/../data/users.htpasswd" // gevorg:gpass, Sarah:testpass ...
});

// Creating new HTTP server.
http.createServer(basic, function(req, res) {
    res.end("Welcome to private area - " + req.user + "!");
}).listen(1337);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号