update
This commit is contained in:
parent
2e05f90851
commit
94837efdee
@ -36,5 +36,5 @@ controller.logout = () => async (ctx) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
controller.getInfo = () => async (ctx) => {
|
controller.getInfo = () => async (ctx) => {
|
||||||
ctx.resp(resp.Success, {})
|
ctx.resp(resp.Success, ctx.token.info)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,9 @@ const joi = require('joi')
|
|||||||
const response = require('src/utils/response/index.js')
|
const response = require('src/utils/response/index.js')
|
||||||
const config = require('src/config/index.js')
|
const config = require('src/config/index.js')
|
||||||
const { jwt } = require('src/utils/pkgs.js')
|
const { jwt } = require('src/utils/pkgs.js')
|
||||||
const { copyObject, toNumber } = require('src/utils/index.js')
|
const sso = require('src/utils/sso/index.js')
|
||||||
|
const { copyObject } = require('src/utils/index.js')
|
||||||
|
const { get: getCacheInstance } = require('src/utils/cache.js')
|
||||||
|
|
||||||
const { Success, InternalError, DataFormat, Forbidden, Unauthorized } = response.resp
|
const { Success, InternalError, DataFormat, Forbidden, Unauthorized } = response.resp
|
||||||
|
|
||||||
@ -107,7 +109,7 @@ controller.validate = schema => {
|
|||||||
* @param {boolean=} allowExpired
|
* @param {boolean=} allowExpired
|
||||||
* @return {import('koa').Middleware}
|
* @return {import('koa').Middleware}
|
||||||
*/
|
*/
|
||||||
controller.authorization = allowExpired => {
|
controller.authorization = () => {
|
||||||
return async (ctx, next) => {
|
return async (ctx, next) => {
|
||||||
ctx.token = {}
|
ctx.token = {}
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
@ -122,44 +124,40 @@ controller.authorization = allowExpired => {
|
|||||||
|
|
||||||
[, ctx.token.origin] = strs
|
[, ctx.token.origin] = strs
|
||||||
|
|
||||||
let decoded = {}
|
const decoded = {}
|
||||||
let expired = false
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
decoded = jwt.verify(strs[1], config.server.jwt_secret)
|
// 可以考慮這邊做個cache 多久之內存取不會到keycloak驗證
|
||||||
|
let userInfo = await sso.getUserInfo(ctx.token.origin)
|
||||||
|
if (!userInfo) {
|
||||||
|
// try refresh
|
||||||
|
const cache = getCacheInstance()
|
||||||
|
const refreshToken = cache.get(ctx.token.origin)
|
||||||
|
if (!refreshToken) throw new Error('no cache data')
|
||||||
|
const token = await sso.refreshToken(refreshToken)
|
||||||
|
// set new cache
|
||||||
|
cache.set(token.access_token, token.refresh_token, false)
|
||||||
|
ctx.token.origin = token.access_token
|
||||||
|
userInfo = await sso.getUserInfo(token.access_token)
|
||||||
|
if (!userInfo) throw new Error('get user info fail')
|
||||||
|
|
||||||
await joi
|
ctx.set('x-new-token', ctx.token.origin)
|
||||||
.object({
|
}
|
||||||
user_id: joi.string().required()
|
|
||||||
})
|
Object.assign(decoded, userInfo)
|
||||||
.unknown()
|
|
||||||
.validateAsync(decoded)
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
debug(`jwt token verify fail: ${util.inspect(err, false, null)}`)
|
debug(`user info get fail ::: ${util.inspect(err, false, null)}`)
|
||||||
if (err instanceof jwt.TokenExpiredError) {
|
ctx.err(Unauthorized)
|
||||||
decoded = jwt.decode(ctx.token.origin)
|
|
||||||
expired = true
|
|
||||||
} else {
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.token.user_id = decoded.user_id
|
ctx.token.user_id = decoded.username
|
||||||
ctx.token.sso = !!decoded.sso
|
ctx.token.sso = true
|
||||||
|
|
||||||
if (expired) ctx.err(Forbidden, response.codeMessage.CodeTokenExpired)
|
ctx.token.info = decoded
|
||||||
|
|
||||||
ctx.verified = true
|
ctx.verified = true
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
debug(`Token valid fail: ${util.inspect(err, false, null)}`)
|
debug(`Token valid fail: ${util.inspect(err, false, null)}`)
|
||||||
if (err instanceof response.APIError) {
|
|
||||||
// 如果是過期的錯誤,判斷是否允許過期存取
|
|
||||||
// @ts-ignore
|
|
||||||
// eslint-disable-next-line
|
|
||||||
if (err._object?.object?.code === response.codeMessage.CodeTokenExpired.code) {
|
|
||||||
if (allowExpired) return next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,10 @@ const util = require('util')
|
|||||||
const url = require('url')
|
const url = require('url')
|
||||||
const sso = require('src/utils/sso/index.js')
|
const sso = require('src/utils/sso/index.js')
|
||||||
const { get: getCacheInstance } = require('src/utils/cache.js')
|
const { get: getCacheInstance } = require('src/utils/cache.js')
|
||||||
const { codeMessage, APIError } = require('src/utils/response/index.js')
|
const { resp, codeMessage, APIError } = require('src/utils/response/index.js')
|
||||||
const config = require('src/config/index.js')
|
const config = require('src/config/index.js')
|
||||||
const { jwt } = require('src/utils/pkgs.js')
|
const acl = require('src/utils/acl.js')
|
||||||
|
const { copyObject } = require('src/utils/index.js')
|
||||||
|
|
||||||
const controller = {}
|
const controller = {}
|
||||||
module.exports = controller
|
module.exports = controller
|
||||||
@ -34,6 +35,12 @@ controller.verifyCode = () => async (ctx) => {
|
|||||||
try {
|
try {
|
||||||
const token = await sso.getToken(code, sessionState)
|
const token = await sso.getToken(code, sessionState)
|
||||||
|
|
||||||
|
if (!acl.checkAllow(token.groups)) {
|
||||||
|
const copy = copyObject(resp.Forbidden)
|
||||||
|
copy.object = codeMessage.CodeAccountNoPermission
|
||||||
|
throw new APIError('account no permission', copy)
|
||||||
|
}
|
||||||
|
|
||||||
// set accessToken/refreshToken cache
|
// set accessToken/refreshToken cache
|
||||||
cache.set(token.access_token, token.refresh_token, false)
|
cache.set(token.access_token, token.refresh_token, false)
|
||||||
|
|
||||||
|
@ -27,16 +27,6 @@ r.get(
|
|||||||
accCtrl.loginSSO()
|
accCtrl.loginSSO()
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
|
||||||
* account refresh token
|
|
||||||
* @swagger
|
|
||||||
* @route POST /api/refresh
|
|
||||||
* @group account - account apis
|
|
||||||
* @security JWT
|
|
||||||
* @returns {RespDefault.model} default -
|
|
||||||
*/
|
|
||||||
r.post('/refresh', commonCtrl.authorization(true), accCtrl.logout())
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* account logout
|
* account logout
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -45,7 +35,7 @@ r.post('/refresh', commonCtrl.authorization(true), accCtrl.logout())
|
|||||||
* @security JWT
|
* @security JWT
|
||||||
* @returns {RespDefault.model} default -
|
* @returns {RespDefault.model} default -
|
||||||
*/
|
*/
|
||||||
r.post('/logout', commonCtrl.authorization(false), accCtrl.logout())
|
r.post('/logout', commonCtrl.authorization(), accCtrl.logout())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* account get info
|
* account get info
|
||||||
@ -55,4 +45,4 @@ r.post('/logout', commonCtrl.authorization(false), accCtrl.logout())
|
|||||||
* @security JWT
|
* @security JWT
|
||||||
* @returns {RespDefault.model} default -
|
* @returns {RespDefault.model} default -
|
||||||
*/
|
*/
|
||||||
r.get('/userinfo', commonCtrl.authorization(false), accCtrl.getInfo())
|
r.get('/userinfo', commonCtrl.authorization(), accCtrl.getInfo())
|
||||||
|
10
utils/acl.js
Normal file
10
utils/acl.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const ALLOW_GROUPS = new Set(['/professorx'])
|
||||||
|
|
||||||
|
const mod = {}
|
||||||
|
module.exports = mod
|
||||||
|
|
||||||
|
mod.checkAllow = groups => {
|
||||||
|
if (!Array.isArray(groups)) return false
|
||||||
|
|
||||||
|
return groups.filter(t => ALLOW_GROUPS.has(t)).length > 0
|
||||||
|
}
|
@ -57,7 +57,8 @@ mod.codeMessage = {
|
|||||||
CodeUnauthorized: { code: 1004, message: 'unauthorized' },
|
CodeUnauthorized: { code: 1004, message: 'unauthorized' },
|
||||||
CodeForbidden: { code: 1005, message: 'forbidden' },
|
CodeForbidden: { code: 1005, message: 'forbidden' },
|
||||||
CodeNotFound: { code: 1006, message: 'not found' },
|
CodeNotFound: { code: 1006, message: 'not found' },
|
||||||
CodeInternalError: { code: 1007, message: 'internal error' }
|
CodeInternalError: { code: 1007, message: 'internal error' },
|
||||||
|
CodeAccountNoPermission: { code: 1008, message: 'account no permission' }
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.resp = {
|
mod.resp = {
|
||||||
|
Loading…
Reference in New Issue
Block a user