feat: Added authentication sstem with discord
This commit is contained in:
@@ -1,5 +1,93 @@
|
||||
import jwt from 'jsonwebtoken'
|
||||
|
||||
type AccessTokenResponse = {
|
||||
access_token: string,
|
||||
token_type: string,
|
||||
expires_in: number,
|
||||
refresh_token: string,
|
||||
scope: string
|
||||
}
|
||||
|
||||
type DiscordUser = {
|
||||
id: string,
|
||||
username: string,
|
||||
discriminator: string,
|
||||
avatar: string,
|
||||
bot?: boolean,
|
||||
system?: boolean,
|
||||
mfa_enabled?: boolean,
|
||||
banner?: string,
|
||||
accent_color?: number,
|
||||
locale?: string,
|
||||
verified?: boolean,
|
||||
email?: string,
|
||||
flags?: number,
|
||||
premium_type?: number,
|
||||
public_flags?: number
|
||||
}
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
return {
|
||||
hello: 'world'
|
||||
const { code }: { code?: string } = getQuery(event)
|
||||
|
||||
if (!code) {
|
||||
return sendRedirect(event, '/', 302)
|
||||
}
|
||||
|
||||
let tokenResponse: AccessTokenResponse
|
||||
let authorizationResponse: DiscordUser
|
||||
try {
|
||||
tokenResponse = await $fetch('https://discord.com/api/oauth2/token', {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams({
|
||||
client_id: config.discordClientId,
|
||||
client_secret: config.discordClientSecret,
|
||||
code,
|
||||
grant_type: 'authorization_code',
|
||||
redirect_uri: config.oauthRedirectUri,
|
||||
scope: 'identify'
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
})
|
||||
|
||||
authorizationResponse = await $fetch('https://discord.com/api/users/@me', {
|
||||
headers: {
|
||||
authorization: `Bearer ${tokenResponse.access_token}`
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('Discord authentication failed', e)
|
||||
|
||||
throw createError({ statusCode: 500, statusMessage: 'Discord authentication failed' })
|
||||
}
|
||||
|
||||
try {
|
||||
await UserModel.updateOne({ 'discord.id': authorizationResponse.id }, {
|
||||
$set: {
|
||||
discord: {
|
||||
id: authorizationResponse.id,
|
||||
username: authorizationResponse.username,
|
||||
avatarHash: authorizationResponse.avatar
|
||||
}
|
||||
},
|
||||
$setOnInsert: {
|
||||
username: authorizationResponse.username
|
||||
}
|
||||
}, { upsert: true })
|
||||
|
||||
const token = jwt.sign({
|
||||
accessToken: tokenResponse.access_token,
|
||||
refreshToken: tokenResponse.refresh_token,
|
||||
discordId: authorizationResponse.id
|
||||
}, config.jwtSecret, { expiresIn: tokenResponse.expires_in })
|
||||
|
||||
setCookie(event, 'jwt', token, { httpOnly: true, maxAge: tokenResponse.expires_in * 1000 })
|
||||
} catch (e) {
|
||||
console.error('Updating user information failed', e)
|
||||
|
||||
throw createError({ statusCode: 500, statusMessage: 'Updating user information failed' })
|
||||
}
|
||||
|
||||
return sendRedirect(event, '/', 302)
|
||||
})
|
||||
|
14
webv2/server/index.ts
Normal file
14
webv2/server/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import mongoose from 'mongoose'
|
||||
|
||||
export default async () => {
|
||||
try {
|
||||
await mongoose.connect(config.mongoUrl, {
|
||||
authSource: 'admin',
|
||||
user: config.mongoUser,
|
||||
pass: config.mongoPass
|
||||
})
|
||||
console.log('DB connection established')
|
||||
} catch (e) {
|
||||
console.error('DB connection failed', e)
|
||||
}
|
||||
}
|
1
webv2/server/utils/config.ts
Normal file
1
webv2/server/utils/config.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const config = useRuntimeConfig()
|
24
webv2/server/utils/models.ts
Normal file
24
webv2/server/utils/models.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Schema, Types, model } from 'mongoose'
|
||||
|
||||
const userSchema = new Schema({
|
||||
username: { type: String, required: true },
|
||||
usernameType: { type: String, required: true, default: 'discord' },
|
||||
discord: {
|
||||
id: { type: String, required: true, unique: true },
|
||||
username: { type: String, required: true }
|
||||
},
|
||||
minecraft: {
|
||||
uuid: { type: String, required: false, unique: true },
|
||||
username: { type: String, required: false }
|
||||
},
|
||||
role: {
|
||||
admin: Boolean,
|
||||
moderator: Boolean,
|
||||
teamAdmin: Boolean
|
||||
},
|
||||
teamInvites: [
|
||||
Types.ObjectId
|
||||
]
|
||||
})
|
||||
|
||||
export const UserModel = model<IUser>('User', userSchema)
|
Reference in New Issue
Block a user