I was working on the Implementation of Social Authentication challenge in the Advanced Node and Express
section locally using vscode. After following the instructions on the challenge and doing everything I was instructed to do, the first test: Route '/auth/github' should be correct.
was not passing. I then copied the solution for the route.js in the check out the project up to this point page but it was still not passing. My local host was showing Error: Unknown authentication strategy "github"
. After googling for a while I found a solution here: https://stackoverflow.com/questions/53152247/unknown-authentication-strategy-github which worked and made the test pass. The solution was to:
1.
const GitHubStrategy = require(‘passport-github’).Strategy;
(declare GithubStrategy which was not required in the challenge)
2.
passport.use(new GitHubStrategy({
clientID: GITHUB_CLIENT_ID,
clientSecret: GITHUB_CLIENT_SECRET,
callbackURL: // your callback url
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({ githubId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
None of the above was required in the challenge, the instruction was only to :
This was my code when the test was failing
const passport = require('passport');
const bcrypt = require('bcrypt');
module.exports = function (app, myDataBase) {
app.route('/').get((req, res) => {
res.render('index', {
title: 'Connected to Database',
message: 'Please log in',
showLogin: true,
showRegistration: true,
showSocialAuth: true
});
});
app.route('/login').post(passport.authenticate('local', { failureRedirect: '/' }), (req, res) => {
res.redirect('/profile');
});
app.route('/profile').get(ensureAuthenticated, (req,res) => {
res.render('profile', { username: req.user.username });
});
app.route('/logout').get((req, res) => {
req.logout();
res.redirect('/');
});
app.route('/register').post((req, res, next) => {
const hash = bcrypt.hashSync(req.body.password, 12);
myDataBase.findOne({ username: req.body.username }, (err, user) => {
if (err) {
next(err);
} else if (user) {
res.redirect('/');
} else {
myDataBase.insertOne({
username: req.body.username,
password: hash
},
(err, doc) => {
if (err) {
res.redirect('/');
} else {
// The inserted document is held within
// the ops property of the doc
next(null, doc.ops[0]);
}
}
)
}
})
},
passport.authenticate('local', { failureRedirect: '/' }),
(req, res, next) => {
res.redirect('/profile');
}
);
app.route('/auth/github').get(passport.authenticate('github'));
app.route('/auth/github/callback').get(passport.authenticate('github', { failureRedirect: '/' }), (req, res) => {
res.redirect('/profile');
})
app.use((req, res, next) => {
res.status(404)
.type('text')
.send('Not Found');
});
}
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/');
};
(basically the solution on the solution page)
and this is my code that is passing:
const passport = require("passport");
const bcrypt = require("bcrypt");
const GitHubStrategy = require("passport-github").Strategy;
passport.use(
new GitHubStrategy(
{
clientID: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/github/callback",
},
function (accessToken, refreshToken, profile, cb) {
User.findOrCreate({ githubId: profile.id }, function (err, user) {
return cb(err, user);
});
}
)
);
module.exports = function (app, myDataBase) {
app.route("/").get((req, res) => {
res.render("index", {
title: "Connected to Database",
message: "Please log in",
showLogin: true,
showRegistration: true,
showSocialAuth: true,
});
});
app
.route("/login")
.post(
passport.authenticate("local", { failureRedirect: "/" }),
(req, res) => {
res.redirect("/profile");
}
);
app.route("/profile").get(ensureAuthenticated, (req, res) => {
res.render("profile", { username: req.user.username });
});
app.route("/logout").get((req, res) => {
req.logout();
res.redirect("/");
});
app.route("/register").post(
(req, res, next) => {
const hash = bcrypt.hashSync(req.body.password, 12);
myDataBase.findOne({ username: req.body.username }, (err, user) => {
if (err) {
next(err);
} else if (user) {
res.redirect("/");
} else {
myDataBase.insertOne(
{
username: req.body.username,
password: hash,
},
(err, doc) => {
if (err) {
res.redirect("/");
} else {
// The inserted document is held within
// the ops property of the doc
next(null, doc.ops[0]);
}
}
);
}
});
},
passport.authenticate("local", { failureRedirect: "/" }),
(req, res, next) => {
res.redirect("/profile");
}
);
// github OAuth
app.route("/auth/github").get(passport.authenticate("github"));
app
.route("/auth/github/callback")
.get(
passport.authenticate("github", { failureRedirect: "/" }),
(req, res) => {
res.redirect("/profile");
}
);
// end of github OAuth
app.use((req, res, next) => {
res.status(404).type("text").send("Not Found");
});
};
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect("/");
}
Following the instructions on the page did not work for me. This could just be in my case but I decided to share my observation and solution.