János
János

Reputation: 35116

Hot to get permission to retrieve event times from Google Calendar?

I have subscribed to a Google Calendar. I can see in the calendar the data, the events. But when I would download them via API, it gives me a permission denied error. Why?

Returned error message:

{
    "message": "Failed to fetch calendar data",
    "details": {
        "error": {
            "code": 403,
            "message": "Request had insufficient authentication scopes.",
            "errors": [
                {
                    "message": "Insufficient Permission",
                    "domain": "global",
                    "reason": "insufficientPermissions"
                }
            ],
            "status": "PERMISSION_DENIED",
            "details": [
                {
                    "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                    "reason": "ACCESS_TOKEN_SCOPE_INSUFFICIENT",
                    "domain": "googleapis.com",
                    "metadata": {
                        "method": "calendar.v3.Events.List",
                        "service": "calendar-json.googleapis.com"
                    }
                }
            ]
        }
    }
}

code with googleapis.com

import { NextApiRequest, NextApiResponse } from 'next'
import { connectToDatabase } from 'lib/connectToDatabase'
import { Db, ObjectId } from 'mongodb'
import jwt from 'jsonwebtoken'
import { getTeams } from 'services/getTeams'
import { AuthResponse, JwtPayload } from 'tikexModule/Types/dto/user'
import { User } from 'types/user'
import { identifyGender } from 'services/identifyGender'

export default async function handler(
    req: NextApiRequest,
    res: NextApiResponse
) {
    const { userId, calendarId } = req.body
    const { mongoClient } = await connectToDatabase()
    const db: Db = mongoClient.db(process.env.DB_NAME)
    const clientIp = req.headers['x-forwarded-for'] || req.socket.remoteAddress
    await db.collection('logs').insertOne({
        api: 'fetchEventTimesFromGoogleCalendar',
        createdAt: new Date(),
        severity: 'log',
        body: req.body,
        clientIp,
    })
    try {
        let user = await db
            .collection<User>('users')
            .findOne({ _id: new ObjectId(userId) })
        if (!user?.googleAccessToken) {
            return
        }
        const response = await fetch(
            `https://www.googleapis.com/calendar/v3/calendars/${encodeURIComponent(
                calendarId
            )}/events`,
            {
                method: 'GET',
                headers: {
                    Authorization: `Bearer ${user?.googleAccessToken}`,
                },
            }
        )
        if (response.ok) {
            const data = await response.json()
            await db.collection('logs').insertOne({
                api: 'fetchEventTimesFromGoogleCalendar',
                createdAt: new Date(),
                severity: 'log',
                clientIp,
                eventTimes: data.items,
            })

            return res.status(200).json({
                data: {},
            })
        } else {
            const errorText = await response.json() // Get the response body text for debugging
            return res
                .status(404)
                .json({ message: 'Failed to fetch calendar data', details: errorText })
        }
    } catch (error) {
        await db.collection('logs').insertOne({
            api: 'fetchEventTimesFromGoogleCalendar',
            createdAt: new Date(),
            severity: 'error',
            error: error.message,
        })
        return res.status(500).json({ message: 'Failed to fetch calendar data' })
    }
}

How to set scope?

This is how google login click is handled:

<button
    className={`${styles.button} ${styles.googleBtn}`}
    onClick={() => registerGoogle()}
>
    Google bejelentkezés
</button>
const registerGoogle = useGoogleLogin({
    onSuccess: (tokenResponse) => {
        console.log(tokenResponse)
        auth.handleAuth(
            'auth/registerGoogle',
            {
                accessToken: tokenResponse.access_token,
            },
            completion,
            createTeamIfNotExist
        )
    },
})

Do I need to set scope somehow?

Upvotes: 0

Views: 55

Answers (0)

Related Questions