import * as PlayerModel from '../models/player.js' import { createHash } from 'crypto' import { generateToken, uuidToNoSymboUUID } from '../generator.js' export const authenticate = { method: 'POST', url: '/authserver/authenticate', schema: { body: { "type": "object", "properties": { "username": { "type": "string" }, "password": { "type": "string" }, "clientToken": { "type": "string" }, "requestUser": { "type": "boolean" }, "agent": { "type": "object", "properties": { "name": { "type": "string" }, "version": { "type": "integer" } } } } }, response: { 200: { "type": "object", "properties": { "accessToken": { "type": "string" }, "clientToken": { "type": "string" }, "availableProfiles": { "type": "array", "items": [{...PlayerModel.PlayerSeriliazationSchema}] }, "selectedProfile": PlayerModel.PlayerSeriliazationSchema, "user": PlayerModel.PlayerAccountSerializationSchema } } } }, preHandler: async function(req, rep) { this.conf.custom.overridePrehandler('/authserver/authenticate') }, handler: async function (req, rep) { let { username, password, clientToken, requestUser, agent } = req.body const player = await this.models.Player.findOne({ email: username, password: createHash('sha256').update(password).digest().toString('hex').toLowerCase() }) if(!player || !player.permissions.some((it) => { return it.node === 'login' && it.allowed && (it.duration === 0 || it.startDate + it.duration > Date.now()) })) { return await rep.code(401).send({ error: "Unauthorized", errorMessage: "用户名或密码错误", cause: "用户名或密码错误" }) } if(!clientToken) { clientToken = createHash('sha256').update( "" + Math.random() * 1.048596).digest().toString('hex') } const [token, key] = await generateToken(clientToken, requestUser, agent) this.log.info(`/authserver/authenticate > 为玩家 ${username} 生成令牌: ${token} | 随机 key = ${key}`) const account = { id: uuidToNoSymboUUID(player.uuid), properties: [ { preferredLanguage: "zh_CN" } ] } const textures = { timestamp: 0, profileId: uuidToNoSymboUUID(player.uuid), profileName: player.username, textures: { } } if(player.textures.skin && player.textures.skin != 0) { // Must be '!=' if this change to '!==' will never works textures.textures.SKIN = { url: player.textures.skin, metadata } } const profile = { uuid: uuidToNoSymboUUID(player.uuid), name: player.username, properties: [ { name: "texturs", value: Buffer.from(JSON.stringify(textures)).toString('base64') } ] } new this.models.Token({ uuid: player.uuid, token: token, expireDate: Date.now() + 1000 * 60 * 60 * 24 * 15, deadDate: Date.now() + 1000 * 60 * 60 * 24 * 30, state: 'alive' }).save() return await rep.send({ accessToken: token, clientToken: clientToken, availableProfiles: [ profile ], selectedProfile: profile, user: account }) } }