mirror of
https://github.com/Hessenuk/DiscordTickets.git
synced 2025-09-06 10:11:27 +03:00
feat: separate user and admin auth, redirect to settings after invite
This commit is contained in:
@@ -1,7 +1,27 @@
|
||||
const { domain } = require('../../lib/http');
|
||||
|
||||
module.exports.get = () => ({
|
||||
handler: async function (req, res) { // MUST NOT use arrow function syntax
|
||||
handler: async function (req, res) {
|
||||
const cookie = req.cookies['oauth2-state'];
|
||||
if (!cookie) {
|
||||
return res.code(400).send({
|
||||
error: 'Bad Request',
|
||||
message: 'State is missing.',
|
||||
statusCode: 400,
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
const state = new URLSearchParams(cookie);
|
||||
if (state.get('secret') !== req.query.state) {
|
||||
return res.code(400).send({
|
||||
error: 'Bad Request',
|
||||
message: 'Invalid state.',
|
||||
statusCode: 400,
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: check if req.query.permissions are correct
|
||||
|
||||
const data = await (await fetch('https://discord.com/api/oauth2/token', {
|
||||
body: new URLSearchParams({
|
||||
client_id: req.routeOptions.config.client.user.id,
|
||||
@@ -14,22 +34,30 @@ module.exports.get = () => ({
|
||||
method: 'POST',
|
||||
})).json();
|
||||
|
||||
const user = await (await fetch('https://discordapp.com/api/users/@me', { headers: { 'Authorization': `Bearer ${data.access_token}` } })).json();
|
||||
const redirect = (data.guild?.id && `/settings/${data.guild?.id}`) || state.get('redirect') || '/';
|
||||
|
||||
const bearerOptions = { headers: { 'Authorization': `Bearer ${data.access_token}` } };
|
||||
const user = await (await fetch('https://discordapp.com/api/users/@me', bearerOptions)).json();
|
||||
|
||||
let scopes;
|
||||
if (data.scope) {
|
||||
scopes = data.scope.split(' ');
|
||||
} else {
|
||||
const auth = await (await fetch('https://discordapp.com/api/oauth2/@me', bearerOptions)).json();
|
||||
scopes = auth.scopes;
|
||||
}
|
||||
|
||||
const token = this.jwt.sign({
|
||||
accessToken: data.access_token,
|
||||
avatar: user.avatar,
|
||||
expiresAt: Date.now() + (data.expires_in * 1000),
|
||||
id: user.id,
|
||||
locale: user.locale,
|
||||
scopes,
|
||||
username: user.username,
|
||||
});
|
||||
|
||||
// note: if data.guild is present, guild_id and permissions should also be in req.query
|
||||
const redirect = this.states.get(req.query.state) || (data.guild?.id && `/settings/${data.guild?.id}`) || '/';
|
||||
this.states.delete(req.query.state);
|
||||
|
||||
res.setCookie('token', token, {
|
||||
domain,
|
||||
httpOnly: true,
|
||||
maxAge: data.expires_in,
|
||||
path: '/',
|
||||
|
44
src/routes/auth/login.js
Normal file
44
src/routes/auth/login.js
Normal file
@@ -0,0 +1,44 @@
|
||||
const { randomBytes } = require('crypto');
|
||||
|
||||
module.exports.get = () => ({
|
||||
handler: async function (req, res) {
|
||||
const { client } = req.routeOptions.config;
|
||||
|
||||
const state = new URLSearchParams({
|
||||
redirect: req.query.r ?? '',
|
||||
secret: randomBytes(8).toString('hex'),
|
||||
});
|
||||
|
||||
res.setCookie('oauth2-state', state.toString(), {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
});
|
||||
|
||||
const params = {
|
||||
client_id: client.user.id,
|
||||
// ? prompt: 'none',
|
||||
redirect_uri: `${process.env.HTTP_EXTERNAL}/auth/callback`, // if not set defaults to first allowed
|
||||
response_type: 'code',
|
||||
scope: 'guilds identify',
|
||||
state: state.get('secret'),
|
||||
};
|
||||
|
||||
if (req.query.invite !== undefined) {
|
||||
params.prompt = 'consent'; // already implied by the bot scope
|
||||
params.scope = 'applications.commands applications.commands.permissions.update bot ' + params.scope;
|
||||
params.integration_type = '0';
|
||||
params.permissions = '268561488';
|
||||
if (req.query.guild) {
|
||||
params.guild_id = req.query.guild;
|
||||
params.disable_guild_select = 'true';
|
||||
}
|
||||
} else if (req.query.role === 'admin') { // invite implies admin already
|
||||
params.scope = 'applications.commands.permissions.update ' + params.scope;
|
||||
}
|
||||
|
||||
const url = new URL('https://discord.com/oauth2/authorize');
|
||||
url.search = new URLSearchParams(params);
|
||||
|
||||
res.redirect(url.toString());
|
||||
},
|
||||
});
|
@@ -1,5 +1,3 @@
|
||||
const { domain } = require('../../lib/http');
|
||||
|
||||
module.exports.get = fastify => ({
|
||||
handler: async function (req, res) {
|
||||
const { accessToken } = req.user;
|
||||
@@ -15,7 +13,6 @@ module.exports.get = fastify => ({
|
||||
});
|
||||
|
||||
res.clearCookie('token', {
|
||||
domain,
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
sameSite: 'Strict',
|
||||
|
@@ -1,29 +1,5 @@
|
||||
const { randomBytes } = require('crypto');
|
||||
|
||||
module.exports.get = () => ({
|
||||
handler: async function (req, res) {
|
||||
const { client } = req.routeOptions.config;
|
||||
|
||||
const state = randomBytes(8).toString('hex');
|
||||
this.states.set(state, null);
|
||||
|
||||
const url = new URL('https://discord.com/oauth2/authorize');
|
||||
url.searchParams.set('response_type', 'code');
|
||||
url.searchParams.set('client_id', client.user.id);
|
||||
url.searchParams.set('prompt', 'none');
|
||||
url.searchParams.set('redirect_uri', `${process.env.HTTP_EXTERNAL}/auth/callback`); // window.location.origin
|
||||
url.searchParams.set('scope', 'applications.commands applications.commands.permissions.update bot guilds identify');
|
||||
url.searchParams.set('permissions', '268561488');
|
||||
|
||||
if (req.query.guild) {
|
||||
url.searchParams.set('guild_id', req.query.guild);
|
||||
url.searchParams.set('disable_guild_select', 'true');
|
||||
}
|
||||
|
||||
res.setCookie('oauth2-redirect-state', state, {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
});
|
||||
res.redirect(url.toString());
|
||||
res.redirect(`/auth/login?invite&guild=${req.query.guild || ''}`);
|
||||
},
|
||||
});
|
||||
|
Reference in New Issue
Block a user