mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-18 17:25:16 -04:00
Move old backend code to old_src folder
Signed-off-by: David Mehren <git@herrmehren.de>
This commit is contained in:
parent
c42d2223e8
commit
7b9f9a487b
97 changed files with 7 additions and 7 deletions
41
old_src/lib/web/auth/dropbox/index.ts
Normal file
41
old_src/lib/web/auth/dropbox/index.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
import { NextFunction, Request, Response, Router } from 'express'
|
||||
import passport from 'passport'
|
||||
import { Strategy as DropboxStrategy } from 'passport-dropbox-oauth2'
|
||||
import { config } from '../../../config'
|
||||
import { User } from '../../../models'
|
||||
import { AuthMiddleware } from '../interface'
|
||||
import { passportGeneralCallback } from '../utils'
|
||||
|
||||
export const dropboxAuth = Router()
|
||||
|
||||
export const DropboxMiddleware: AuthMiddleware = {
|
||||
getMiddleware (): Router {
|
||||
passport.use(new DropboxStrategy({
|
||||
apiVersion: '2',
|
||||
clientID: config.dropbox.clientID,
|
||||
clientSecret: config.dropbox.clientSecret,
|
||||
callbackURL: config.serverURL + '/auth/dropbox/callback'
|
||||
}, (
|
||||
accessToken: string,
|
||||
refreshToken: string,
|
||||
profile,
|
||||
done: (err?: Error | null, user?: User) => void
|
||||
): void => {
|
||||
// the Dropbox plugin wraps the email addresses in an object
|
||||
// see https://github.com/florianheinemann/passport-dropbox-oauth2/blob/master/lib/passport-dropbox-oauth2/strategy.js#L146
|
||||
profile.emails = profile.emails.map(element => element.value)
|
||||
passportGeneralCallback(accessToken, refreshToken, profile, done)
|
||||
}))
|
||||
|
||||
dropboxAuth.get('/auth/dropbox', function (req: Request, res: Response, next: NextFunction) {
|
||||
passport.authenticate('dropbox-oauth2')(req, res, next)
|
||||
})
|
||||
dropboxAuth.get('/auth/dropbox/callback',
|
||||
passport.authenticate('dropbox-oauth2', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
failureRedirect: config.serverURL + '/'
|
||||
})
|
||||
)
|
||||
return dropboxAuth
|
||||
}
|
||||
}
|
95
old_src/lib/web/auth/email/index.ts
Normal file
95
old_src/lib/web/auth/email/index.ts
Normal file
|
@ -0,0 +1,95 @@
|
|||
import { NextFunction, Request, Response, Router } from 'express'
|
||||
import passport from 'passport'
|
||||
import { Strategy as LocalStrategy } from 'passport-local'
|
||||
import validator from 'validator'
|
||||
import { config } from '../../../config'
|
||||
import { errors } from '../../../errors'
|
||||
import { logger } from '../../../logger'
|
||||
import { User } from '../../../models'
|
||||
import { urlencodedParser } from '../../utils'
|
||||
import { AuthMiddleware } from '../interface'
|
||||
|
||||
const emailAuth = Router()
|
||||
|
||||
export const EmailMiddleware: AuthMiddleware = {
|
||||
getMiddleware (): Router {
|
||||
passport.use(new LocalStrategy({
|
||||
usernameField: 'email'
|
||||
}, function (email: string, password: string, done) {
|
||||
if (!validator.isEmail(email)) return done(null, false)
|
||||
User.findOne({
|
||||
where: {
|
||||
email: email
|
||||
}
|
||||
}).then(function (user: User) {
|
||||
if (!user) return done(null, false)
|
||||
user.verifyPassword(password).then(verified => {
|
||||
if (verified) {
|
||||
return done(null, user)
|
||||
} else {
|
||||
logger.warn('invalid password given for %s', user.email)
|
||||
return done(null, false)
|
||||
}
|
||||
})
|
||||
}).catch(function (err: Error) {
|
||||
logger.error(err)
|
||||
return done(err)
|
||||
})
|
||||
}))
|
||||
|
||||
if (config.allowEmailRegister) {
|
||||
emailAuth.post('/register', urlencodedParser, function (req: Request, res: Response, _: NextFunction) {
|
||||
if (!req.body.email || !req.body.password) {
|
||||
errors.errorBadRequest(res)
|
||||
return
|
||||
}
|
||||
if (!validator.isEmail(req.body.email)) {
|
||||
errors.errorBadRequest(res)
|
||||
return
|
||||
}
|
||||
User.findOrCreate({
|
||||
where: {
|
||||
email: req.body.email
|
||||
},
|
||||
defaults: {
|
||||
password: req.body.password
|
||||
}
|
||||
}).then(function ([user, created]: [User, boolean]) {
|
||||
if (user) {
|
||||
if (created) {
|
||||
logger.debug('user registered: ' + user.id)
|
||||
req.flash('info', "You've successfully registered, please signin.")
|
||||
return res.redirect(config.serverURL + '/')
|
||||
} else {
|
||||
logger.debug('user found: ' + user.id)
|
||||
req.flash('error', 'This email has been used, please try another one.')
|
||||
return res.redirect(config.serverURL + '/')
|
||||
}
|
||||
}
|
||||
req.flash('error', 'Failed to register your account, please try again.')
|
||||
return res.redirect(config.serverURL + '/')
|
||||
}).catch(function (err) {
|
||||
logger.error('auth callback failed: ' + err)
|
||||
errors.errorInternalError(res)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
emailAuth.post('/login', urlencodedParser, function (req: Request, res: Response, next: NextFunction) {
|
||||
if (!req.body.email || !req.body.password) {
|
||||
errors.errorBadRequest(res)
|
||||
return
|
||||
}
|
||||
if (!validator.isEmail(req.body.email)) {
|
||||
errors.errorBadRequest(res)
|
||||
return
|
||||
}
|
||||
passport.authenticate('local', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
failureRedirect: config.serverURL + '/',
|
||||
failureFlash: 'Invalid email or password.'
|
||||
})(req, res, next)
|
||||
})
|
||||
return emailAuth
|
||||
}
|
||||
}
|
31
old_src/lib/web/auth/facebook/index.ts
Normal file
31
old_src/lib/web/auth/facebook/index.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
import passport from 'passport'
|
||||
import { config } from '../../../config'
|
||||
import { AuthMiddleware } from '../interface'
|
||||
import { Router } from 'express'
|
||||
import { passportGeneralCallback } from '../utils'
|
||||
import { Strategy as FacebookStrategy } from 'passport-facebook'
|
||||
|
||||
export const FacebookMiddleware: AuthMiddleware = {
|
||||
getMiddleware (): Router {
|
||||
const facebookAuth = Router()
|
||||
passport.use(new FacebookStrategy({
|
||||
clientID: config.facebook.clientID,
|
||||
clientSecret: config.facebook.clientSecret,
|
||||
callbackURL: config.serverURL + '/auth/facebook/callback'
|
||||
}, passportGeneralCallback
|
||||
))
|
||||
|
||||
facebookAuth.get('/auth/facebook', function (req, res, next) {
|
||||
passport.authenticate('facebook')(req, res, next)
|
||||
})
|
||||
|
||||
// facebook auth callback
|
||||
facebookAuth.get('/auth/facebook/callback',
|
||||
passport.authenticate('facebook', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
failureRedirect: config.serverURL + '/'
|
||||
})
|
||||
)
|
||||
return facebookAuth
|
||||
}
|
||||
}
|
36
old_src/lib/web/auth/github/index.ts
Normal file
36
old_src/lib/web/auth/github/index.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { Router } from 'express'
|
||||
import passport from 'passport'
|
||||
import { Strategy as GithubStrategy } from 'passport-github'
|
||||
import { config } from '../../../config'
|
||||
import { response } from '../../../response'
|
||||
import { AuthMiddleware } from '../interface'
|
||||
import { passportGeneralCallback } from '../utils'
|
||||
|
||||
export const GithubMiddleware: AuthMiddleware = {
|
||||
getMiddleware (): Router {
|
||||
const githubAuth = Router()
|
||||
|
||||
passport.use(new GithubStrategy({
|
||||
clientID: config.github.clientID,
|
||||
clientSecret: config.github.clientSecret,
|
||||
callbackURL: config.serverURL + '/auth/github/callback'
|
||||
}, passportGeneralCallback))
|
||||
|
||||
githubAuth.get('/auth/github', function (req, res, next) {
|
||||
passport.authenticate('github')(req, res, next)
|
||||
})
|
||||
|
||||
// github auth callback
|
||||
githubAuth.get('/auth/github/callback',
|
||||
passport.authenticate('github', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
failureRedirect: config.serverURL + '/'
|
||||
})
|
||||
)
|
||||
|
||||
// github callback actions
|
||||
githubAuth.get('/auth/github/callback/:noteId/:action', response.githubActions)
|
||||
|
||||
return githubAuth
|
||||
}
|
||||
}
|
41
old_src/lib/web/auth/gitlab/index.ts
Normal file
41
old_src/lib/web/auth/gitlab/index.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
import { Router } from 'express'
|
||||
import passport from 'passport'
|
||||
import { Strategy as GitlabStrategy } from 'passport-gitlab2'
|
||||
import { config } from '../../../config'
|
||||
import { response } from '../../../response'
|
||||
import { AuthMiddleware } from '../interface'
|
||||
import { passportGeneralCallback } from '../utils'
|
||||
|
||||
export const GitlabMiddleware: AuthMiddleware =
|
||||
{
|
||||
getMiddleware (): Router {
|
||||
const gitlabAuth = module.exports = Router()
|
||||
|
||||
passport.use(new GitlabStrategy({
|
||||
baseURL: config.gitlab.baseURL,
|
||||
clientID: config.gitlab.clientID,
|
||||
clientSecret: config.gitlab.clientSecret,
|
||||
scope: config.gitlab.scope,
|
||||
callbackURL: config.serverURL + '/auth/gitlab/callback'
|
||||
}, passportGeneralCallback))
|
||||
|
||||
gitlabAuth.get('/auth/gitlab', function (req, res, next) {
|
||||
passport.authenticate('gitlab')(req, res, next)
|
||||
})
|
||||
|
||||
// gitlab auth callback
|
||||
gitlabAuth.get('/auth/gitlab/callback',
|
||||
passport.authenticate('gitlab', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
failureRedirect: config.serverURL + '/'
|
||||
})
|
||||
)
|
||||
|
||||
if (!config.gitlab.scope || config.gitlab.scope === 'api'
|
||||
) {
|
||||
// gitlab callback actions
|
||||
gitlabAuth.get('/auth/gitlab/callback/:noteId/:action', response.gitlabActions)
|
||||
}
|
||||
return gitlabAuth
|
||||
}
|
||||
}
|
44
old_src/lib/web/auth/google/index.ts
Normal file
44
old_src/lib/web/auth/google/index.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { Router } from 'express'
|
||||
import passport from 'passport'
|
||||
import * as Google from 'passport-google-oauth20'
|
||||
import { config } from '../../../config'
|
||||
import { AuthMiddleware } from '../interface'
|
||||
import { passportGeneralCallback } from '../utils'
|
||||
|
||||
const googleAuth = Router()
|
||||
|
||||
export const GoogleMiddleware: AuthMiddleware = {
|
||||
getMiddleware: function (): Router {
|
||||
passport.use(new Google.Strategy({
|
||||
clientID: config.google.clientID,
|
||||
clientSecret: config.google.clientSecret,
|
||||
callbackURL: config.serverURL + '/auth/google/callback',
|
||||
userProfileURL: 'https://www.googleapis.com/oauth2/v3/userinfo'
|
||||
}, (
|
||||
accessToken: string,
|
||||
refreshToken: string,
|
||||
profile,
|
||||
done) => {
|
||||
/*
|
||||
This ugly hack is neccessary, because the Google Strategy wants a done-callback with an err as Error | null | undefined
|
||||
but the passportGeneralCallback (and every other PassportStrategy) want a done-callback with err as string | Error | undefined
|
||||
Note the absence of null. The lambda converts all `null` to `undefined`.
|
||||
*/
|
||||
passportGeneralCallback(accessToken, refreshToken, profile, (err?, user?) => {
|
||||
done(err === null ? undefined : err, user)
|
||||
})
|
||||
}))
|
||||
|
||||
googleAuth.get('/auth/google', function (req, res, next) {
|
||||
const authOpts = { scope: ['profile'], hostedDomain: config.google.hostedDomain }
|
||||
passport.authenticate('google', authOpts)(req, res, next)
|
||||
})
|
||||
googleAuth.get('/auth/google/callback',
|
||||
passport.authenticate('google', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
failureRedirect: config.serverURL + '/'
|
||||
})
|
||||
)
|
||||
return googleAuth
|
||||
}
|
||||
}
|
69
old_src/lib/web/auth/index.ts
Normal file
69
old_src/lib/web/auth/index.ts
Normal file
|
@ -0,0 +1,69 @@
|
|||
import { Request, Response, Router } from 'express'
|
||||
import passport from 'passport'
|
||||
import { config } from '../../config'
|
||||
import { logger } from '../../logger'
|
||||
import { User } from '../../models'
|
||||
import { FacebookMiddleware } from './facebook'
|
||||
import { TwitterMiddleware } from './twitter'
|
||||
import { GithubMiddleware } from './github'
|
||||
import { GitlabMiddleware } from './gitlab'
|
||||
import { DropboxMiddleware } from './dropbox'
|
||||
import { GoogleMiddleware } from './google'
|
||||
import { LdapMiddleware } from './ldap'
|
||||
import { SamlMiddleware } from './saml'
|
||||
import { OAuth2Middleware } from './oauth2'
|
||||
import { EmailMiddleware } from './email'
|
||||
import { OPenIDMiddleware } from './openid'
|
||||
|
||||
const AuthRouter = Router()
|
||||
|
||||
// serialize and deserialize
|
||||
passport.serializeUser(function (user: User, done) {
|
||||
logger.info('serializeUser: ' + user.id)
|
||||
return done(null, user.id)
|
||||
})
|
||||
|
||||
passport.deserializeUser(function (id: string, done) {
|
||||
User.findOne({
|
||||
where: {
|
||||
id: id
|
||||
}
|
||||
}).then(function (user) {
|
||||
// Don't die on non-existent user
|
||||
if (user == null) {
|
||||
// The extra object with message doesn't exits in @types/passport
|
||||
return done(null, false) // , { message: 'Invalid UserID' })
|
||||
}
|
||||
|
||||
logger.info('deserializeUser: ' + user.id)
|
||||
return done(null, user)
|
||||
}).catch(function (err) {
|
||||
logger.error(err)
|
||||
return done(err, null)
|
||||
})
|
||||
})
|
||||
|
||||
if (config.isFacebookEnable) AuthRouter.use(FacebookMiddleware.getMiddleware())
|
||||
if (config.isTwitterEnable) AuthRouter.use(TwitterMiddleware.getMiddleware())
|
||||
if (config.isGitHubEnable) AuthRouter.use(GithubMiddleware.getMiddleware())
|
||||
if (config.isGitLabEnable) AuthRouter.use(GitlabMiddleware.getMiddleware())
|
||||
if (config.isDropboxEnable) AuthRouter.use(DropboxMiddleware.getMiddleware())
|
||||
if (config.isGoogleEnable) AuthRouter.use(GoogleMiddleware.getMiddleware())
|
||||
if (config.isLDAPEnable) AuthRouter.use(LdapMiddleware.getMiddleware())
|
||||
if (config.isSAMLEnable) AuthRouter.use(SamlMiddleware.getMiddleware())
|
||||
if (config.isOAuth2Enable) AuthRouter.use(OAuth2Middleware.getMiddleware())
|
||||
if (config.isEmailEnable) AuthRouter.use(EmailMiddleware.getMiddleware())
|
||||
if (config.isOpenIDEnable) AuthRouter.use(OPenIDMiddleware.getMiddleware())
|
||||
|
||||
// logout
|
||||
AuthRouter.get('/logout', function (req: Request, res: Response) {
|
||||
if (config.debug && req.isAuthenticated()) {
|
||||
if (req.user !== undefined) {
|
||||
logger.debug('user logout: ' + req.user.id)
|
||||
}
|
||||
}
|
||||
req.logout()
|
||||
res.redirect(config.serverURL + '/')
|
||||
})
|
||||
|
||||
export { AuthRouter }
|
5
old_src/lib/web/auth/interface.ts
Normal file
5
old_src/lib/web/auth/interface.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { Router } from 'express'
|
||||
|
||||
export interface AuthMiddleware {
|
||||
getMiddleware (): Router;
|
||||
}
|
96
old_src/lib/web/auth/ldap/index.ts
Normal file
96
old_src/lib/web/auth/ldap/index.ts
Normal file
|
@ -0,0 +1,96 @@
|
|||
import { Router } from 'express'
|
||||
import passport from 'passport'
|
||||
import LDAPStrategy from 'passport-ldapauth'
|
||||
|
||||
import { config } from '../../../config'
|
||||
import { errors } from '../../../errors'
|
||||
import { logger } from '../../../logger'
|
||||
import { User } from '../../../models'
|
||||
import { urlencodedParser } from '../../utils'
|
||||
import { AuthMiddleware } from '../interface'
|
||||
|
||||
export const LdapMiddleware: AuthMiddleware = {
|
||||
getMiddleware (): Router {
|
||||
const LdapAuth = Router()
|
||||
|
||||
passport.use(new LDAPStrategy({
|
||||
server: {
|
||||
url: config.ldap.url || null,
|
||||
bindDN: config.ldap.bindDn || null,
|
||||
bindCredentials: config.ldap.bindCredentials || null,
|
||||
searchBase: config.ldap.searchBase || null,
|
||||
searchFilter: config.ldap.searchFilter || null,
|
||||
searchAttributes: config.ldap.searchAttributes || null,
|
||||
tlsOptions: config.ldap.tlsOptions || null,
|
||||
starttls: config.ldap.starttls || null
|
||||
}
|
||||
}, function (user, done) {
|
||||
let uuid = user.uidNumber || user.uid || user.sAMAccountName || undefined
|
||||
if (config.ldap.useridField && user[config.ldap.useridField]) {
|
||||
uuid = user[config.ldap.useridField]
|
||||
}
|
||||
|
||||
if (typeof uuid === 'undefined') {
|
||||
throw new Error('Could not determine UUID for LDAP user. Check that ' +
|
||||
'either uidNumber, uid or sAMAccountName is set in your LDAP directory ' +
|
||||
'or use another unique attribute and configure it using the ' +
|
||||
'"useridField" option in ldap settings.')
|
||||
}
|
||||
|
||||
let username = uuid
|
||||
if (config.ldap.usernameField && user[config.ldap.usernameField]) {
|
||||
username = user[config.ldap.usernameField]
|
||||
}
|
||||
|
||||
const profile = {
|
||||
id: 'LDAP-' + uuid,
|
||||
username: username,
|
||||
displayName: user.displayName,
|
||||
emails: user.mail ? Array.isArray(user.mail) ? user.mail : [user.mail] : [],
|
||||
avatarUrl: null,
|
||||
profileUrl: null,
|
||||
provider: 'ldap'
|
||||
}
|
||||
const stringifiedProfile = JSON.stringify(profile)
|
||||
User.findOrCreate({
|
||||
where: {
|
||||
profileid: profile.id.toString()
|
||||
},
|
||||
defaults: {
|
||||
profile: stringifiedProfile
|
||||
}
|
||||
}).then(function ([user, _]) {
|
||||
if (user) {
|
||||
let needSave = false
|
||||
if (user.profile !== stringifiedProfile) {
|
||||
user.profile = stringifiedProfile
|
||||
needSave = true
|
||||
}
|
||||
if (needSave) {
|
||||
user.save().then(function () {
|
||||
logger.debug(`user login: ${user.id}`)
|
||||
return done(null, user)
|
||||
})
|
||||
} else {
|
||||
logger.debug(`user login: ${user.id}`)
|
||||
return done(null, user)
|
||||
}
|
||||
}
|
||||
}).catch(function (err) {
|
||||
logger.error('ldap auth failed: ' + err)
|
||||
return done(err, null)
|
||||
})
|
||||
}))
|
||||
|
||||
LdapAuth.post('/auth/ldap', urlencodedParser, function (req, res, next) {
|
||||
if (!req.body.username || !req.body.password) return errors.errorBadRequest(res)
|
||||
passport.authenticate('ldapauth', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
failureRedirect: config.serverURL + '/',
|
||||
failureFlash: true
|
||||
})(req, res, next)
|
||||
})
|
||||
|
||||
return LdapAuth
|
||||
}
|
||||
}
|
36
old_src/lib/web/auth/oauth2/index.ts
Normal file
36
old_src/lib/web/auth/oauth2/index.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { Router } from 'express'
|
||||
import passport from 'passport'
|
||||
|
||||
import { OAuth2CustomStrategy } from './oauth2-custom-strategy'
|
||||
import { config } from '../../../config'
|
||||
import { passportGeneralCallback } from '../utils'
|
||||
import { AuthMiddleware } from '../interface'
|
||||
|
||||
export const OAuth2Middleware: AuthMiddleware = {
|
||||
getMiddleware (): Router {
|
||||
const OAuth2Auth = Router()
|
||||
|
||||
passport.use(new OAuth2CustomStrategy({
|
||||
authorizationURL: config.oauth2.authorizationURL,
|
||||
tokenURL: config.oauth2.tokenURL,
|
||||
clientID: config.oauth2.clientID,
|
||||
clientSecret: config.oauth2.clientSecret,
|
||||
callbackURL: config.serverURL + '/auth/oauth2/callback',
|
||||
userProfileURL: config.oauth2.userProfileURL,
|
||||
scope: config.oauth2.scope,
|
||||
state: true
|
||||
}, passportGeneralCallback))
|
||||
|
||||
OAuth2Auth.get('/auth/oauth2', passport.authenticate('oauth2'))
|
||||
|
||||
// github auth callback
|
||||
OAuth2Auth.get('/auth/oauth2/callback',
|
||||
passport.authenticate('oauth2', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
failureRedirect: config.serverURL + '/'
|
||||
})
|
||||
)
|
||||
|
||||
return OAuth2Auth
|
||||
}
|
||||
}
|
84
old_src/lib/web/auth/oauth2/oauth2-custom-strategy.ts
Normal file
84
old_src/lib/web/auth/oauth2/oauth2-custom-strategy.ts
Normal file
|
@ -0,0 +1,84 @@
|
|||
import { InternalOAuthError, Strategy as OAuth2Strategy } from 'passport-oauth2'
|
||||
import { config } from '../../../config'
|
||||
import { PassportProfile, ProviderEnum } from '../utils'
|
||||
import { logger } from '../../../logger'
|
||||
|
||||
function extractProfileAttribute (data, path: string): string {
|
||||
// can handle stuff like `attrs[0].name`
|
||||
const pathArray = path.split('.')
|
||||
for (const segment of pathArray) {
|
||||
const regex = /([\d\w]+)\[(.*)\]/
|
||||
const m = regex.exec(segment)
|
||||
data = m ? data[m[1]][m[2]] : data[segment]
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
function parseProfile (data): Partial<PassportProfile> {
|
||||
const username = extractProfileAttribute(data, config.oauth2.userProfileUsernameAttr)
|
||||
let displayName: string | undefined
|
||||
try {
|
||||
// This may fail if the config.oauth2.userProfileDisplayNameAttr is undefined,
|
||||
// or it is foo.bar and data["foo"] is undefined.
|
||||
displayName = extractProfileAttribute(data, config.oauth2.userProfileDisplayNameAttr)
|
||||
} catch (e) {
|
||||
displayName = undefined
|
||||
logger.debug('\'id_token[%s]\' is undefined. Setting \'displayName\' to \'undefined\'.\n%s', config.oauth2.userProfileDisplayNameAttr, e.message)
|
||||
}
|
||||
|
||||
const emails: string[] = []
|
||||
try {
|
||||
const email = extractProfileAttribute(data, config.oauth2.userProfileEmailAttr)
|
||||
if (email !== undefined) {
|
||||
emails.push(email)
|
||||
} else {
|
||||
logger.debug('\'id_token[%s]\' is undefined. Setting \'emails\' to [].', config.oauth2.userProfileEmailAttr)
|
||||
}
|
||||
} catch (e) {
|
||||
logger.debug('\'id_token[%s]\' is undefined. Setting \'emails\' to [].\n%s', config.oauth2.userProfileEmailAttr, e.message)
|
||||
}
|
||||
|
||||
return {
|
||||
id: username,
|
||||
username: username,
|
||||
displayName: displayName,
|
||||
emails: emails
|
||||
}
|
||||
}
|
||||
|
||||
class OAuth2CustomStrategy extends OAuth2Strategy {
|
||||
private readonly _userProfileURL: string;
|
||||
|
||||
constructor (options, verify) {
|
||||
options.customHeaders = options.customHeaders || {}
|
||||
super(options, verify)
|
||||
this.name = 'oauth2'
|
||||
this._userProfileURL = options.userProfileURL
|
||||
this._oauth2.useAuthorizationHeaderforGET(true)
|
||||
}
|
||||
|
||||
userProfile (accessToken, done): void {
|
||||
this._oauth2.get(this._userProfileURL, accessToken, function (err, body, _) {
|
||||
let json
|
||||
|
||||
if (err) {
|
||||
return done(new InternalOAuthError('Failed to fetch user profile', err))
|
||||
}
|
||||
|
||||
try {
|
||||
if (body !== undefined) {
|
||||
json = JSON.parse(body.toString())
|
||||
}
|
||||
} catch (ex) {
|
||||
return done(new Error('Failed to parse user profile'))
|
||||
}
|
||||
|
||||
const profile = parseProfile(json)
|
||||
profile.provider = ProviderEnum.oauth2
|
||||
|
||||
done(null, profile)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { OAuth2CustomStrategy }
|
59
old_src/lib/web/auth/openid/index.ts
Normal file
59
old_src/lib/web/auth/openid/index.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
import { Router } from 'express'
|
||||
import passport from 'passport'
|
||||
import * as OpenID from '@passport-next/passport-openid'
|
||||
import { config } from '../../../config'
|
||||
import { User } from '../../../models'
|
||||
import { logger } from '../../../logger'
|
||||
import { urlencodedParser } from '../../utils'
|
||||
import { AuthMiddleware } from '../interface'
|
||||
|
||||
const openIDAuth = Router()
|
||||
export const OPenIDMiddleware: AuthMiddleware = {
|
||||
getMiddleware (): Router {
|
||||
passport.use(new OpenID.Strategy({
|
||||
returnURL: config.serverURL + '/auth/openid/callback',
|
||||
realm: config.serverURL,
|
||||
profile: true
|
||||
}, function (openid, profile, done) {
|
||||
const stringifiedProfile = JSON.stringify(profile)
|
||||
User.findOrCreate({
|
||||
where: {
|
||||
profileid: openid
|
||||
},
|
||||
defaults: {
|
||||
profile: stringifiedProfile
|
||||
}
|
||||
}).then(function ([user, _]) {
|
||||
if (user) {
|
||||
let needSave = false
|
||||
if (user.profile !== stringifiedProfile) {
|
||||
user.profile = stringifiedProfile
|
||||
needSave = true
|
||||
}
|
||||
if (needSave) {
|
||||
user.save().then(function () {
|
||||
logger.debug(`user login: ${user.id}`)
|
||||
return done(null, user)
|
||||
})
|
||||
} else {
|
||||
logger.debug(`user login: ${user.id}`)
|
||||
return done(null, user)
|
||||
}
|
||||
}
|
||||
}).catch(function (err) {
|
||||
logger.error('auth callback failed: ' + err)
|
||||
return done(err, null)
|
||||
})
|
||||
}))
|
||||
openIDAuth.post('/auth/openid', urlencodedParser, function (req, res, next) {
|
||||
passport.authenticate('openid')(req, res, next)
|
||||
})
|
||||
openIDAuth.get('/auth/openid/callback',
|
||||
passport.authenticate('openid', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
failureRedirect: config.serverURL + '/'
|
||||
})
|
||||
)
|
||||
return openIDAuth
|
||||
}
|
||||
}
|
107
old_src/lib/web/auth/saml/index.ts
Normal file
107
old_src/lib/web/auth/saml/index.ts
Normal file
|
@ -0,0 +1,107 @@
|
|||
import { Router } from 'express'
|
||||
import passport from 'passport'
|
||||
import { Strategy as SamlStrategy } from 'passport-saml'
|
||||
import fs from 'fs'
|
||||
|
||||
import { config } from '../../../config'
|
||||
import { User } from '../../../models'
|
||||
import { logger } from '../../../logger'
|
||||
import { urlencodedParser } from '../../utils'
|
||||
import { AuthMiddleware } from '../interface'
|
||||
|
||||
function intersection<T> (array1: T[], array2: T[]): T[] {
|
||||
return array1.filter((n) => array2.includes(n))
|
||||
}
|
||||
|
||||
export const SamlMiddleware: AuthMiddleware = {
|
||||
getMiddleware (): Router {
|
||||
const SamlAuth = Router()
|
||||
|
||||
const samlStrategy = new SamlStrategy({
|
||||
callbackUrl: config.serverURL + '/auth/saml/callback',
|
||||
entryPoint: config.saml.idpSsoUrl,
|
||||
issuer: config.saml.issuer || config.serverURL,
|
||||
cert: fs.readFileSync(config.saml.idpCert, 'utf-8'),
|
||||
identifierFormat: config.saml.identifierFormat,
|
||||
disableRequestedAuthnContext: config.saml.disableRequestedAuthnContext
|
||||
}, function (user, done) {
|
||||
// check authorization if needed
|
||||
if (config.saml.externalGroups && config.saml.groupAttribute) {
|
||||
const externalGroups: string[] = intersection(config.saml.externalGroups, user[config.saml.groupAttribute])
|
||||
if (externalGroups.length > 0) {
|
||||
logger.error('saml permission denied: ' + externalGroups.join(', '))
|
||||
return done('Permission denied', null)
|
||||
}
|
||||
}
|
||||
if (config.saml.requiredGroups && config.saml.groupAttribute) {
|
||||
if (intersection(config.saml.requiredGroups, user[config.saml.groupAttribute]).length === 0) {
|
||||
logger.error('saml permission denied')
|
||||
return done('Permission denied', null)
|
||||
}
|
||||
}
|
||||
// user creation
|
||||
const uuid = user[config.saml.attribute.id] || user.nameID
|
||||
const profile = {
|
||||
provider: 'saml',
|
||||
id: 'SAML-' + uuid,
|
||||
username: user[config.saml.attribute.username] || user.nameID,
|
||||
emails: user[config.saml.attribute.email] ? [user[config.saml.attribute.email]] : []
|
||||
}
|
||||
if (profile.emails.length === 0 && config.saml.identifierFormat === 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress') {
|
||||
profile.emails.push(user.nameID)
|
||||
}
|
||||
const stringifiedProfile = JSON.stringify(profile)
|
||||
User.findOrCreate({
|
||||
where: {
|
||||
profileid: profile.id.toString()
|
||||
},
|
||||
defaults: {
|
||||
profile: stringifiedProfile
|
||||
}
|
||||
}).then(function ([user, _]) {
|
||||
if (user) {
|
||||
let needSave = false
|
||||
if (user.profile !== stringifiedProfile) {
|
||||
user.profile = stringifiedProfile
|
||||
needSave = true
|
||||
}
|
||||
if (needSave) {
|
||||
user.save().then(function () {
|
||||
logger.debug(`user login: ${user.id}`)
|
||||
return done(null, user)
|
||||
})
|
||||
} else {
|
||||
logger.debug(`user login: ${user.id}`)
|
||||
return done(null, user)
|
||||
}
|
||||
}
|
||||
}).catch(function (err) {
|
||||
logger.error('saml auth failed: ' + err)
|
||||
return done(err, null)
|
||||
})
|
||||
})
|
||||
|
||||
passport.use(samlStrategy)
|
||||
|
||||
SamlAuth.get('/auth/saml',
|
||||
passport.authenticate('saml', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
failureRedirect: config.serverURL + '/'
|
||||
})
|
||||
)
|
||||
|
||||
SamlAuth.post('/auth/saml/callback', urlencodedParser,
|
||||
passport.authenticate('saml', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
failureRedirect: config.serverURL + '/'
|
||||
})
|
||||
)
|
||||
|
||||
SamlAuth.get('/auth/saml/metadata', function (req, res) {
|
||||
res.type('application/xml')
|
||||
res.send(samlStrategy.generateServiceProviderMetadata(null))
|
||||
})
|
||||
|
||||
return SamlAuth
|
||||
}
|
||||
}
|
33
old_src/lib/web/auth/twitter/index.ts
Normal file
33
old_src/lib/web/auth/twitter/index.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import { Router } from 'express'
|
||||
import passport from 'passport'
|
||||
import { Strategy as TwitterStrategy } from 'passport-twitter'
|
||||
|
||||
import { config } from '../../../config'
|
||||
import { passportGeneralCallback } from '../utils'
|
||||
import { AuthMiddleware } from '../interface'
|
||||
|
||||
export const TwitterMiddleware: AuthMiddleware = {
|
||||
getMiddleware (): Router {
|
||||
const TwitterAuth = Router()
|
||||
|
||||
passport.use(new TwitterStrategy({
|
||||
consumerKey: config.twitter.consumerKey,
|
||||
consumerSecret: config.twitter.consumerSecret,
|
||||
callbackURL: config.serverURL + '/auth/twitter/callback'
|
||||
}, passportGeneralCallback))
|
||||
|
||||
TwitterAuth.get('/auth/twitter', function (req, res, next) {
|
||||
passport.authenticate('twitter')(req, res, next)
|
||||
})
|
||||
|
||||
// twitter auth callback
|
||||
TwitterAuth.get('/auth/twitter/callback',
|
||||
passport.authenticate('twitter', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
failureRedirect: config.serverURL + '/'
|
||||
})
|
||||
)
|
||||
|
||||
return TwitterAuth
|
||||
}
|
||||
}
|
73
old_src/lib/web/auth/utils.ts
Normal file
73
old_src/lib/web/auth/utils.ts
Normal file
|
@ -0,0 +1,73 @@
|
|||
import { Profile } from 'passport'
|
||||
import { logger } from '../../logger'
|
||||
import { User } from '../../models'
|
||||
|
||||
export function passportGeneralCallback (
|
||||
accessToken: string,
|
||||
refreshToken: string,
|
||||
profile: Profile,
|
||||
done: (err?: Error | null, user?: User) => void
|
||||
): void {
|
||||
const stringifiedProfile = JSON.stringify(profile)
|
||||
User.findOrCreate({
|
||||
where: {
|
||||
profileid: profile.id.toString()
|
||||
},
|
||||
defaults: {
|
||||
profile: stringifiedProfile,
|
||||
accessToken: accessToken,
|
||||
refreshToken: refreshToken
|
||||
}
|
||||
}).then(function ([user, _]) {
|
||||
if (user) {
|
||||
let needSave = false
|
||||
if (user.profile !== stringifiedProfile) {
|
||||
user.profile = stringifiedProfile
|
||||
needSave = true
|
||||
}
|
||||
if (user.accessToken !== accessToken) {
|
||||
user.accessToken = accessToken
|
||||
needSave = true
|
||||
}
|
||||
if (user.refreshToken !== refreshToken) {
|
||||
user.refreshToken = refreshToken
|
||||
needSave = true
|
||||
}
|
||||
if (needSave) {
|
||||
user.save().then(function () {
|
||||
logger.debug(`user login: ${user.id}`)
|
||||
return done(null, user)
|
||||
})
|
||||
} else {
|
||||
logger.debug(`user login: ${user.id}`)
|
||||
return done(null, user)
|
||||
}
|
||||
}
|
||||
}).catch(function (err) {
|
||||
logger.error('auth callback failed: ' + err)
|
||||
return done(err, undefined)
|
||||
})
|
||||
}
|
||||
|
||||
export enum ProviderEnum {
|
||||
facebook = 'facebook',
|
||||
twitter = 'twitter',
|
||||
github = 'github',
|
||||
gitlab = 'gitlab',
|
||||
dropbox = 'dropbox',
|
||||
google = 'google',
|
||||
ldap = 'ldap',
|
||||
oauth2 = 'oauth2',
|
||||
saml = 'saml',
|
||||
}
|
||||
|
||||
export type PassportProfile = {
|
||||
id: string;
|
||||
username: string;
|
||||
displayName: string;
|
||||
emails: string[];
|
||||
avatarUrl: string;
|
||||
profileUrl: string;
|
||||
provider: ProviderEnum;
|
||||
photos: { value: string }[];
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue