'use strict'; // const sha256 = require("crypto-js/sha256"); module.exports = () => { class Model { constructor(ctx) { this.ctx = ctx; this.fileName = "oauth"; this.redisType = { "B": "db0", "C": "db1", "M": "db2", "T": "db5", "E": "db6", "A": "db7" }; this.modelType = { "B": this.ctx.model.BSide, "C": this.ctx.model2.CSide, "M": this.ctx.model3.Insiders, "T": this.ctx.model4.Account, "E": this.ctx.model5.Examinee, "A": this.ctx.model5.Manager, }; this.redisAccessTokenEX = { "B": 1000, "C": 1000, "M": 1000, "T": 1000, "E": 3000, "A": 1000 }; this.redisRefreshTokenEX = { "B": 1000, "C": 1000, "M": 1000, "T": 1000, "E": 360000, "A": 1000 }; } async getClient(clientId) { // let clientSecret = this.ctx.request.body.client_secret; try { // 1. 从数据库中查询客户端信息 // if(clientId == "insiders-manager" && clientSecret == "insiders-manager") { let checkFixedClient = false; this.ctx.app.config.fixedClient.forEach(element => { if (clientId == element) checkFixedClient = true; }); if (checkFixedClient) { return { id: clientId, redirectUris: 'http://127.0.0.1:'+this.ctx.app.server.address().port+'/getToken/', grants: ['authorization_code'], type: clientId, }; } else { const client = await this.ctx.model3.Business.findOne({ where: { client_id: clientId } }); if (!client) return false; // 2. 校验客户端密钥 // if (clientSecret && (clientSecret !== client.client_secret)) { // return false; // } // 3. 返回数据 return { id: client.client_id, redirectUris: 'http://127.0.0.1:'+this.ctx.app.server.address().port+'/getToken/', grants: ['authorization_code'], type: client.type, }; } } catch (error) { const blockName = this.fileName + "--" + "getClient"; this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error); return false; } } async grantTypeAllowed (clientId, grantType) { try { const client = await this.ctx.model.Oauth2.findOne({ where: { clientId: clientId } }); if(clientId == client.clientId && grantType == client.grants.split(',')){ return true; }else{ return false; } } catch (error) { const blockName = this.fileName + "--" + "grantTypeAllowed"; this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error); return false; } } async getUser(username, password) { try { // 返回用户信息 return { uid: username, }; } catch (error) { const blockName = this.fileName + "--" + "getUser"; this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error); return false; } } async getUserFromClient (clientId) { try { return { uid:clientId.id }; } catch (error) { const blockName = this.fileName + "--" + "getUserFromClient"; this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error); return false; } }; async saveToken(token, client, user) { try { const rdmtoken = { accessToken: token.accessToken, refreshToken: token.refreshToken, clientId: client.id, }; const lastCode = user.uid[user.uid.length-1]; const redisDbType = this.redisType[lastCode]; const redisAccessTokenEX = this.redisAccessTokenEX[lastCode]; const redisRefreshTokenEX = this.redisRefreshTokenEX[lastCode]; let reex = ((new Date(token.refreshTokenExpiresAt).getTime() - new Date().getTime()) / redisRefreshTokenEX).toFixed(0); const usertoken = await this.ctx.app.redis.get(redisDbType).get(user.uid); if(usertoken){ await this.ctx.app.redis.get(redisDbType).del(JSON.parse(usertoken).accessToken); let remainder = await this.ctx.app.redis.get(redisDbType).ttl(user.uid); reex = remainder; await this.ctx.app.redis.get(redisDbType).del(JSON.parse(usertoken).refreshToken); } await this.ctx.app.redis.get(redisDbType).set(user.uid, JSON.stringify(rdmtoken), 'EX', reex); // 1.保存访问令牌 const rdmaccess = { token: token.accessToken, expiresAt: token.accessTokenExpiresAt, scope: token.scope || '', clientId: client.id, clientType: client.type, uid: user.uid, }; let acex = ((new Date(token.accessTokenExpiresAt).getTime() - new Date().getTime()) / redisAccessTokenEX).toFixed(0); await this.ctx.app.redis.get(redisDbType).set(token.accessToken, JSON.stringify(rdmaccess), 'EX', acex); // 2.保存刷新令牌 if(token.refreshToken){ const rdmrefresh = { token: token.refreshToken, expiresAt: token.refreshTokenExpiresAt, scope: token.scope || '', clientId: client.id, clientType: client.type, uid: user.uid, }; await this.ctx.app.redis.get(redisDbType).set(token.refreshToken, JSON.stringify(rdmrefresh), 'EX', reex); } // 3.返回保存的令牌信息 return { accessToken: { uid: user.uid, token:token.accessToken }, accessTokenExpiresAt: token.accessTokenExpiresAt, refreshToken: token.refreshToken ? token.refreshToken : '', refreshTokenExpiresAt: token.refreshTokenExpiresAt ? token.refreshTokenExpiresAt : '', scope: token.scope || '', client: { id: client.id, type: client.type }, user: { uid: user.uid }, }; } catch (error) { const blockName = this.fileName + "--" + "saveToken"; this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error); return false; } } async getAccessToken(bearerToken) { try { // 1. 查询数据库,获取访问密钥信息 // 2. 查询数据库,获取客户端信息 // 3. 查询数据库,获取用户信息 let { access_token, uid } = JSON.parse(bearerToken); const lastCode = uid[uid.length-1]; const redisDbType = this.redisType[lastCode]; const token = await this.ctx.app.redis.get(redisDbType).get(access_token); if (token == null) { const data = await this.ctx.app.redis.get(redisDbType).get(uid); const refreshToken = await this.ctx.app.redis.get(redisDbType).get(JSON.parse(data).refreshToken); if (refreshToken == null) await this.ctx.app.redis.get(redisDbType).del(uid); }; // 4. 返回数据 let accessToken = { accessTokenExpiresAt: new Date(JSON.parse(token).expiresAt), user: { uid: JSON.parse(token).uid }, client_type: JSON.parse(token).clientType, } return accessToken; } catch (error) { const blockName = this.fileName + "--" + "getAccessToken"; this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error); return false; } } async revokeToken(token) { try { // 查询数据库并删除刷新令牌 const revokeValue = await this.ctx.app.redis.del(token.refreshToken); if(revokeValue){ return true; }else{ return false; } } catch (error) { const blockName = this.fileName + "--" + "revokeToken"; this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error); return false; } } async saveAuthorizationCode(code, client, user) { try { // 1. 保存授权码信息到数据库 const rdmcode = { code: code.authorizationCode, expiresAt: code.expiresAt, redirectUri: code.redirectUri, scope: code.scope || '', clientId: client.id, clientType: client.type, uid: user.uid } let ex = ((new Date(code.expiresAt).getTime() - new Date().getTime()) / 1000).toFixed(0); await this.ctx.app.redis.get('db3').set(code.authorizationCode, JSON.stringify(rdmcode), 'EX', ex); // 2. 返回数据 return { authorizationCode: code.authorizationCode, expiresAt: code.expiresAt, redirectUri: code.redirectUri, scope: code.scope || '', client: { id: client.id }, user: { uid: user.uid }, }; } catch (error) { const blockName = this.fileName + "--" + "saveAuthorizationCode"; this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error); return false; } } async getAuthorizationCode(authorizationCode) { try { // 1. 从数据库中查询授权码信息 const { code, type } = JSON.parse(authorizationCode); const lastCode = type[type.length - 1]; const redisDbType = this.redisType[lastCode]; let rdmcode; if(type == 'code') { rdmcode = await this.ctx.app.redis.get('db3').get(code); } else { rdmcode = await this.ctx.app.redis.get(redisDbType).get(code); } if (!rdmcode) return false; // 2. 从数据库中查询客户端信息、用户信息 const cloneRdmcode = JSON.parse(rdmcode); const cloneLastCode = cloneRdmcode.uid[cloneRdmcode.uid.length-1]; const modelDbType = this.modelType[cloneLastCode]; const user = await modelDbType.findOne({ where: { uid: cloneRdmcode.uid } }); if (!user) return false; // 3. 返回数据 return { code: authorizationCode, expiresAt: new Date(cloneRdmcode.expiresAt), redirectUri: cloneRdmcode.redirectUri, scope: cloneRdmcode.scope, client: { id: cloneRdmcode.clientId }, user: { uid: cloneRdmcode.uid }, }; } catch (error) { const blockName = this.fileName + "--" + "getAuthorizationCode"; this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error); return false; } } async revokeAuthorizationCode(authorizationCode) { try { // 从数据库中查询该授权码并删除 const { code, type } = JSON.parse(authorizationCode.code); const lastCode = type[type.length - 1]; const redisDbType = this.redisType[lastCode]; let revokeValue; if(type == 'code') { revokeValue = await this.ctx.app.redis.get('db3').del(code); } else { revokeValue = await this.ctx.app.redis.get(redisDbType).del(code); } if(revokeValue){ return true; }else{ return false; } } catch (error) { const blockName = this.fileName + "--" + "revokeAuthorizationCode"; this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error); return false; } } async getRefreshToken(refreshToken) { try { // 1. 查询数据库获取刷新令牌 const rdmrefresh = await this.ctx.app.redis.get(refreshToken); if (!rdmrefresh) return false; // 2. 返回数据 return { refreshToken: JSON.parse(rdmrefresh).token, refreshTokenExpiresAt: new Date(JSON.parse(rdmrefresh).expiresAt), scope: JSON.parse(rdmrefresh).scope, client: { id: JSON.parse(rdmrefresh).clientId }, user: { uid: JSON.parse(rdmrefresh).uid }, }; } catch (error) { const blockName = this.fileName + "--" + "getRefreshToken"; this.ctx.app.middleware.log('../../oauthLog', blockName + ">>>>" + error); return false; } } } return Model; };