google

Nowa tożsamość Google w Nuxt 3

Nowa instalacja Google Identity dla Nuxt 3 z weryfikacją poświadczeń w fastify.

Daniel Gustaw

Daniel Gustaw

7 min read

Nowa tożsamość Google w Nuxt 3

Dzisiaj się przestraszyłem, ponieważ dwie świetne biblioteki nie działały z Google Sign In dla Nuxt 3. Mam na myśli auth.nuxtjs i nuxt-vue3-google-signin.

Z Stack Overflow

Jak używać modułu nuxtjs/auth-next z Nuxt3?

Dowiedziałem się, że pierwsza jest niekompatybilna z nuxt 3, ale jest to zaplanowane w roadmapie.

Roadmap · Nuxt

Druga po prostu nie mogła działać, wyświetlając błąd, który sugerował, że coś jest nie tak z moim identyfikatorem klienta.

Sprawdziłem oficjalna dokumentację Google i zobaczyłem to:

Integracja logowania Google do twojej aplikacji internetowej | Uwierzytelnianie | Google Developers](https://developers.google.com/identity/sign-in/web/sign-in)

Wygląda strasznie, ale na szczęście szybko zintegrowałem przycisk logowania Google bez użycia zewnętrznych bibliotek. W tym artykule pokażę, jak zaimplementować nową tożsamość Google w Nuxt 3.

Tożsamość Google - jak się różni

Ponieważ obraz jest wart więcej niż tysiąc słów, nowy przycisk logowania zawiera awatar:

Przycisk Zaloguj się za pomocą Google UX | Uwierzytelnianie | Google Developers

Przycisk Zaloguj się HTML

Aby dodać go do swojego komponentu, będziesz musiał wkleić poniższy kod HTML

  <div id="g_id_onload"
       :data-client_id="config.public.googleClientId"
       data-context="signin"
       data-ux_mode="popup"
       data-callback="googleLoginCallback"
       data-auto_select="true"
       data-itp_support="true">
  </div>

  <div class="g_id_signin"
       data-type="standard"
       data-shape="pill"
       data-theme="outline"
       data-text="continue_with"
       data-size="large"
       data-logo_alignment="left">
  </div>

lub przygotuj swój własny w konfiguratorze

Generuj kod HTML | Uwierzytelnianie | Google Developers

Są trzy elementy, które musimy połączyć:

  1. config.public.googleClientId - identyfikator klienta Google
  2. googleLoginCallback - globalnie zdefiniowana funkcja, która uzyska wyniki logowania
  3. biblioteka google, która sprawi, że te przyciski będą działać

Przekazywanie .env do Nuxt 3

Aby przekazać .env do nuxt 3, możesz postępować zgodnie z tym rozwiązaniem

Jak przekazać zmienne środowiskowe do nuxt w produkcji?

Tworzysz plik .env z

GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com

aby połączyć te wartości, możesz użyć biblioteki dotenv, ale wolę Makefile taki jak ten

include .env
export

node_modules: package.json
	npm i

up: node_modules
	npm run dev

W konfiguracji nuxt należy dodać

export default defineNuxtConfig({
    runtimeConfig: {
        public: {
            googleClientId: process.env.GOOGLE_CLIENT_ID ?? '',
        }
    },
})

a na końcu w komponencie możesz uzyskać dostęp do config poprzez

const config = useRuntimeConfig()

Rozszerzanie obiektu window za pomocą funkcji zwrotnej

Obiekt window domyślnie nie ma googleLoginCallback, więc aby go dodać, należy stworzyć plik types/global.d.ts z

declare global {
    interface Window {
        googleLoginCallback: () => void;
    }
}

i w komponencie dodaj

if(process.client) {
  window.googleLoginCallback = (...args) => {
    console.log(args);
  }
}

Załaduj bibliotekę klienta w Nuxt 3

Google wspomina o tym kroku na stronie

Załaduj bibliotekę klienta | Uwierzytelnianie | Google Developers

Ale nie powinieneś dodawać

<script src="https://accounts.google.com/gsi/client" async defer></script>

w nuxt3 zamiast używać tego kodu w swoim komponencie:

useHead({
  script: [{
    async: true,
    src: 'https://accounts.google.com/gsi/client',
    defer: true
  }]
})

Teraz powinieneś zobaczyć przycisk logowania. Powinieneś móc kliknąć go, zalogować się i zobaczyć dane uwierzytelniające w konsoli. Zakładając, że prawidłowo skonfigurowałeś klienta OAuth 2.0.

I dodano localhost do Autoryzowanych pochodzeń JavaScript

Po zalogowaniu się w konsoli zobaczysz tablicę z pojedynczym obiektem, tak jak to:

{
  clientId:"xxx.apps.googleusercontent.com"
  client_id:"xxx.apps.googleusercontent.com"
  credential: "token"
  select_by:"auto"
}

Token uwierzytelniający to JWT z ładunkiem.

{
  "iss": "https://accounts.google.com",
  "nbf": 1676544985,
  "aud": "xxx.apps.googleusercontent.com",
  "sub": "108561822785941523583",
  "email": "[email protected]",
  "email_verified": true,
  "azp": "xxx.apps.googleusercontent.com",
  "name": "Daniel Gustaw",
  "picture": "https://lh3.googleusercontent.com/a/AEdFTp64X-0imH5xey6U4JDKzFRrMXdtg4lGy8GlEjLxyQ=s96-c",
  "given_name": "Daniel",
  "family_name": "Gustaw",
  "iat": 1676545285,
  "exp": 1676548885,
  "jti": "a7e1afd716925de385bf0069c7c370f8e64580d3"
}

Aby to zweryfikować, powinieneś wysłać to do backendu.

Weryfikacja backendu dla poświadczeń Google

Jako backend możemy użyć fastify. Opisałem konfigurację fastify w tym blogu tutaj

Logowanie przez Metamask - Backend Rest w Fastify (Node, Typescript, Prisma)

zakładam, że wykonałeś krok „Dodaj Fastify z pierwszym punktem końcowym” z tego artykułu.

W fastify.ts możemy dodać linię z ścieżką

app.post('/google-verify', Auth.googleVerify)

i w routes/Auth.ts zdefiniuj statyczną funkcję googleVerify.

W googleVerify będziemy sprawdzać, czy dane uwierzytelniające zostały poprawnie utworzone przez google.

Sprawdzanie autentyczności danych uwierzytelniających

Aby zweryfikować, musimy zainstalować pakiet google na backendzie zgodnie z instrukcją

Zweryfikuj token identyfikacyjny Google po stronie serwera | Uwierzytelnianie | Google Developers

npm install google-auth-library --save

potrzebujemy tego samego GOOGLE_CLIENT_ID w backendowym .env

GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com

w pliku z kontrolerem - routes/Auth.ts możemy napisać naszą funkcję jako

import {FastifyRequest} from "fastify";
import {OAuth2Client} from 'google-auth-library';

export class Auth {
  static async googleVerify(req: FastifyRequest<{ Body: { credential: string } }>) {
    const client = new OAuth2Client(process.env.GOOGLE_CLIENT_ID);
    const ticket = await client.verifyIdToken({
      idToken: req.body.credential,
      audience: process.env.GOOGLE_CLIENT_ID,
    });
    const payload = ticket.getPayload();
    if(!payload) throw new Error(`No payload`);

    console.log(payload);
    return payload;
  }
}

a teraz zaktualizuj część frontendową. Najpierw global.d.ts

interface GoogleAuthenticatedResponse {
    clientId: string
    client_id: string
    credential: string
    select_by: "auto"
}

declare global {
    interface Window {
        googleLoginCallback: (userData: GoogleAuthenticatedResponse) => void;
    }
}

następnie dodaj API_URL do .env, a następnie dodaj apiUrl do runtimeConfig tak jak googleClientId, na koniec możemy napisać funkcję zwrotną w komponencie nuxt3 w formie:

if(process.client) {
  window.googleLoginCallback = (userData) => {
    console.log("ud", userData);
    axios.post(config.public.apiUrl + '/google-verify', {
      credential: userData.credential
    }).then((res) => {
      console.log("pl", res.data)
    }).catch(console.error)
  }
}

Włącz CORS w Fastify

zapomnieliśmy o cors

więc szybka poprawka

npm i @fastify/cors

i w src/fastify.ts

import cors from '@fastify/cors'

//...

    app.register(cors)

i możemy zobaczyć w konsoli wszystkie szczegóły użytkownika

Nie chcemy wywoływać await client.verifyIdToken( przy żadnym żądaniu, więc musimy wymienić token JWT Google na nasz własny, dlatego warto utworzyć użytkownika w swojej bazie danych i wygenerować dla niego token JWT, ale opisałem to w wcześniej wspomnianym artykule:

Logowanie przez Metamask - Backend Rest w Fastify (Node, Typescript, Prisma)

Other articles

You can find interesting also.