Spaces:
Runtime error
Runtime error
const passport = require('passport'); | |
const { Issuer, Strategy: OpenIDStrategy } = require('openid-client'); | |
const axios = require('axios'); | |
const fs = require('fs'); | |
const path = require('path'); | |
const config = require('../../config/loader'); | |
const domains = config.domains; | |
const User = require('../models/User'); | |
let crypto; | |
try { | |
crypto = require('node:crypto'); | |
} catch (err) { | |
console.error('crypto support is disabled!'); | |
} | |
const downloadImage = async (url, imagePath, accessToken) => { | |
try { | |
const response = await axios.get(url, { | |
headers: { | |
Authorization: `Bearer ${accessToken}`, | |
}, | |
responseType: 'arraybuffer', | |
}); | |
fs.mkdirSync(path.dirname(imagePath), { recursive: true }); | |
fs.writeFileSync(imagePath, response.data); | |
const fileName = path.basename(imagePath); | |
return `/images/openid/${fileName}`; | |
} catch (error) { | |
console.error(`Error downloading image at URL "${url}": ${error}`); | |
return ''; | |
} | |
}; | |
async function setupOpenId() { | |
try { | |
const issuer = await Issuer.discover(process.env.OPENID_ISSUER); | |
const client = new issuer.Client({ | |
client_id: process.env.OPENID_CLIENT_ID, | |
client_secret: process.env.OPENID_CLIENT_SECRET, | |
redirect_uris: [domains.server + process.env.OPENID_CALLBACK_URL], | |
}); | |
const openidLogin = new OpenIDStrategy( | |
{ | |
client, | |
params: { | |
scope: process.env.OPENID_SCOPE, | |
}, | |
}, | |
async (tokenset, userinfo, done) => { | |
try { | |
let user = await User.findOne({ openidId: userinfo.sub }); | |
if (!user) { | |
user = await User.findOne({ email: userinfo.email }); | |
} | |
let fullName = ''; | |
if (userinfo.given_name && userinfo.family_name) { | |
fullName = userinfo.given_name + ' ' + userinfo.family_name; | |
} else if (userinfo.given_name) { | |
fullName = userinfo.given_name; | |
} else if (userinfo.family_name) { | |
fullName = userinfo.family_name; | |
} else { | |
fullName = userinfo.username || userinfo.email; | |
} | |
if (!user) { | |
user = new User({ | |
provider: 'openid', | |
openidId: userinfo.sub, | |
username: userinfo.username || userinfo.given_name || '', | |
email: userinfo.email || '', | |
emailVerified: userinfo.email_verified || false, | |
name: fullName, | |
}); | |
} else { | |
user.provider = 'openid'; | |
user.openidId = userinfo.sub; | |
user.username = userinfo.given_name || ''; | |
user.name = fullName; | |
} | |
if (userinfo.picture) { | |
const imageUrl = userinfo.picture; | |
let fileName; | |
if (crypto) { | |
const hash = crypto.createHash('sha256'); | |
hash.update(userinfo.sub); | |
fileName = hash.digest('hex') + '.png'; | |
} else { | |
fileName = userinfo.sub + '.png'; | |
} | |
const imagePath = path.join( | |
__dirname, | |
'..', | |
'..', | |
'client', | |
'public', | |
'images', | |
'openid', | |
fileName, | |
); | |
const imagePathOrEmpty = await downloadImage( | |
imageUrl, | |
imagePath, | |
tokenset.access_token, | |
); | |
user.avatar = imagePathOrEmpty; | |
} else { | |
user.avatar = ''; | |
} | |
await user.save(); | |
done(null, user); | |
} catch (err) { | |
done(err); | |
} | |
}, | |
); | |
passport.use('openid', openidLogin); | |
} catch (err) { | |
console.error(err); | |
} | |
} | |
module.exports = setupOpenId; | |