diff --git a/server/src/routes/oauth-social.js b/server/src/routes/oauth-social.js index 8eeea59..9fae41b 100644 --- a/server/src/routes/oauth-social.js +++ b/server/src/routes/oauth-social.js @@ -94,6 +94,34 @@ export async function registerOAuthSocialRoutes(fastify) { return reply.redirect(url.toString()) }) + fastify.get('/api/auth/oauth/vk/link', { preHandler: [fastify.authenticate] }, async (request, reply) => { + const adminEmail = normalizeEmail(process.env.ADMIN_EMAIL) + if (request.user.email === adminEmail) { + return reply.code(403).send({ error: 'Администратор не может привязывать OAuth' }) + } + + const clientId = process.env.VK_CLIENT_ID + const clientSecret = process.env.VK_CLIENT_SECRET + if (!clientId || !clientSecret) return reply.code(503).send({ error: 'VK OAuth не настроен' }) + + const redirectUri = `${serverPublic}/api/auth/oauth/vk/callback` + const state = fastify.jwt.sign( + { oauth: 'vk', action: 'link', userId: request.user.sub }, + { expiresIn: '15m' }, + ) + + const url = new URL('https://oauth.vk.com/authorize') + url.searchParams.set('client_id', clientId) + url.searchParams.set('display', 'page') + url.searchParams.set('redirect_uri', redirectUri) + url.searchParams.set('scope', 'email') + url.searchParams.set('response_type', 'code') + url.searchParams.set('v', '5.199') + url.searchParams.set('state', state) + + return reply.redirect(url.toString()) + }) + fastify.get('/api/auth/oauth/vk/callback', async (request, reply) => { const query = request.query ?? {} if (query.error || query.error_description) { @@ -174,6 +202,31 @@ export async function registerOAuthSocialRoutes(fastify) { return reply.redirect(url.toString()) }) + fastify.get('/api/auth/oauth/yandex/link', { preHandler: [fastify.authenticate] }, async (request, reply) => { + const adminEmail = normalizeEmail(process.env.ADMIN_EMAIL) + if (request.user.email === adminEmail) { + return reply.code(403).send({ error: 'Администратор не может привязывать OAuth' }) + } + + const clientId = process.env.YANDEX_CLIENT_ID + if (!clientId) return reply.code(503).send({ error: 'Yandex OAuth не настроен' }) + + const redirectUri = `${serverPublic}/api/auth/oauth/yandex/callback` + const state = fastify.jwt.sign( + { oauth: 'yandex', action: 'link', userId: request.user.sub }, + { expiresIn: '15m' }, + ) + + const url = new URL('https://oauth.yandex.ru/authorize') + url.searchParams.set('response_type', 'code') + url.searchParams.set('client_id', clientId) + url.searchParams.set('redirect_uri', redirectUri) + url.searchParams.set('scope', 'login:email') + url.searchParams.set('state', state) + + return reply.redirect(url.toString()) + }) + fastify.get('/api/auth/oauth/yandex/callback', async (request, reply) => { const query = request.query ?? {} if (query.error) return oauthErrorRedirect(reply, String(query.error))