Jackson Kasi
Jackson Kasi

Reputation: 119

how to create gapi-script authentication using next-auth on nextjs project?

I am creating open-source project using google drive api, but I have a issue!

how to create gapi-script authentication using next-auth on nextjs project?

I can make authentication in gapi-script with out next-auth, also can make using next-auth using googleProvider.

But how to make authendication using gapi-script npm package with next-auth?

gapi-script auth


    const initClient = () => {
    setIsLoadingGoogleDriveApi(true);
    gapi.client
      .init({
        apiKey: API_KEY,
        clientId: CLIENT_ID,
        discoveryDocs: DISCOVERY_DOCS,
        scope: SCOPES,
      })
      .then(
        function () {
          // Listen for sign-in state changes.
          gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);

          // Handle the initial sign-in state.
          updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
        },
        function (error) {}
      );
  };

* Click to See the Full Code using gapi-cript

Upvotes: 1

Views: 2410

Answers (1)

fotoflo
fotoflo

Reputation: 957

I solved a similar problem by creating a Gapi Context and passing the user's token into the context.

I had previously grabbed the users token during next auth and stored it in my DB

import React, { useState, createContext, useEffect, useCallback } from "react";

export const GapiClientContext = createContext();

const GAPI_CONFIG = {
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_CONFIG_apiKey,
  clientId: process.env.GOOGLE_ID,
  scope: "https://www.googleapis.com/auth/gmail.send",
  discoveryDocs: ["https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"],
  fetch_basic_profile: true,
  immediate: true,
  plugin_name: "app name",
};


const GapiContextProvider = ({ session, ...props }) => {

  const [GapiClient, setGapiClient] = useState(); //{ gapi });

  // to test initClient properly, remove access from third party access after each grant:
  // https://myaccount.google.com/permissions?continue=https%3A%2F%2Fmyaccount.google.com%2Fsecurity%3Fpli%3D1
  // then logout
  // to ensure gapi only loads once: https://stackoverflow.com/questions/68985492/how-to-prevent-script-from-loading-multiple-times-with-react

  const initClient = useCallback(async () => {
    if (window.gapiIsInitialized) return;

    console.log("intting gapi");
    return gapi.client.init(GAPI_CONFIG).then(
      () => {
        const access_token =
          session.externalAccounts.find((acct) => acct.provider === "gmail")
            ?.access_token ?? "";

        if (access_token === "") return;

        gapi.client.setToken({ access_token });

        window.gapiIsInitialized = true;
        setGmailIsDisabled(false);
        return;
      },
      (e) => {
        window.gapiIsLoading = false;
        console.info("error init gapi client", e.details);
      }
    );
  }, []);

  const setupGapi = useCallback(async () => {
    const gapi = await import("gapi-script").then((pack) => pack.gapi);
    // https://stackoverflow.com/questions/71040050/why-am-i-getting-syntaxerror-cannot-use-import-statement-outside-a-module
    setGapiClient({ gapi });

    try {
      await gapi.load("client:auth2", initClient);
    } catch (e) {
      window.gapiIsLoading = false;
      console.log("couldnt sign in to gAPI!", e);
    }
  }, [initClient]);

  useEffect(() => {
    if (window.gapiIsInitialized || window.gapiIsLoading) return;
    window.gapiIsLoading = true;
    setupGapi();
  }, [initClient, setupGapi]);

  return (
    <GapiClientContext.Provider
      value={{
        GapiClient
      }}
    >
      {props.children}
    </GapiClientContext.Provider>
  );
};

export default GapiContextProvider;

Then in my application I wrapped the consuming components A full example would show that I also tracked the state of sending email from within the context provider... you can see that here:

https://github.com/fotoflo/next-firebase-multi-auth-starter

... i'll be merging this context in in the next couple days also

          <GapiContextProvider session={session}>
            <SendGmailButton emailMessage={emailMessage} />
          </GapiContextProvider>

Hope this is helpful! Good luck :-)

Upvotes: 1

Related Questions