Hello,
For me it's not clear how to provide basic authorization. Can someone to show me a step-by-step solution, please?
(I've read similar question here, but I didn't get it).
What I want to do:
P.S. Thank you for this great and simple REST server!
Send username and password to server in Body
I am assuming that you mean sending the user and pass encoded (base64) as authentication header, sorry, I am not fimiliar with Retrofit
Receive a user object in response
I am also assuming that you pass back the user only, not both user and pass
Another assumption is you use this for mocking/non-production usage, otherwise, you need to secure it more by validating the user before passing it back in the response
In order to achieve the logic you described you may run json-server as a module not from the command line (example provided)
router.render"I've attached this simple quick repo for you, feel free to clone and use it.
server.js
var jsonServer = require('json-server')
var server = jsonServer.create()
var router = jsonServer.router('db.json')
var middlewares = jsonServer.defaults()
function simpleAuth(req, res, next) {
if (req.headers.authorization) {
// user and password are stored in the authorization header
// do whatever you want with them
var user_and_password = new Buffer(req.headers.authorization.split(" ")[1], 'base64').toString();
// for example, get the username
var user_only = user_and_password.split(':')[0];
/*
* I am not sure if you want to only send the user as a simple confirmation
* or you want to apply your own logic, like, really authenticate/validate
* the user against users database, static users .. etc
*
* in production, it is recommended to validate the user by somehow.
*/
// and save it in the request for later use in the `router.render` method
req.user = user_only;
// continue doing json-server magic
next();
} else {
// it is not recommended in REST APIs to throw errors,
// instead, we send 401 response with whatever erros
// we want to expose to the client
res.status(401).send({error: 'unauthorized'})
}
}
// this method overwrites the original json-server's way of response
// with your custom logic, here we will add the user to the response
router.render = function (req, res) {
// manually wrap any response send by json-server into an object
// this is something like `res.send()`, but it is cleaner and meaningful
// as we're sending json object not normal text/response
res.json({
user: req.user, // the user we stored previously in `simpleAuth` function
body: res.locals.data // the original server-json response is stored in `req.locals.data`
})
}
// start setting up json-server middlewares
server.use(middlewares)
// before proceeding with any request, run `simpleAuth` function
// which should check for basic authentication header .. etc
server.use(simpleAuth);
// continue doing json-server magic
server.use(router);
// start listening to port 3000
server.listen(3000, function () {
console.log('JSON Server is running on port 3000');
})
db.json
{
"posts": [
{
"id":1,
"title": "first post title",
"name": "ahmed ayoub"
}
]
}
git clone https://github.com/Nilegfx/json-server-answer-417.git
cd json-server-answer-417
npm install
node server
index.js and db.json in the same directory node server
from your command line, run
curl -u yourusername:yourpassword http://localhost:3000/posts
responses with status 200:
{
"user": "yourusername",
"body": [
{
"id": 1,
"title": "first post title",
"name": "ahmed ayoub"
}
]
}
from your command line, run
curl http://localhost:3000/posts
**responses with status 401:
{
"error": "unauthorized"
}
Hope it helps.
@Nilegfx very thank you! I need only one hint more.
In want to get a user object that has the same username as in authentecation header.
My db.json is like:
"users": [
{
"id": 1,
"username": "yourusername",
"password": "yourpassword",
"firstname": "yourfirstname",
"lastname": "yourlastname",
// other fields
},
{
"id": 2,
"username": "user",
"password": "user"
"firstname": "userfirstname",
"lastname": "userlastname",
// other fields
}
So, if i request
curl -u yourusername:yourpassword http://localhost:3000/users
expected answer is:
{
"id": 1,
"username": "yourusername",
// other fields, but w/o password field.
}
How can i achive that kind of "selection"?
Thank you.
Most helpful comment
Assumptions
I am assuming that you mean sending the user and pass encoded (base64) as authentication header, sorry, I am not fimiliar with Retrofit
I am also assuming that you pass back the user only, not both user and pass
Another assumption is you use this for mocking/non-production usage, otherwise, you need to secure it more by validating the user before passing it back in the response
Explanation
In order to achieve the logic you described you may run json-server as a module not from the command line (example provided)
Pseudo Steps
router.render"I've attached this simple quick repo for you, feel free to clone and use it.
let's get our hands dirty
server.js
db.json
running the exampl (clone the provided repo)
running the app (manually)
index.jsanddb.jsonin the same directorymake a request with basic authentication
from your command line, run
responses with status 200:
a request without basic authentication
from your command line, run
**responses with status 401:
Hope it helps.