---
# System prepended metadata

title: Google OAuth登入 + Nuxt3
tags: [vue.js, nuxt]

---

# 實作Google登入

## 1. 到 [Google Cloud API和服務](https://console.cloud.google.com/apis/dashboard) 建立OAuth憑證
![](https://hackmd.io/_uploads/HkuRY301p.png)
## 2. 記得加入使用憑證的網址
![](https://hackmd.io/_uploads/SkcR520Ja.png)
## 3. 安裝 `vue-google-login` 套件
* [套件詳細說明文件](https://devbaji.github.io/vue3-google-login/)

在終端機輸入：
```
npm install -D vue3-google-login
```
## 4. 在 `nuxt.config.ts` 內的 `runtimeConfig` 新增參數
```typescript
runtimeConfig: {
    public: {
      googleClientId:
        "你的google client id",
    },
},
```
![](https://hackmd.io/_uploads/HybmThCkp.png)

## 5. 建立`plugins/vue3-goolge-login.client.js`
![](https://hackmd.io/_uploads/Bkaoo3R1a.png)

`vue3-goolge-login.client.js` 內容如下：
```javascript
import vue3GoogleLogin from "vue3-google-login";

export default defineNuxtPlugin((nuxtApp) => {
  const runtimeConfig = useRuntimeConfig();
  const { googleClientId: GOOGLE_CLIENT_ID } = runtimeConfig.public;

  nuxtApp.vueApp.use(vue3GoogleLogin, {
    clientId: GOOGLE_CLIENT_ID,
  });
});

```
## 6. 使用套件
方式有很多種，可以 call function 或 使用 component。

### 使用component
```javascript
<template>
  <GoogleLogin :callback="callback"/>
</template>
<script setup>
const callback = (response) => {
  // This callback will be triggered when the user selects or login to
  // his Google account from the popup
  console.log("Handle the response", response)
}
</script>
```

### 使用 function
#### `googleAuthCodeLogin`
```javascript
<script setup>
import { googleAuthCodeLogin } from "vue3-google-login"
const login = () => {
  googleAuthCodeLogin().then((response) => {
    console.log("Handle the response", response)
  })
}
</script>

<template>
  <button @click="login">Login Using Google</button>
</template>
```
#### `googleTokenLogin`
```
<script setup>
import { googleTokenLogin } from "vue3-google-login"
const login = () => {
  googleTokenLogin().then((response) => {
    console.log("Handle the response", response)
  })
}
</script>

<template>
  <button @click="login">Login Using Google</button>
</template>
```
## 7. 驗證 或 獲取 user information
### 安裝 `accessToken.access_token`
```
npm install -D google-auth-library
```

### 驗證 `Access Token`
新增一個 Server API，只接受 **POST** 方法，在 Body 中夾帶 `accessToken` 發送至後端。

建立 `./server/api/auth/google.post.js`，內容如下：

```javascript
import { OAuth2Client } from 'google-auth-library'

export default defineEventHandler(async (event) => {
  const body = await readBody(event)
  const oauth2Client = new OAuth2Client()
  oauth2Client.setCredentials({ access_token: body.accessToken })

  const userInfo = await oauth2Client
    .request({
      url: 'https://www.googleapis.com/oauth2/v3/userinfo'
    })
    .then((response) => response.data)
    .catch(() => null)

  oauth2Client.revokeCredentials()

  if (!userInfo) {
    throw createError({
      statusCode: 400,
      statusMessage: 'Invalid token'
    })
  }

  return {
    id: userInfo.sub,
    name: userInfo.name,
    avatar: userInfo.picture,
    email: userInfo.email,
    emailVerified: userInfo.email_verified,
  }
})

```

調整元件內的登入流程。

```javascript
<script setup>
import { googleTokenLogin } from 'vue3-google-login'

const runtimeConfig = useRuntimeConfig()
const { googleClientId: GOOGLE_CLIENT_ID } = runtimeConfig.public

const userInfo = ref()

const handleGoogleLogin = async () => {
  const accessToken = await googleTokenLogin({
    clientId: GOOGLE_CLIENT_ID
  }).then((response) => response?.access_token)

  if (!accessToken) {
    return '登入失敗'
  }

  const { data } = await useFetch('/api/auth/google', {
    method: 'POST',
    body: {
      accessToken
    },
    initialCache: false
  })

  userInfo.value = data.value
}
</script>
```
## 參考資料
https://ithelp.ithome.com.tw/articles/10304148

https://dotblogs.com.tw/shadow/2018/07/05/152206