Reputation: 119
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
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