I'm trying to create an authentication with JWT, when I created my method it's a function called verifyJWT () it starts firing this error ...
NOTE: Before constructing this function and using it in the route, I can send it calmly, the problem is when I do res.status (200) .send ({auth: true, token: jwtToken}); and then res.redirect ('/ home/ v1'); But really I do not know why this problem ..
What is the correct mode of user authentication and on subsequent routes?
LOGIN ROUTER:
const { body } = require('express-validator/check');
module.exports = (app) => {
app.route('/')
.get((req, res) => { app.controllers.login.controller.redirectRouter(app, req, res) });
app.route('/login')
.get((req, res) => { app.controllers.login.controller.login(app, req, res); })
.post([
body('username').isString().isLength({ min: 1 }).not().isEmpty(),
body('password').isString().isLength({ min: 1 }).not().isEmpty()
], (req, res) => { app.controllers.login.controller.checkLoginForm(app, req, res); });
}
LOGIN CONTROLLER ROUTER
const { validationResult } = require('express-validator/check');
const jwt = require('jsonwebtoken');
module.exports.redirectRouter = (app, req, res) => res.redirect('/login');
module.exports.login = (app, req, res) => {
const renderConfig = new app.models.services.utilities.Render("LOGIN", true);
renderConfig.httpJSPResponseStatusCode = 200;
res.render('login/view', renderConfig.config);
}
module.exports.checkLoginForm = (app, req, res) => {
/** #description: RECEBE O RESULTADO DA VALIÇÃO DO FORMULÁRIO PELO {EXPRESS-VALIDATOR} */
const errors = validationResult(req);
/** #description: VERIFICA SE HOUVE ERRO NA VALIDAÇÃO DO FORMULÁRIO COM O {EXPRESS-VALIDATOR} */
if (!errors.isEmpty()) {
/** #description: CASO ALGUM DADO ESTEJA INCONSISTENTE RETORNA {ERROR: 401} DE {NÃO AUTORIZADO} */
res.status(401).send("401 Não autorizado");
} else {
/** #description: CASO OS DADOS FOREM VÁLIDOS, ADICIONA OS VALORES DO BODY NAS VARIÁVEIS */
const username = req.body.username,
password = req.body.password;
/** FUNÇÕES TEMPORÁRIAS */
if(username === "1" && password === "1"){
const userId = 10;
const jwtToken = jwt.sign({ userId }, process.env.SECRET, {
expiresIn: 300 // EXPIRA EM 5MIN
});
//res.status(200).send({ auth: true, token: jwtToken });
res.redirect('/home/v1');
} else {
res.status(401).send("401 Não autorizado");
}
}
}
HOME ROUTER
const jwtClass = require('../../models/services/JWT/controller.js');
module.exports = (app) => {
app.route('/home/v1/')
.get(jwtClass.verifyJWT, (req, res) => {
console.log("é get")
//app.controllers.home.controller.home(app, req, res);
}).post(jwtClass.verifyJWT, (req, res) => {
console.log("é post")
//app.controllers.home.controller.home(app, req, res);
});
}
** HOME CONTROLLER ROUTER **
module.exports.home = (app, req, res) => {
res.render('home/view');
}
JWT FUNCTION METHOD
const jwt = require('jsonwebtoken');
module.exports.verifyJWT = (req, res, next) => {
const jwtToken = req.headers['x-access-token'];
if (!jwtToken) {
return res.status(401).send({ auth: false, message: 'No token provided.' });
} else {
jwt.verify(jwtToken, process.env.SECRET, (error, decoded) => {
if (error) {
return res.status(500).send({ auth: false, message: 'Failed to authenticate token.' });
} else {
console.log("ae")
req.userId = decoded.id;
next();
}
});
}
}
//res.status(200).send({ auth: true, token: jwtToken });
res.redirect('/home/v1');
You can't redirect after sending Response. Refer the way Request and Response work in REST api. What you can do here is Redirect first and Have the Auth Token sent after Redirection (in the Redirection Route). You need to Write login after Redirection.
Update :
Try adding the line res.status(200).send({ auth: true, token: jwtToken });
inside HOME ROUTER
Also please import Proper Modules to HOME ROUTER.
const jwtClass = require('../../models/services/JWT/controller.js');
module.exports = (app) => {
app.route('/home/v1/')
.get(jwtClass.verifyJWT, (req, res) => {
console.log("é get")
//ADD HERE
res.status(200).send({ auth: true, token: jwtToken });
//app.controllers.home.controller.home(app, req, res);
}).post(jwtClass.verifyJWT, (req, res) => {
console.log("é post")
//ADD HERE
res.status(200).send({ auth: true, token: jwtToken });
//app.controllers.home.controller.home(app, req, res);
});
}
** HOME CONTROLLER ROUTER **
module.exports.home = (app, req, res) => {
res.render('home/view');
}
Related
So I'm trying to fetch some data from my backend and I get this error. It's wierd because until a few days ago it worked just fine.
Failed to load resource: the server responded with a status of 403 (Forbidden)
Also this is my backend code:
verifyToken.js
const jwt = require('jsonwebtoken');
const verifyToken = (req, res, next) => {
const authHeader = req.headers.token;
if (authHeader) {
const token = authHeader.split(' ')[1];
jwt.verify(token, process.env.JWT_SEC, (err, user) => {
if (err) res.status(403).json('Token is not valid!');
req.user = user;
next();
});
} else {
return res.status(401).json('You are not authenticated!');
}
};
const verifyTokenAndAuthorization = (req, res, next) => {
verifyToken(req, res, () => {
if (req.user.id === req.params.id || req.user.isAdmin) {
next();
} else {
res.status(403).json('You are not alowed to do that!');
}
});
};
const verifyTokenAndAdmin = (req, res, next) => {
verifyToken(req, res, () => {
if (req.user.isAdmin) {
next();
} else {
res.status(403).json('You are not alowed to do that!');
}
});
};
module.exports = {
verifyToken,
verifyTokenAndAuthorization,
verifyTokenAndAdmin,
};
What should I do to fix it?
How to make user redirect after authentication based on user.role ?
I'm getting the following error: UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
const jwt = require('jsonwebtoken')
const { COOKIE_NAME, SECRET } = require('../config/config')
module.exports = function() {
return (req, res, next) => {
let token = req.cookies[COOKIE_NAME]
if(token) {
jwt.verify(token, SECRET, function(err, decoded){
if (err) {
res.clearCookie(COOKIE_NAME)
} else {
if(decoded.user.role === 'admin') {
res.redirect('http://localhost:4000')
}
req.user = decoded;
}
})
}
next();
}
}
Login Fetch:
fetch(`${API}/auth/login`,{
method: 'POST',
credentials: 'include',
withCredentials: true,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
})
.then((response) => {
if(response.status === 302) {
window.location = 'http://localhost:4000'
}
else if(response.status === 200) {
onSuccess()
setTimeout(() => {
window.location = '/'
}, 1000)
} else if (response.status === 401) {
onError()
}
})
.catch((error) => {
console.log(error)
})
}
Here is my authService:
const jwt = require('jsonwebtoken')
const User = require('../models/User');
const bcrypt = require('bcrypt')
const { SALT_ROUNDS, SECRET } = require('../config/config');
const register = async ({name, username, email, password, cart}) => {
let salt = await bcrypt.genSalt(SALT_ROUNDS);
let hash = await bcrypt.hash(password, salt);
const user = new User({
name,
username,
email,
password: hash,
cart
});
return await user.save()
}
const login = async ({email, password}) => {
let user = await User.findOne({email})
if (!user) {
throw {message: 'User not found!'}
}
let isMatch = await bcrypt.compare(password, user.password)
if (!isMatch) {
throw {message: 'Password does not match!'}
}
let token = jwt.sign({user}, SECRET)
return token;
}
And my authController:
const { Router } = require('express');
const authService = require('../services/authService');
const { COOKIE_NAME } = require('../config/config');
const router = Router();
router.post('/login', async (req, res) => {
const {email, password} = req.body
try {
let token = await authService.login({email, password})
res.cookie(COOKIE_NAME, token)
res.status(200).json(token)
} catch (error) {
res.status(401).json({ error: error })
}
})
Here is my server if this will help:
app.use((req, res, next) => {
const allowedOrigins = ['http://localhost:3000', 'http://localhost:4000'];
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
res.setHeader('Access-Control-Allow-Credentials', true)
}
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
});
Since you're using jwt.verify with a callback, it is being executed asynchronously. Due to this, immediately after calling verify but before getting the decoded token, your next() function is called which passes the control to the next middleware (which probably would be synchronous) which then returns the request.
The flow of events would be something like this:
if(token) { ... starts
jwt.verify(token, ... is called asynchronously. It registers the callback function(err, decoded) { ... but doesn't execute it yet.
You exit the if(token) { ... } block and call next().
The next middleware in line starts executing and probably returns the request if it is the last middleware in chain. So the client has already been sent the response by this time.
jwt.verify(token ... succeeds and calls your registered callback.
It sees that there is no error at line if (err) ... so it moves to the else block.
It decodes the user role and tries to redirect (which internally would try to insert a header on the response). But this fails because the user was already sent the response (and hence your error message).
So the simple solution to this is to not call next() UNTIL jwt verifies and decodes your token and you know the role. In the code below, I've moved the next() function call a few lines upwards.
const jwt = require('jsonwebtoken')
const { COOKIE_NAME, SECRET } = require('../config/config')
module.exports = function() {
return (req, res, next) => {
let token = req.cookies[COOKIE_NAME]
if(token) {
jwt.verify(token, SECRET, function(err, decoded){
if (err) {
res.clearCookie(COOKIE_NAME)
} else {
if(decoded.user.role === 'admin') {
res.redirect('http://localhost:4000')
}
req.user = decoded;
}
next();
})
}
}
}
I tried to add passport-jwt to my MEVN-stack application, login is successful, but when app tries to redirect to home page after login, I get 401 Unauthorized error in console. I pass token as value of Authorization header in get request on the home page, but it did not help.
This is the code of server.js (the entrypoint of server side):
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const cors = require('cors');
const morgan = require('morgan');
const fs = require('fs');
const jwt = require('jsonwebtoken');
const passport = require('passport');
const passportJWT = require('passport-jwt');
const ExtractJWT = passportJWT.ExtractJwt;
const JWTStrategy = passportJWT.Strategy;
const jwtOptions = {};
jwtOptions.jwtFromRequest = ExtractJWT.fromAuthHeaderWithScheme('jwt');
jwtOptions.secretOrKey = 'movieratingapplicationsecretkey';
const app = express();
const router = express.Router();
const User = require('./models/User');
app.use(morgan('combined'));
app.use(bodyParser.json());
app.use(cors());
app.use(passport.initialize());
passport.use(new JWTStrategy(jwtOptions, (jwt_payload, done) => {
User.findOne({ id: jwt_payload.id }, (err, user) => {
if (err) {
return done(err, false);
}
if (user) {
return done(null, user);
} else {
return done(null, false);
}
});
}));
mongoose.connect('mongodb://localhost/movie_rating_app', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log('Connection is established');
})
.catch((err) => {
console.error(`App starting error: ${err.stack}`);
});
// include controllers
fs.readdirSync('controllers').forEach(file => {
if (file.substr(-3) === '.js') {
const route = require(`./controllers/${file}`)
route.controller(app)
}
})
router.get('/', (req, res) => {
res.json({ message: 'API was initialized!' });
});
const port = process.env.API_PORT || 8081;
app.use('/', router);
app.listen(port, () => {
console.log(`api running on port ${port}`);
});
This is the movies.js controllerm, which contains passport.authenticate() method in get request:
const Movie = require('../models/Movie')
const Rating = require('../models/Rating')
const passport = require('passport')
module.exports.controller = app => {
// fetch all movies
app.get(
'/movies',
passport.authenticate('jwt', { session: false }),
(req, res) => {
Movie.find({}, 'name description release_year genre', (error, movies) => {
if (error) console.error(error)
res.send(movies);
})
})
// fetch a single movie
app.get('/movies/:id', (req, res) => {
Movie.findById(req.params.id, 'name description release_year genre', (error, movie) => {
if (error) console.error(error)
res.send(movie);
})
})
}
This is the users.js controller:
const User = require('../models/User');
const passportJWT = require('passport-jwt');
const jwt = require('jsonwebtoken');
const ExtractJwt = passportJWT.ExtractJwt;
const jwtOptions = {};
jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('jwt');
jwtOptions.secretOrKey = 'thisisthesecretkey';
module.exports.controller = app => {
// register a user
app.post('/users/register', (req, res) => {
const newUser = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password,
})
User.createUser(newUser, (error, user) => {
if (error) {
res.status(422).json({
message: 'Something went wrong. Please try again after some time'
})
}
res.send({ user });
})
})
// login user
app.post('/users/login', (req, res) => {
if (req.body.email && req.body.password) {
const email = req.body.email,
password = req.body.password;
User.getUserByEmail(email, (err, user) => {
if (!user) {
res.status(404).json({ message: 'The user does not exist' })
} else {
User.comparePassword(password, user.password, (error, isMatch) => {
if (error) throw error;
if (isMatch) {
const payload = { id: user.id };
const token = jwt.sign(payload, jwtOptions.secretOrKey);
res.json({ message: 'ok', token })
} else {
res.status(401).json({ message: 'The password is incorrect' })
}
})
}
})
}
})
}
This is the script part of Home.vue, when I try to receive response:
<script>
import axios from 'axios';
import MovieCard from '#/components/MovieCard.vue';
export default {
name: 'Home',
components: {
MovieCard,
},
data: () => ({
movies: [],
}),
mounted() {
this.fetchMovies();
},
methods: {
async fetchMovies() {
const token = window.localStorage.getItem('auth');
return axios({
method: 'get',
url: 'http://localhost:8081/movies',
headers: {
Authorization: `JWT ${token}`,
'Content-Type': 'application/json',
},
})
.then((response) => {
console.log(response);
});
// return axios.get('http://localhost:8081/movies')
// .then(({ data }) => {
// this.movies = data;
// })
// .catch((error) => {
// console.error(error);
// });
},
},
};
</script>
Please don't mark my question as duplicate, because I have already tried some advices such as change ExtractJWT.fromAuthHeaderWithScheme('jwt') to ExtractJWT.fromAuthHeaderWithScheme('bearer'), but it did not help me.
How to fix 401 error?
I replaced all ExtractJwt.fromAuthHeaderWithScheme('jwt') with ExtractJwt.fromAuthHeaderAsBearerToken(), and set all jwtOptions.secretOrKey values as 'thisisthesecretkey'. 401 error does not exist now
I'm having trouble understanding how to send back a refresh token to get a new access token.
I've looked at this documentation: https://developer.microsoft.com/en-us/graph/docs/concepts/nodejs and I basically need help with Authenticate User- step4 but they don't seem to go into more details.
I tried using passport-oauth2-refresh but I think because I'm using Azure AD, I kept getting Error: Cannot register: not an OAuth2 strategy. So I've decided to try to manually check the expiry instead.
I am able to retrieve a refresh token (POST /token with req.user.refreshToken) along with my access token and I store it in json but I don't know how to send it back.
Here is my index.js:
const express = require('express');
const router = express.Router();
const graphHelper = require('../utils/graphHelper.js');
const passport = require('passport');
const request = require('request');
const SERVER = process.env.SERVER;
let user_id = null;
router.get('/', (req, res) => {
if (!req.isAuthenticated()) {
res.render('login');
} else {
renderBotPage(req, res);
}
});
router.get('/login',
passport.authenticate('azuread-openidconnect', {failureRedirect: '/'}),
(req, res) => {
res.redirect('/');
});
router.get('/token',
function (req, res, next) {
passport.authenticate('azuread-openidconnect',
{
response: res, // required
failureRedirect: '/'
}
)
},
function (req, res) {
const options = {
headers: {
'content-type' : 'application/json'
},
method: 'POST',
url: SERVER,
json: {
'accessToken': req.user.accessToken,
'refreshToken': req.user.refreshToken
}
};
request(options,
function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body)
}
}
);
console.log('We received a return from AzureAD get token.');
res.redirect('/');
});
router.post('/token',
function (req, res, next) {
passport.authenticate('azuread-openidconnect',
{
response: res, // required
failureRedirect: '/'
}
)(req, res, next);
},
function (req, res) {
console.log('res after first token function', res);
const options = {
headers: {
'content-type' : 'application/json'
},
method: 'POST',
url: SERVER,
json: {
'accessToken': req.user.accessToken,
'refreshToken': req.user.refreshToken
}
};
request(options,
function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body)
}
}
);
res.redirect('/');
});
function renderBotPage(req, res) {
graphHelper.getUserData(req.user.accessToken, (err, user) => {
if (!err) {
res.render('chatbotOn', {
display_name: user.body.displayName,
user_id:user.body.id
});
} else {
// Catch of Expired token error
if (hasAccessTokenExpired(err)) {
req.session.destroy(() => {
req.logOut();
res.clearCookie('graphNodeCookie');
res.status(200);
res.redirect('/');
});
}
renderError(err, res);
res.render('chatbotOn', {
display_name: "Random User"
});
}
});
}
router.get('/disconnect', (req, res) => {
req.session.destroy(() => {
req.logOut();
res.clearCookie('graphNodeCookie');
res.status(200);
res.redirect('/');
});
});
function hasAccessTokenExpired(e) {
let expired;
if (!e.innerError) {
expired = false;
} else {
expired = e.forbidden &&
e.message === 'InvalidAuthenticationToken' &&
e.response.error.message === "Le token d'accès a expiré.";
}
return expired;
}
function renderError(e, res) {
e.innerError = (e.response) ? e.response.text : '';
res.render('error', {
error: e
});
}
module.exports = router;
My app.js
const callback = (iss, sub, profile, accessToken, refreshToken, done) => {
done(null, {
profile,
accessToken,
refreshToken
});
};
passport.use(new OIDCStrategy(config.creds, callback));
And here is my graphHelper.js:
const request = require('superagent');
function getUserData(accessToken, callback) {
request
.get('https://graph.microsoft.com/beta/me')
.set('Authorization', 'Bearer ' + accessToken)
.end((err, res) => {
callback(err, res);
});
}
exports.getUserData = getUserData;
here is my config.js:
module.exports = {
creds: {
redirectUrl: 'http://localhost:3000/token',
clientID: 'xxxxx', // regular
clientSecret: 'xxxxx', // regular
identityMetadata:
'xxxxxx',
allowHttpForRedirectUrl: true, // For development only
responseType: 'code id_token',
validateIssuer: false, // For development only
responseMode: 'form_post',
scope: ['openid', 'offline_access', 'Contacts.Read',
'Calendars.ReadWrite'
]
},
};
I try to add some token in my API , I don't have any error in my console but when I try to use postman whit my route with a post ( email and password )
"http://localhost:3005/api/utilisateur/login"
// '/v1/account/login'
api.post('/login', passport.authenticate(
'local', {
session: false,
scope: []
}), generateAccessToken, respond);
Postman returns to me : Unauthorized
My full authMiddleware:
import jwt from 'jsonwebtoken';
import expressJwt from 'express-jwt';
const TOKENTIME = 60 * 60 * 24 * 30 // 30 days
const SECRET = "f9ilOusçSE El;l3 m4ng3 d3:s pimOu55e!";
let authenticate = expressJwt({secret: SECRET});
let generateAccessToken = (req, res, next) => {
req.token = req.token || {};
req.token = jwt.sign({
id: req.user.id,
}, SECRET, {
expiresIn: TOKENTIME // 30 days
});
next();
}
let respond = (req, res) => {
res.status(200).json({
user: req.user.username,
token: req.token
});
}
module.exports = {
authenticate,
generateAccessToken,
respond
};
And :
import mongoose from 'mongoose';
import {
Router
} from 'express';
import Utilisateur from '../model/utilisateur';
import bodyParser from 'body-parser';
import passport from 'passport';
import config from '../config';
import {
generateAccessToken,
respond,
authenticate
} from '../middleware/authMiddleware';
export default ({
config,
db
}) => {
let api = Router();
// CRUD - CREAT READ UPDATE DELETE
//'/api/match/add' // First Step Creat
api.post('/add', (req, res) => {
let newUti = new Utilisateur();
newUti.name = req.body.name;
newUti.email = req.body.email;
newUti.password = req.body.password;
newUti.nom = req.body.nom;
newUti.prenom = req.body.prenom;
newUti.pays = req.body.pays;
newUti.codePostale = req.body.codePostale;
newUti.adresse = req.body.adresse;
newUti.telephone = req.body.telephone;
newUti.sexe = req.body.sexe;
newUti.admin = req.body.admin;
newUti.dateCreationCompte = req.body.dateCreationCompte;
newUti.dateDebutPeriodeEssai = req.body.dateDebutPeriodeEssai;
newUti.dateFinPeriodeEssai = req.body.dateFinPeriodeEssai;
newUti.dateDernierConnexion = req.body.dateDernierConnexion;
newUti.dateDernierModificationMotDePasse =
req.body.dateDernierModificationMotDePasse;
newUti.nombreDeConnexion = req.body.nombreDeConnexion;
newUti.adresseIpCreation = req.body.adresseIpCreation;
newUti.dernierAdresseIpConnecte = req.body.dernierAdresseIpConnecte;
newUti.emailVerifier = req.body.emailVerifier;
newUti.save(err => {
if (err) {
res.send(err);
}
passport.authenticate(
'local', {
sesssion: false
})(req, res, () => {
res.json({
message: "Utilisateur enregistré"
});
});
});
});
// '/api/account/login'
api.post('/login', passport.authenticate(
'local', {
session: false,
scope: []
}), generateAccessToken, respond);
// /api/utilisateur/logout
api.get('/logout', authenticate, (req, res) => {
res.logout();
res.status(200).send('Succefully logged out ');
});
api.get('/me', authenticate, (req, res) => {
res.status(200).json(req.user);
});
// Second Step READ
//'/api/utilisateur' - Read
api.get('/', (req, res) => {
Utilisateur.find({}, (err, utilisateur) => {
if (err) {
res.send(err);
}
res.json(utilisateur);
});
});
// /api/utilisateur/:id' - Read 1
api.get('/id/:id', (req, res) => {
Utilisateur.findById(req.params.id, (err, utilisateur) => {
if (err) {
res.send(err);
}
res.json(utilisateur);
});
});
// update ' /api/utilisateur/:id'
api.put('/:id', (req, res) => {
Utilisateur.findById(req.params.id, (err, utilisateur) => {
if (err) {
res.send(err);
}
utilisateur.name = req.body.name;
utilisateur.email = req.body.email;
utilisateur.password = req.body.password;
utilisateur.nom = req.body.nom;
utilisateur.prenom = req.body.prenom;
utilisateur.pays = req.body.pays;
utilisateur.codePostale = req.body.codePostale;
utilisateur.adresse = req.body.adresse;
utilisateur.telephone = req.body.telephone;
utilisateur.sexe = req.body.sexe;
utilisateur.admin = req.body.admin;
utilisateur.dateCreationCompte = req.body.dateCreationCompte;
utilisateur.dateDebutPeriodeEssai = req.body.dateDebutPeriodeEssai;
utilisateur.dateFinPeriodeEssai = req.body.dateFinPeriodeEssai;
utilisateur.dateDernierConnexion = req.body.dateDernierConnexion;
utilisateur.dateDernierModificationMotDePasse =
req.body.dateDernierModificationMotDePasse;
utilisateur.nombreDeConnexion = req.body.nombreDeConnexion;
utilisateur.adresseIpCreation = req.body.adresseIpCreation;
utilisateur.dernierAdresseIpConnecte =
req.body.dernierAdresseIpConnecte;
utilisateur.emailVerifier = req.body.emailVerifier;
utilisateur.save(err => {
if (err) {
res.send(err);
}
res.json({
message: "Info utilisateur mise a jour "
});
});
});
});
// 'v1/utilisateur/:id - Supprimer
api.delete('/:id', (req, res) => {
Utilisateur.remove({
_id: req.params.id
}, (err, utilisateur) => {
if (err) {
res.send(err);
}
res.json({
message: "Utilisateur supprimé"
});
});
});
api.get('/pseudo/:name', (req, res) => {
Utilisateur.find({
name: req.params.name
}, (err, utilisateur) => {
if (err) {
res.send(err);
}
res.json(utilisateur);
});
});
return api;
};
Its my first API , i follow a tutorial , i hope someone can help me , you can see the full project at : https://github.com/soosoo34/ParisSportifAPI