# 實作Google登入
## 1. 到 [Google Cloud API和服務](https://console.cloud.google.com/apis/dashboard) 建立OAuth憑證

## 2. 記得加入使用憑證的網址

## 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",
},
},
```

## 5. 建立`plugins/vue3-goolge-login.client.js`

`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