From fe5fd79d85c59ce7665c1d45b72318ef1b788f29 Mon Sep 17 00:00:00 2001 From: smanylov Date: Wed, 7 Jan 2026 18:13:53 +0700 Subject: [PATCH] change codeVerifier on codeChallenge --- .env | 2 +- package.json | 2 +- src/app/actions/vkAuth.ts | 7 +- src/app/components/VKLogin.tsx | 116 +++++++++++++++++++++++++-------- 4 files changed, 94 insertions(+), 33 deletions(-) diff --git a/.env b/.env index 940d91b..00cd124 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ SESSION_SECRET=odW+sq1yKte/gMgUUu/B/OyXqr45/LMYplPVOlWc+uo= -DEV_URL=http://localhost \ No newline at end of file +DEV_URL=http://localhost:81 \ No newline at end of file diff --git a/package.json b/package.json index 99b0bd2..746d412 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.12.0", "private": true, "scripts": { - "dev": "next dev -p 2999", + "dev": "next dev -p 80", "build": "next build", "start": "next start -p 2999", "lint": "eslint" diff --git a/src/app/actions/vkAuth.ts b/src/app/actions/vkAuth.ts index 32d35aa..ed41a2e 100644 --- a/src/app/actions/vkAuth.ts +++ b/src/app/actions/vkAuth.ts @@ -5,14 +5,14 @@ import { createSession } from '@/app/actions/session'; import { redirect } from 'next/navigation'; -export async function vkAuthorization(data : any, codeVerifier: string) { +export async function vkAuthorization(data : any, codeChallenge: string) { console.log(data); - console.log(codeVerifier); + console.log(codeChallenge); const { code, state, device_id } = data try { - const response = await fetch(`${API_BASE_URL}/api/v1/vk/authorization/${code}/${state}/${codeVerifier}/${device_id}`, { + const response = await fetch(`${API_BASE_URL}/api/v1/vk/authorization/${code}/${state}/${codeChallenge}/${device_id}`, { method: 'GET', headers: { "Content-Type": "application/json", @@ -21,6 +21,7 @@ export async function vkAuthorization(data : any, codeVerifier: string) { }); if (response.ok) { let parsed = await response.json(); + console.log(parsed); if (parsed.message_desc === 'Operation successful') { /* await createSession(parsed.message_body.token, email); */ } else { diff --git a/src/app/components/VKLogin.tsx b/src/app/components/VKLogin.tsx index acfd398..6fef6c9 100644 --- a/src/app/components/VKLogin.tsx +++ b/src/app/components/VKLogin.tsx @@ -1,15 +1,14 @@ 'use client' -import { useEffect, useRef, useState } from 'react'; +import { useEffect, useState } from 'react'; import * as VKID from '@vkid/sdk'; import { vkAuthorization } from '@/app/actions/vkAuth'; export default function VKLogin() { - let [codeVerifier, setCodeVerifier] = useState(''); + const [codeVerifier, setCodeVerifier] = useState(''); + const [codeChallenge, setCodeChallenge] = useState(''); - const vkButton = useRef(null) - - function generateAuthString() { + async function generateAuthString() { const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-'; const minLength = 43; const maxLength = 128; @@ -26,36 +25,97 @@ export default function VKLogin() { return result; } - - function clickHandler() { - /* alert('Кнопка пока не подключена к бизнес аккаунту!'); */ - console.log('clickHandler'); - console.log(codeVerifier); - VKID.Auth.login() - .then(vkidOnSuccess) - .catch(console.error); + async function generateCodeChallenge(codeVerifier: string) { + try { + const encoder = new TextEncoder(); + const data = encoder.encode(codeVerifier); + const digest = await crypto.subtle.digest('SHA-256', data); + const base64 = btoa(String.fromCharCode(...new Uint8Array(digest))); + const base64url = base64 + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=/g, ''); + return base64url; + } catch (error) { + console.error('Error generating code challenge:', error); + throw error; + } } - function vkidOnSuccess(data: any) { + + async function clickHandler() { + console.log('clickHandler'); + console.log('codeChallenge:', codeChallenge); + + try { + // Если codeVerifier пустой, генерируем новый + if (!codeVerifier) { + const newCodeVerifier = await generateAuthString(); + const newCodeChallenge = await generateCodeChallenge(newCodeVerifier); + + setCodeVerifier(newCodeVerifier); + setCodeChallenge(newCodeChallenge); + + // Обновляем конфигурацию VKID + VKID.Config.update({ + codeChallenge: newCodeChallenge + }); + } + + // Выполняем авторизацию + const data = await VKID.Auth.login(); + vkidOnSuccess(data); + } catch (error) { + console.error('Authorization error:', error); + } + } + + async function vkidOnSuccess(data: any) { console.log('vkidOnSuccess'); - console.log(data); - console.log(codeVerifier); - vkAuthorization(data, codeVerifier) - setCodeVerifier(generateAuthString()); + console.log('vk data:', data); + console.log('codeChallenge :', codeChallenge); + + vkAuthorization(data, codeChallenge); + + const newCodeVerifier = await generateAuthString(); + const newCodeChallenge = await generateCodeChallenge(newCodeVerifier); + + setCodeVerifier(newCodeVerifier); + setCodeChallenge(newCodeChallenge); + + VKID.Config.update({ + codeChallenge: newCodeChallenge + }); + + console.log('new codeChallenge:', newCodeChallenge); } useEffect(() => { - setCodeVerifier(generateAuthString()); - console.log(codeVerifier); + async function initVKID() { + try { + const newCodeVerifier = await generateAuthString(); + const newCodeChallenge = await generateCodeChallenge(newCodeVerifier); - VKID.Config.init({ - app: 54389559, - redirectUrl: 'http://localhost', - responseMode: VKID.ConfigResponseMode.Callback, - source: VKID.ConfigSource.LOWCODE, - scope: 'email phone vkid.personal_info', - codeVerifier: "codeVerifier" - }); + setCodeVerifier(newCodeVerifier); + setCodeChallenge(newCodeChallenge); + + VKID.Config.init({ + app: 54389559, + redirectUrl: 'http://localhost', + responseMode: VKID.ConfigResponseMode.Callback, + source: VKID.ConfigSource.LOWCODE, + scope: 'email phone vkid.personal_info', + codeChallenge: newCodeChallenge + }); + + console.log('Generated codeVerifier:', newCodeVerifier); + console.log('Generated codeChallenge:', newCodeChallenge); + } catch (error) { + console.error('Error initializing VKID:', error); + } + } + + initVKID(); }, []); return (