feat: facebook login (#820)

* Facebook strategy

* Update user_auth_system.md

* Update user_auth_system.md
This commit is contained in:
Marco Beretta 2023-08-25 02:10:48 +02:00 committed by GitHub
parent a569020312
commit 007d51ede1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 155 additions and 27 deletions

View file

@ -63,6 +63,11 @@ const userSchema = mongoose.Schema(
unique: true,
sparse: true,
},
facebookId: {
type: String,
unique: true,
sparse: true,
},
openidId: {
type: String,
unique: true,

View file

@ -8,6 +8,8 @@ afterEach(() => {
delete process.env.APP_TITLE;
delete process.env.GOOGLE_CLIENT_ID;
delete process.env.GOOGLE_CLIENT_SECRET;
delete process.env.FACEBOOK_CLIENT_ID;
delete process.env.FACEBOOK_CLIENT_SECRET;
delete process.env.OPENID_CLIENT_ID;
delete process.env.OPENID_CLIENT_SECRET;
delete process.env.OPENID_ISSUER;
@ -31,6 +33,8 @@ describe.skip('GET /', () => {
process.env.APP_TITLE = 'Test Title';
process.env.GOOGLE_CLIENT_ID = 'Test Google Client Id';
process.env.GOOGLE_CLIENT_SECRET = 'Test Google Client Secret';
process.env.FACEBOOK_CLIENT_ID = 'Test Facebook Client Id';
process.env.FACEBOOK_CLIENT_SECRET = 'Test Facebook Client Secret';
process.env.OPENID_CLIENT_ID = 'Test OpenID Id';
process.env.OPENID_CLIENT_SECRET = 'Test OpenID Secret';
process.env.OPENID_ISSUER = 'Test OpenID Issuer';
@ -51,6 +55,7 @@ describe.skip('GET /', () => {
expect(response.body).toEqual({
appTitle: 'Test Title',
googleLoginEnabled: true,
facebookLoginEnabled: true,
openidLoginEnabled: true,
openidLabel: 'Test OpenID',
openidImageUrl: 'http://test-server.com',

View file

@ -5,6 +5,8 @@ router.get('/', async function (req, res) {
try {
const appTitle = process.env.APP_TITLE || 'LibreChat';
const googleLoginEnabled = !!process.env.GOOGLE_CLIENT_ID && !!process.env.GOOGLE_CLIENT_SECRET;
const facebookLoginEnabled =
!!process.env.FACEBOOK_CLIENT_ID && !!process.env.FACEBOOK_CLIENT_SECRET;
const openidLoginEnabled =
!!process.env.OPENID_CLIENT_ID &&
!!process.env.OPENID_CLIENT_SECRET &&
@ -27,6 +29,7 @@ router.get('/', async function (req, res) {
return res.status(200).send({
appTitle,
googleLoginEnabled,
facebookLoginEnabled,
openidLoginEnabled,
openidLabel,
openidImageUrl,

View file

@ -38,7 +38,8 @@ router.get(
router.get(
'/facebook',
passport.authenticate('facebook', {
scope: ['public_profile', 'email'],
scope: ['public_profile'],
profileFields: ['id', 'email', 'name'],
session: false,
}),
);
@ -49,7 +50,8 @@ router.get(
failureRedirect: `${domains.client}/login`,
failureMessage: true,
session: false,
scope: ['public_profile', 'email'],
scope: ['public_profile'],
profileFields: ['id', 'email', 'name'],
}),
(req, res) => {
const token = req.user.generateToken();

View file

@ -5,8 +5,7 @@ const domains = config.domains;
const facebookLogin = async (accessToken, refreshToken, profile, cb) => {
try {
console.log('facebookLogin => profile', profile);
const email = profile.emails[0].value;
const email = profile.emails[0]?.value;
const facebookId = profile.id;
const oldUser = await User.findOne({
email,
@ -15,17 +14,17 @@ const facebookLogin = async (accessToken, refreshToken, profile, cb) => {
process.env.ALLOW_SOCIAL_REGISTRATION?.toLowerCase() === 'true';
if (oldUser) {
oldUser.avatar = profile.photos[0].value;
oldUser.avatar = profile.photo;
await oldUser.save();
return cb(null, oldUser);
} else if (ALLOW_SOCIAL_REGISTRATION) {
const newUser = await new User({
provider: 'facebook',
facebookId,
username: profile.name.givenName + profile.name.familyName,
username: profile.displayName,
email,
name: profile.displayName,
avatar: profile.photos[0].value,
name: profile.name?.givenName + ' ' + profile.name?.familyName,
avatar: profile.photos[0]?.value,
}).save();
return cb(null, newUser);
@ -43,23 +42,12 @@ const facebookLogin = async (accessToken, refreshToken, profile, cb) => {
module.exports = () =>
new FacebookStrategy(
{
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FACEBOOK_SECRET,
clientID: process.env.FACEBOOK_CLIENT_ID,
clientSecret: process.env.FACEBOOK_CLIENT_SECRET,
callbackURL: `${domains.server}${process.env.FACEBOOK_CALLBACK_URL}`,
proxy: true,
// profileFields: [
// 'id',
// 'email',
// 'gender',
// 'profileUrl',
// 'displayName',
// 'locale',
// 'name',
// 'timezone',
// 'updated_time',
// 'verified',
// 'picture.type(large)'
// ]
scope: ['public_profile'],
profileFields: ['id', 'email', 'name'],
},
facebookLogin,
);