feat: logout by auth strategy + keycloak implementation
This commit is contained in:
parent
cda1f1e805
commit
062a0b7979
@ -462,8 +462,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
logout () {
|
logout () {
|
||||||
Cookies.remove('jwt')
|
window.location.assign('/logout')
|
||||||
window.location.assign('/')
|
|
||||||
},
|
},
|
||||||
goHome () {
|
goHome () {
|
||||||
window.location.assign('/')
|
window.location.assign('/')
|
||||||
|
@ -109,10 +109,11 @@ router.post('/login', bruteforce.prevent, async (req, res, next) => {
|
|||||||
/**
|
/**
|
||||||
* Logout
|
* Logout
|
||||||
*/
|
*/
|
||||||
router.get('/logout', function (req, res) {
|
router.get('/logout', async (req, res) => {
|
||||||
|
const redirURL = await WIKI.models.users.logout({ req, res })
|
||||||
req.logout()
|
req.logout()
|
||||||
res.clearCookie('jwt')
|
res.clearCookie('jwt')
|
||||||
res.redirect('/')
|
res.redirect(redirURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -271,6 +271,9 @@ module.exports = class User extends Model {
|
|||||||
throw new Error('You are not authorized to login.')
|
throw new Error('You are not authorized to login.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login a user
|
||||||
|
*/
|
||||||
static async login (opts, context) {
|
static async login (opts, context) {
|
||||||
if (_.has(WIKI.auth.strategies, opts.strategy)) {
|
if (_.has(WIKI.auth.strategies, opts.strategy)) {
|
||||||
const selStrategy = _.get(WIKI.auth.strategies, opts.strategy)
|
const selStrategy = _.get(WIKI.auth.strategies, opts.strategy)
|
||||||
@ -307,6 +310,9 @@ module.exports = class User extends Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform post-login checks
|
||||||
|
*/
|
||||||
static async afterLoginChecks (user, context, { skipTFA, skipChangePwd } = { skipTFA: false, skipChangePwd: false }) {
|
static async afterLoginChecks (user, context, { skipTFA, skipChangePwd } = { skipTFA: false, skipChangePwd: false }) {
|
||||||
// Get redirect target
|
// Get redirect target
|
||||||
user.groups = await user.$relatedQuery('groups').select('groups.id', 'permissions', 'redirectOnLogin')
|
user.groups = await user.$relatedQuery('groups').select('groups.id', 'permissions', 'redirectOnLogin')
|
||||||
@ -380,6 +386,9 @@ module.exports = class User extends Model {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a new token for a user
|
||||||
|
*/
|
||||||
static async refreshToken(user) {
|
static async refreshToken(user) {
|
||||||
if (_.isSafeInteger(user)) {
|
if (_.isSafeInteger(user)) {
|
||||||
user = await WIKI.models.users.query().findById(user).withGraphFetched('groups').modifyGraph('groups', builder => {
|
user = await WIKI.models.users.query().findById(user).withGraphFetched('groups').modifyGraph('groups', builder => {
|
||||||
@ -427,6 +436,9 @@ module.exports = class User extends Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a TFA login
|
||||||
|
*/
|
||||||
static async loginTFA ({ securityCode, continuationToken, setup }, context) {
|
static async loginTFA ({ securityCode, continuationToken, setup }, context) {
|
||||||
if (securityCode.length === 6 && continuationToken.length > 1) {
|
if (securityCode.length === 6 && continuationToken.length > 1) {
|
||||||
const user = await WIKI.models.userKeys.validateToken({
|
const user = await WIKI.models.userKeys.validateToken({
|
||||||
@ -819,6 +831,18 @@ module.exports = class User extends Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logout the current user
|
||||||
|
*/
|
||||||
|
static async logout (context) {
|
||||||
|
if (!context.req.user || context.req.user.id === 2) {
|
||||||
|
return '/'
|
||||||
|
}
|
||||||
|
const usr = await WIKI.models.users.query().findById(context.req.user.id).select('providerKey')
|
||||||
|
const provider = _.find(WIKI.auth.strategies, ['key', usr.providerKey])
|
||||||
|
return provider.logout ? provider.logout(provider.config) : '/'
|
||||||
|
}
|
||||||
|
|
||||||
static async getGuestUser () {
|
static async getGuestUser () {
|
||||||
const user = await WIKI.models.users.query().findById(2).withGraphJoined('groups').modifyGraph('groups', builder => {
|
const user = await WIKI.models.users.query().findById(2).withGraphJoined('groups').modifyGraph('groups', builder => {
|
||||||
builder.select('groups.id', 'permissions')
|
builder.select('groups.id', 'permissions')
|
||||||
|
@ -30,5 +30,8 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
logout (conf) {
|
||||||
|
return '/'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,5 +42,15 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
logout (conf) {
|
||||||
|
if (!conf.logoutUpstream) {
|
||||||
|
return '/'
|
||||||
|
} else if (conf.logoutURL && conf.logoutURL.length > 5) {
|
||||||
|
return `${conf.logoutURL}?redirect_uri=${encodeURIComponent(WIKI.config.host)}`
|
||||||
|
} else {
|
||||||
|
WIKI.logger.warn('Keycloak logout URL is not configured!')
|
||||||
|
return '/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,49 @@ website: https://www.keycloak.org/
|
|||||||
useForm: false
|
useForm: false
|
||||||
isAvailable: true
|
isAvailable: true
|
||||||
props:
|
props:
|
||||||
host: String
|
host:
|
||||||
realm: String
|
type: String
|
||||||
clientId: String
|
title: Host
|
||||||
clientSecret: String
|
hint: e.g. https://your.keycloak-host.com
|
||||||
authorizationURL: String
|
order: 1
|
||||||
userInfoURL: String
|
realm:
|
||||||
tokenURL: String
|
type: String
|
||||||
|
title: Realm
|
||||||
|
hint: The realm this application belongs to.
|
||||||
|
order: 2
|
||||||
|
clientId:
|
||||||
|
type: String
|
||||||
|
title: Client ID
|
||||||
|
hint: Application Client ID
|
||||||
|
order: 3
|
||||||
|
clientSecret:
|
||||||
|
type: String
|
||||||
|
title: Client Secret
|
||||||
|
hint: Application Client Secret
|
||||||
|
order: 4
|
||||||
|
authorizationURL:
|
||||||
|
type: String
|
||||||
|
title: Authorization Endpoint URL
|
||||||
|
hint: e.g. https://KEYCLOAK-HOST/auth/realms/YOUR-REALM/protocol/openid-connect/auth
|
||||||
|
order: 5
|
||||||
|
tokenURL:
|
||||||
|
type: String
|
||||||
|
title: Token Endpoint URL
|
||||||
|
hint: e.g. https://KEYCLOAK-HOST/auth/realms/YOUR-REALM/protocol/openid-connect/token
|
||||||
|
order: 6
|
||||||
|
userInfoURL:
|
||||||
|
type: String
|
||||||
|
title: User Info Endpoint URL
|
||||||
|
hint: e.g. https://KEYCLOAK-HOST/auth/realms/YOUR-REALM/protocol/openid-connect/userinfo
|
||||||
|
order: 7
|
||||||
|
logoutUpstream:
|
||||||
|
type: Boolean
|
||||||
|
title: Logout from Keycloak on Logout
|
||||||
|
hint: Should the user be redirected to Keycloak logout mechanism upon logout
|
||||||
|
order: 8
|
||||||
|
logoutURL:
|
||||||
|
type: String
|
||||||
|
title: Logout Endpoint URL
|
||||||
|
hint: e.g. https://KEYCLOAK-HOST/auth/realms/YOUR-REALM/protocol/openid-connect/logout
|
||||||
|
order: 9
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user