@Vocler

Как должна работать интеграция VK ID в SPA в описанном случае?

Пытаясь интегрировать вход по VK ID в своё приложение затупил на казалось бы очевидном действии.

У меня есть SPA приложение (здесь и далее - фронтенд).
Есть серверное приложение (здесь и далее - бекенд).

Сейчас аутентификация реализована следующим образом: после того как пользователь вводит в форму свои данные и нажимает кнопку "Login" SPA из JS кода (при помощи fetch()) отправляет эту информацию на эндпоинт бекенда и получает в ответ Bearer token. Далее SPA добавляет этот токен в хедер каждого запроса.

Я хочу интегрировать VK ID в своё приложение что-бы пользователи могли входить в него через ВК.

Судя по доке VK ID работает следующим образом:

1. Я создаю в VK своё приложение, указываю там домен моего сайта и Redirect URI для переадресации после успешного логина.
Допустим в моём случае это mysite.com/redirect
2. Я подключаю JS-библиотеку с VK ID и указываю где отрендерить кнопку "Войти через ВК"
3. Пользователь кликает на кнопку и его переадресовывает на страницу логина ВК.
4. Он вводит свои данные и если они верные ВК переадресовывает его на Redirect URI (mysite.com/redirect) с silent token в GET параметрах.
5. Бекенд принимает коннект на Redirect URI, использует silent token для получения access token, производит необходимые манипуляции с таблицей пользователей (В контексте вопроса это не особо важно) и... Что дальше? Что должен возвращать mysite.com/redirect пользователю?

Вопрос глупый, но раньше при разработке SPA я всегда отправлял запрос аутентификации из JS скриптов и никуда пользователя не редиректил, поэтому не знаю как будет поступить правильно в моём случае.

Диаграмма запросов что-бы было проще понять о чём я говорю:
sequenceDiagram
    User->>+mysite.com: GET mysite.com/auth (запрашивает страницу логина);
    mysite.com-->>-User: 200 OK (возвращает страницу логина где есть кнопка "Войти через VK ID");
    User->>+id.vk.com: GET id.vk.com (Пользователь нажимает на кнопку и открывает страницу логина VK ID);
    id.vk.com-->>-User: 200 OK (ВК возвращает страницу с формой логина)
    User->>+id.vk.com: POST id.vk.com (пользователь логинится);
    id.vk.com-->>-User: 301 mysite.com/redirect (ВК редиректит на страницу моего сайта которую я указал для редиректа)
    User->>+mysite.com: GET mysite.com/redirect (Браузер пользователя автоматически переходит на эту страницу);
    mysite.com-->>-User: ??? Что отдавать пользователю?;

65e26a8c09864616790965.png
  • Вопрос задан
  • 72 просмотра
Решения вопроса 1
vabka
@vabka
Токсичный шарпист

Что должен возвращать mysite.com/redirect пользователю?

Тот же самый токен, который бы твой сайт вернул при обычной аутентификации и отправить пользователя дальше
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
nykakdelishki
@nykakdelishki
Системный аналитик
Еще как вариант редиректить пользователя с QUERY параметром

Наипростейшая реализация на GO

func YandexRedirectHandler(w http.ResponseWriter, r *http.Request) {
	url := configs.OauthConfig.AuthCodeURL("state", oauth2.AccessTypeOffline)
	http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}

func YandexCallbackHandler(w http.ResponseWriter, r *http.Request) {
	code := r.FormValue("code")

	token, err := configs.OauthConfig.Exchange(r.Context(), code)
	if err != nil {
		http.Error(w, "Failed to exchange token", http.StatusInternalServerError)
		return
	}

	resp, err := http.Get("https://login.yandex.ru/info?format=json&oauth_token=" + token.AccessToken)
	if err != nil {
		http.Error(w, "Failed to get user info", http.StatusInternalServerError)
		return
	}
	defer resp.Body.Close()

	var userinfo struct {
		ID        string `json:"id"`
		FirstName string `json:"first_name"`
		LastName  string `json:"last_name"`
		Email     string `json:"default_email"`
	}

	err = json.NewDecoder(resp.Body).Decode(&userinfo)
	if err != nil {
		http.Error(w, "Failed to decode user info", http.StatusInternalServerError)
		return
	}

	// 1 означает яндекс
	userID := store.GetUserID(r.Context(), userinfo.ID, 1)

	println(userID)
	// Если не найден
	if userID == "" {
		// Register the user in the database
		err = store.CreateUser(r.Context(), userinfo.ID, userinfo.FirstName, userinfo.LastName, userinfo.Email, 1)
		if err != nil {
			http.Error(w, "Failed to register user", http.StatusInternalServerError)
			return
		}
	}

	// Генерация JWT токена
	tokenString, err := oauth.GenerateToken(userID)
	if err != nil {
		http.Error(w, "Failed to generate JWT token", http.StatusInternalServerError)
		return
	}

	http.Redirect(w, r, "http://localhost:3000/login?token="+tokenString, http.StatusTemporaryRedirect)
}


Ну положить токен в куки из QUERY на SPA думаю справишься
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы