Linting
This commit is contained in:
parent
ec93d15462
commit
c16cfc328f
|
@ -11,14 +11,15 @@ async function authenticate(accessToken, refreshToken, profile, done) {
|
|||
email: profile._json.email,
|
||||
oauth2: {
|
||||
accessToken: accessToken,
|
||||
refreshToken: refreshToken
|
||||
}
|
||||
refreshToken: refreshToken,
|
||||
},
|
||||
}
|
||||
|
||||
return authenticateThirdParty(
|
||||
thirdPartyUser,
|
||||
thirdPartyUser,
|
||||
true, // require local accounts to exist
|
||||
done)
|
||||
done
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,7 +12,6 @@ const { authenticateThirdParty } = require("./third-party-common")
|
|||
* @param {*} idToken The id_token - always a JWT
|
||||
* @param {*} params The response body from requesting an access_token
|
||||
* @param {*} done The passport callback: err, user, info
|
||||
* @returns
|
||||
*/
|
||||
async function authenticate(
|
||||
issuer,
|
||||
|
@ -27,21 +26,22 @@ async function authenticate(
|
|||
) {
|
||||
const thirdPartyUser = {
|
||||
// store the issuer info to enable sync in future
|
||||
provider: issuer,
|
||||
provider: issuer,
|
||||
providerType: "oidc",
|
||||
userId: profile.id,
|
||||
profile: profile,
|
||||
email: getEmail(profile, jwtClaims),
|
||||
oauth2: {
|
||||
accessToken: accessToken,
|
||||
refreshToken: refreshToken
|
||||
}
|
||||
refreshToken: refreshToken,
|
||||
},
|
||||
}
|
||||
|
||||
return authenticateThirdParty(
|
||||
thirdPartyUser,
|
||||
thirdPartyUser,
|
||||
false, // don't require local accounts to exist
|
||||
done)
|
||||
done
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,12 +65,15 @@ function getEmail(profile, jwtClaims) {
|
|||
return username
|
||||
}
|
||||
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
function validEmail(value) {
|
||||
return (
|
||||
(value && !!value.match(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/))
|
||||
value &&
|
||||
!!value.match(
|
||||
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -92,7 +95,9 @@ exports.strategyFactory = async function (config, callbackUrl) {
|
|||
const response = await fetch(configUrl)
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Unexpected response when fetching openid-configuration: ${response.statusText}`)
|
||||
throw new Error(
|
||||
`Unexpected response when fetching openid-configuration: ${response.statusText}`
|
||||
)
|
||||
}
|
||||
|
||||
const body = await response.json()
|
||||
|
@ -110,7 +115,6 @@ exports.strategyFactory = async function (config, callbackUrl) {
|
|||
},
|
||||
authenticate
|
||||
)
|
||||
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
throw new Error("Error constructing OIDC authentication strategy", err)
|
||||
|
|
|
@ -9,73 +9,83 @@ const {
|
|||
const { authError } = require("./utils")
|
||||
|
||||
/**
|
||||
* Common authentication logic for third parties. e.g. OAuth, OIDC.
|
||||
* Common authentication logic for third parties. e.g. OAuth, OIDC.
|
||||
*/
|
||||
exports.authenticateThirdParty = async function (
|
||||
thirdPartyUser,
|
||||
requireLocalAccount = true,
|
||||
done
|
||||
) {
|
||||
if (!thirdPartyUser.provider) return authError(done, "third party user provider required")
|
||||
if (!thirdPartyUser.userId) return authError(done, "third party user id required")
|
||||
if (!thirdPartyUser.email) return authError(done, "third party user email required")
|
||||
|
||||
const db = database.getDB(StaticDatabases.GLOBAL.name)
|
||||
|
||||
let dbUser
|
||||
|
||||
// use the third party id
|
||||
const userId = generateGlobalUserID(thirdPartyUser.userId)
|
||||
|
||||
try {
|
||||
dbUser = await db.get(userId)
|
||||
} catch (err) {
|
||||
// abort when not 404 error
|
||||
if (!err.status || err.status !== 404) {
|
||||
return authError(done, "Unexpected error when retrieving existing user", err)
|
||||
}
|
||||
|
||||
// check user already exists by email
|
||||
const users = await db.query(`database/${ViewNames.USER_BY_EMAIL}`, {
|
||||
key: thirdPartyUser.email,
|
||||
include_docs: true,
|
||||
})
|
||||
const userExists = users.rows.length > 0
|
||||
thirdPartyUser,
|
||||
requireLocalAccount = true,
|
||||
done
|
||||
) {
|
||||
if (!thirdPartyUser.provider)
|
||||
return authError(done, "third party user provider required")
|
||||
if (!thirdPartyUser.userId)
|
||||
return authError(done, "third party user id required")
|
||||
if (!thirdPartyUser.email)
|
||||
return authError(done, "third party user email required")
|
||||
|
||||
if (requireLocalAccount && !userExists) {
|
||||
return authError(done, "Email does not yet exist. You must set up your local budibase account first.")
|
||||
}
|
||||
const db = database.getDB(StaticDatabases.GLOBAL.name)
|
||||
|
||||
// create the user to save
|
||||
let user
|
||||
if (userExists) {
|
||||
const existing = users.rows[0].doc
|
||||
user = constructMergedUser(userId, existing, thirdPartyUser)
|
||||
|
||||
// remove the local account to avoid conflicts
|
||||
await db.remove(existing._id, existing._rev)
|
||||
} else {
|
||||
user = constructNewUser(userId, thirdPartyUser)
|
||||
}
|
||||
let dbUser
|
||||
|
||||
// save the user
|
||||
const response = await db.post(user)
|
||||
dbUser = user
|
||||
dbUser._rev = response.rev
|
||||
// use the third party id
|
||||
const userId = generateGlobalUserID(thirdPartyUser.userId)
|
||||
|
||||
try {
|
||||
dbUser = await db.get(userId)
|
||||
} catch (err) {
|
||||
// abort when not 404 error
|
||||
if (!err.status || err.status !== 404) {
|
||||
return authError(
|
||||
done,
|
||||
"Unexpected error when retrieving existing user",
|
||||
err
|
||||
)
|
||||
}
|
||||
|
||||
// authenticate
|
||||
const payload = {
|
||||
userId: dbUser._id,
|
||||
builder: dbUser.builder,
|
||||
email: dbUser.email,
|
||||
}
|
||||
|
||||
dbUser.token = jwt.sign(payload, env.JWT_SECRET, {
|
||||
expiresIn: "1 day",
|
||||
|
||||
// check user already exists by email
|
||||
const users = await db.query(`database/${ViewNames.USER_BY_EMAIL}`, {
|
||||
key: thirdPartyUser.email,
|
||||
include_docs: true,
|
||||
})
|
||||
|
||||
return done(null, dbUser)
|
||||
const userExists = users.rows.length > 0
|
||||
|
||||
if (requireLocalAccount && !userExists) {
|
||||
return authError(
|
||||
done,
|
||||
"Email does not yet exist. You must set up your local budibase account first."
|
||||
)
|
||||
}
|
||||
|
||||
// create the user to save
|
||||
let user
|
||||
if (userExists) {
|
||||
const existing = users.rows[0].doc
|
||||
user = constructMergedUser(userId, existing, thirdPartyUser)
|
||||
|
||||
// remove the local account to avoid conflicts
|
||||
await db.remove(existing._id, existing._rev)
|
||||
} else {
|
||||
user = constructNewUser(userId, thirdPartyUser)
|
||||
}
|
||||
|
||||
// save the user
|
||||
const response = await db.post(user)
|
||||
dbUser = user
|
||||
dbUser._rev = response.rev
|
||||
}
|
||||
|
||||
// authenticate
|
||||
const payload = {
|
||||
userId: dbUser._id,
|
||||
builder: dbUser.builder,
|
||||
email: dbUser.email,
|
||||
}
|
||||
|
||||
dbUser.token = jwt.sign(payload, env.JWT_SECRET, {
|
||||
expiresIn: "1 day",
|
||||
})
|
||||
|
||||
return done(null, dbUser)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,23 +111,23 @@ function constructNewUser(userId, thirdPartyUser) {
|
|||
provider: thirdPartyUser.provider,
|
||||
providerType: thirdPartyUser.providerType,
|
||||
email: thirdPartyUser.email,
|
||||
roles: {}
|
||||
roles: {},
|
||||
}
|
||||
|
||||
// persist profile information
|
||||
// @reviewers: Historically stored at the root level of the user
|
||||
// Nest to prevent conflicts with future fields
|
||||
// Is this okay to change?
|
||||
// Is this okay to change?
|
||||
if (thirdPartyUser.profile) {
|
||||
user.thirdPartyProfile = {
|
||||
...thirdPartyUser.profile._json
|
||||
...thirdPartyUser.profile._json,
|
||||
}
|
||||
}
|
||||
|
||||
// persist oauth tokens for future use
|
||||
// persist oauth tokens for future use
|
||||
if (thirdPartyUser.oauth2) {
|
||||
user.oauth2 = {
|
||||
...thirdPartyUser.oauth2
|
||||
...thirdPartyUser.oauth2,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/**
|
||||
* Utility to handle authentication errors.
|
||||
*
|
||||
* @param {*} done The passport callback.
|
||||
* Utility to handle authentication errors.
|
||||
*
|
||||
* @param {*} done The passport callback.
|
||||
* @param {*} message Message that will be returned in the response body
|
||||
* @param {*} err (Optional) error that will be logged
|
||||
*/
|
||||
exports.authError = function (done, message, err = null) {
|
||||
return done(
|
||||
err,
|
||||
null, // never return a user
|
||||
{ message: message }
|
||||
)
|
||||
}
|
||||
return done(
|
||||
err,
|
||||
null, // never return a user
|
||||
{ message: message }
|
||||
)
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
let fileName = e.target.files[0].name
|
||||
image = e.target.files[0]
|
||||
providers.oidc.config["iconName"] = fileName
|
||||
iconDropdownOptions.unshift({label: fileName, value: fileName})
|
||||
iconDropdownOptions.unshift({ label: fileName, value: fileName })
|
||||
}
|
||||
|
||||
const providers = { google, oidc }
|
||||
|
@ -140,17 +140,17 @@
|
|||
const configSettings = await res.json()
|
||||
|
||||
if (configSettings.config) {
|
||||
const logoKeys = Object.keys(configSettings.config)
|
||||
const logoKeys = Object.keys(configSettings.config)
|
||||
|
||||
logoKeys.map(logoKey => {
|
||||
const logoUrl = configSettings.config[logoKey]
|
||||
iconDropdownOptions.unshift({
|
||||
label: logoKey,
|
||||
value: logoKey,
|
||||
icon: logoUrl,
|
||||
logoKeys.map(logoKey => {
|
||||
const logoUrl = configSettings.config[logoKey]
|
||||
iconDropdownOptions.unshift({
|
||||
label: logoKey,
|
||||
value: logoKey,
|
||||
icon: logoUrl,
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
const oidcResponse = await api.get(`/api/admin/configs/${ConfigTypes.OIDC}`)
|
||||
const oidcDoc = await oidcResponse.json()
|
||||
|
||||
|
|
|
@ -14,14 +14,14 @@ const GLOBAL_DB = authPkg.StaticDatabases.GLOBAL.name
|
|||
function authInternal(ctx, user, err = null, info = null) {
|
||||
if (err) {
|
||||
console.error("Authentication error", err)
|
||||
return ctx.throw(403, info? info : "Unauthorized")
|
||||
return ctx.throw(403, info ? info : "Unauthorized")
|
||||
}
|
||||
|
||||
const expires = new Date()
|
||||
expires.setDate(expires.getDate() + 1)
|
||||
|
||||
if (!user) {
|
||||
return ctx.throw(403, info? info : "Unauthorized")
|
||||
return ctx.throw(403, info ? info : "Unauthorized")
|
||||
}
|
||||
|
||||
ctx.cookies.set(Cookies.Auth, user.token, {
|
||||
|
|
Loading…
Reference in New Issue