Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Recipe to Power Up Gatsby with Auth

A Recipe to Power Up Gatsby with Auth

Gatsby rose to fame as a static site generator, but it’s also an amazing platform for building dynamic sites! Wouldn’t it be awesome if we could add a user profile with access to protected data in our Gatsby app? Like Mario’s fire flower or Link’s hook shot, adding auth will power up your dynamic Gatsby site. Just one question: is it any different than adding auth to a regular React app?

In this talk, you’ll learn about Gatsby’s build process and runtime and how they impact setting up auth. You’ll also learn how to use Hooks and Context to build your auth sidekick. Finally, you’ll learn how Gatsby recipes can speed up this implementation and make it easy to replicate in all of your projects. By the end, you’ll be ready for the next level of your Gatsby quest!

Sam Julien

July 01, 2020
Tweet

More Decks by Sam Julien

Other Decks in Technology

Transcript

  1. Adding Auth to Gatsby @samjulien Build Time vs. Runtime Using

    Hooks for Auth An Auth Recipe for Gatsby %
  2. @samjulien Sam Julien samjulien.com Sr. Developer Advocate Engineer at Auth0

    Google Developer Expert Instructor for Thinkster & egghead
  3. Adding Auth to Gatsby @samjulien Build Time vs. Runtime Using

    Hooks for Auth An Auth Recipe for Gatsby %
  4. Adding Auth to Gatsby @samjulien Build Time vs. Runtime Using

    Hooks for Auth An Auth Recipe for Gatsby %
  5. @samjulien Store token and user in memory Interact with auth

    SDK Handle all redirect logic Auth Utility
  6. @samjulien const [authClient, setAuthClient] = useState(); const [isAuthenticated, setIsAuthenticated] =

    useState(); const [token, setToken] = useState(); const [user, setUser] = useState(); const [loading, setLoading] = useState(true);
  7. @samjulien const [authClient, setAuthClient] = useState(); const [isAuthenticated, setIsAuthenticated] =

    useState(); const [token, setToken] = useState(); const [user, setUser] = useState(); const [loading, setLoading] = useState(true);
  8. @samjulien const [authClient, setAuthClient] = useState(); const [isAuthenticated, setIsAuthenticated] =

    useState(); const [token, setToken] = useState(); const [user, setUser] = useState(); const [loading, setLoading] = useState(true);
  9. @samjulien const [authClient, setAuthClient] = useState(); const [isAuthenticated, setIsAuthenticated] =

    useState(); const [token, setToken] = useState(); const [user, setUser] = useState(); const [loading, setLoading] = useState(true);
  10. @samjulien const [authClient, setAuthClient] = useState(); const [isAuthenticated, setIsAuthenticated] =

    useState(); const [token, setToken] = useState(); const [user, setUser] = useState(); const [loading, setLoading] = useState(true);
  11. @samjulien useEffect(() => { const initAuth = async () =>

    { // initialize the auth client const authFromHook = await createAuthClient(initOptions); setAuth(authFromHook); // check if we're in the middle of a redirect if ( window.location.search.includes("code=") && window.location.search.includes("state=") ) { const { appState } = await authFromHook.handleRedirectCallback(); onRedirectCallback(appState); }
  12. @samjulien useEffect(() => { const initAuth = async () =>

    { // initialize the auth client const authFromHook = await createAuthClient(initOptions); setAuth(authFromHook); // check if we're in the middle of a redirect if ( window.location.search.includes("code=") && window.location.search.includes("state=") ) { const { appState } = await authFromHook.handleRedirectCallback(); onRedirectCallback(appState); }
  13. @samjulien useEffect(() => { const initAuth = async () =>

    { // initialize the auth client const authFromHook = await createAuthClient(initOptions); setAuth(authFromHook); // check if we're in the middle of a redirect if ( window.location.search.includes("code=") && window.location.search.includes("state=") ) { const { appState } = await authFromHook.handleRedirectCallback(); onRedirectCallback(appState); }
  14. @samjulien useEffect(() => { const initAuth = async () =>

    { // initialize the auth client const authFromHook = await createAuthClient(initOptions); setAuth(authFromHook); // check if we're in the middle of a redirect if ( window.location.search.includes("code=") && window.location.search.includes("state=") ) { const { appState } = await authFromHook.handleRedirectCallback(); onRedirectCallback(appState); }
  15. @samjulien // set initial state using hooks const isAuthenticated =

    await authFromHook.isAuthenticated(); setIsAuthenticated(isAuthenticated); if (isAuthenticated) { const user = await authFromHook.getUser(); setUser(user); } setLoading(false); }; initAuth(); }, []);
  16. @samjulien // set initial state using hooks const isAuthenticated =

    await authFromHook.isAuthenticated(); setIsAuthenticated(isAuthenticated); if (isAuthenticated) { const user = await authFromHook.getUser(); setUser(user); } setLoading(false); }; initAuth(); }, []);
  17. @samjulien // set initial state using hooks const isAuthenticated =

    await authFromHook.isAuthenticated(); setIsAuthenticated(isAuthenticated); if (isAuthenticated) { const user = await authFromHook.getUser(); setUser(user); } setLoading(false); }; initAuth(); }, []);
  18. @samjulien // set initial state using hooks const isAuthenticated =

    await authFromHook.isAuthenticated(); setIsAuthenticated(isAuthenticated); if (isAuthenticated) { const user = await authFromHook.getUser(); setUser(user); } setLoading(false); }; initAuth(); }, []);
  19. @samjulien // set initial state using hooks const isAuthenticated =

    await authFromHook.isAuthenticated(); setIsAuthenticated(isAuthenticated); if (isAuthenticated) { const user = await authFromHook.getUser(); setUser(user); } setLoading(false); }; initAuth(); }, []);
  20. @samjulien // set initial state using hooks const isAuthenticated =

    await authFromHook.isAuthenticated(); setIsAuthenticated(isAuthenticated); if (isAuthenticated) { const user = await authFromHook.getUser(); setUser(user); } setLoading(false); }; initAuth(); }, []);
  21. @samjulien return ( <AuthContext.Provider value={{ isAuthenticated, user, token, loading, handleRedirectCallback,

    getToken: (...p) => authClient.getTokenSilently(...p), logout: (...p) => authClient.logout(...p), }} > {children} </AuthContext.Provider> );
  22. @samjulien return ( <AuthContext.Provider value={{ isAuthenticated, user, token, loading, handleRedirectCallback,

    getToken: (...p) => authClient.getTokenSilently(...p), logout: (...p) => authClient.logout(...p), }} > {children} </AuthContext.Provider> );
  23. @samjulien return ( <AuthContext.Provider value={{ isAuthenticated, user, token, loading, handleRedirectCallback,

    getToken: (...p) => authClient.getTokenSilently(...p), logout: (...p) => authClient.logout(...p), }} > {children} </AuthContext.Provider> );
  24. @samjulien return ( <AuthContext.Provider value={{ isAuthenticated, user, token, loading, handleRedirectCallback,

    getToken: (...p) => authClient.getTokenSilently(...p), logout: (...p) => authClient.logout(...p), }} > {children} </AuthContext.Provider> );
  25. @samjulien return ( <AuthContext.Provider value={{ isAuthenticated, user, token, loading, handleRedirectCallback,

    getToken: (...p) => authClient.getTokenSilently(...p), logout: (...p) => authClient.logout(...p), }} > {children} </AuthContext.Provider> );
  26. @samjulien return ( <AuthContext.Provider value={{ isAuthenticated, user, token, loading, handleRedirectCallback,

    getToken: (...p) => authClient.getTokenSilently(...p), logout: (...p) => authClient.logout(...p), }} > {children} </AuthContext.Provider> );
  27. @samjulien Store token and user in memory Interact with auth

    SDK Handle all redirect logic Auth Utility
  28. @samjulien const NavBar = () => { const { isAuthenticated,

    login, logout } = useAuth(); return ( <div> <Link to="/">Home</Link>{" "} {!isAuthenticated && <button onClick={() => login()}>Log in</button>} {isAuthenticated && ( <> <Link to="/profile">Profile</Link> <button onClick={() => logout()}>Log out</button> </> )} </div> ); };
  29. @samjulien const NavBar = () => { const { isAuthenticated,

    login, logout } = useAuth(); return ( <div> <Link to="/">Home</Link>{" "} {!isAuthenticated && <button onClick={() => login()}>Log in</button>} {isAuthenticated && ( <> <Link to="/profile">Profile</Link> <button onClick={() => logout()}>Log out</button> </> )} </div> ); };
  30. @samjulien const NavBar = () => { const { isAuthenticated,

    login, logout } = useAuth(); return ( <div> <Link to="/">Home</Link>{" "} {!isAuthenticated && <button onClick={() => login()}>Log in</button>} {isAuthenticated && ( <> <Link to="/profile">Profile</Link> <button onClick={() => logout()}>Log out</button> </> )} </div> ); };
  31. @samjulien const NavBar = () => { const { isAuthenticated,

    login, logout } = useAuth(); return ( <div> <Link to="/">Home</Link>{" "} {!isAuthenticated && <button onClick={() => login()}>Log in</button>} {isAuthenticated && ( <> <Link to="/profile">Profile</Link> <button onClick={() => logout()}>Log out</button> </> )} </div> ); };
  32. @samjulien const NavBar = () => { const { isAuthenticated,

    login, logout } = useAuth(); return ( <div> <Link to="/">Home</Link>{" "} {!isAuthenticated && <button onClick={() => login()}>Log in</button>} {isAuthenticated && ( <> <Link to="/profile">Profile</Link> <button onClick={() => logout()}>Log out</button> </> )} </div> ); };
  33. @samjulien export default () => { const { loading }

    = useAuth(); if (loading) { return <div>Loading...</div>; } return ( <div> <NavBar /> <Home /> </div> ); };
  34. @samjulien export default () => { const { loading }

    = useAuth(); if (loading) { return <div>Loading...</div>; } return ( <div> <NavBar /> <Home /> </div> ); };
  35. @samjulien export default () => { const { loading }

    = useAuth(); if (loading) { return <div>Loading...</div>; } return ( <div> <NavBar /> <Home /> </div> ); };
  36. Adding Auth to Gatsby @samjulien Build Time vs. Runtime Using

    Hooks for Auth An Auth Recipe for Gatsby %
  37. Automate common tasks Gatsby Recipes # Install packages and plugins

    Generate pages and code Written in MDX @samjulien
  38. Automate common tasks Run from the CLI Gatsby Recipes #

    Install packages and plugins Generate pages and code Written in MDX @samjulien
  39. export const wrapRootElement = ({ element }) => { return

    ( <AuthProvider // pass in any configuration here > {element} </AuthProvider> ); }; @samjulien
  40. export const wrapRootElement = ({ element }) => { return

    ( <AuthProvider // pass in any configuration here > {element} </AuthProvider> ); }; @samjulien
  41. export const wrapRootElement = ({ element }) => { return

    ( <AuthProvider // pass in any configuration here > {element} </AuthProvider> ); }; @samjulien
  42. Watch out for dependencies using browser APIs like window or

    document. @samjulien (Spoilers: auth libraries usually do this a lot because of redirects and pop-ups.)
  43. @samjulien exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {

    if (["build-html", “develop-html"].includes(stage)) { actions.setWebpackConfig({ module: { rules: [ { test: /auth-sdk/, use: loaders.null(), }, ], }, }); } };
  44. @samjulien exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {

    if (["build-html", “develop-html"].includes(stage)) { actions.setWebpackConfig({ module: { rules: [ { test: /auth-sdk/, use: loaders.null(), }, ], }, }); } };
  45. @samjulien exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {

    if (["build-html", "develop-html"].includes(stage)) { actions.setWebpackConfig({ module: { rules: [ { test: /auth-sdk/, use: loaders.null(), }, ], }, }); } };
  46. @samjulien exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {

    if (["build-html", "develop-html"].includes(stage)) { actions.setWebpackConfig({ module: { rules: [ { test: /auth-sdk/, use: loaders.null(), }, ], }, }); } };
  47. @samjulien exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {

    if (["build-html", "develop-html"].includes(stage)) { actions.setWebpackConfig({ module: { rules: [ { test: /auth-sdk/, use: loaders.null(), }, ], }, }); } };
  48. @samjulien exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {

    if (["build-html", "develop-html"].includes(stage)) { actions.setWebpackConfig({ module: { rules: [ { test: /auth-sdk/, use: loaders.null(), }, ], }, }); } };
  49. @samjulien Store token and user in memory Interact with auth

    SDK Handle all redirect logic Auth Utility
  50. @samjulien return ( <AuthContext.Provider value={{ isAuthenticated, user, token, loading, handleRedirectCallback,

    getToken: (...p) => authClient.getTokenSilently(...p), logout: (...p) => authClient.logout(...p), }} > {children} </AuthContext.Provider> );
  51. Automate common tasks Gatsby Recipes # Install packages and plugins

    Generate pages and code Written in MDX @samjulien
  52. Automate common tasks Run from the CLI Gatsby Recipes #

    Install packages and plugins Generate pages and code Written in MDX @samjulien
  53. export const wrapRootElement = ({ element }) => { return

    ( <AuthProvider // pass in any configuration here > {element} </AuthProvider> ); }; @samjulien
  54. Watch out for dependencies using browser APIs like window or

    document. @samjulien (Spoilers: auth libraries usually do this a lot because of redirects and pop-ups.)
  55. @samjulien exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {

    if (stage === "build-html") { actions.setWebpackConfig({ module: { rules: [ { test: /auth-sdk/, use: loaders.null(), }, ], }, }); } };