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

Power Up Gatsby with Auth!

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 some tips and tricks to avoid common pitfalls with adding auth to Gatsby. By the end, you’ll be ready for the next level of your Gatsby quest!

Sam Julien

May 02, 2020
Tweet

More Decks by Sam Julien

Other Decks in Technology

Transcript

  1. @samjulien Sam Julien @samjulien Sr. Developer Advocate Engineer at Auth0

    Google Developer Expert Instructor for Thinkster & egghead
  2. @samjulien Store token and user in memory Interact with auth

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

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

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

    useState(); const [token, setToken] = useState(); const [user, setUser] = useState(); const [loading, setLoading] = useState(true);
  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 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); }
  9. @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); }
  10. @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); }
  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 // set initial state using hooks const isAuthenticated =

    await authFromHook.isAuthenticated(); setIsAuthenticated(isAuthenticated); if (isAuthenticated) { const user = await authFromHook.getUser(); setUser(user); } setLoading(false); }; initAuth(); }, []);
  13. @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(); }, []);
  14. @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(); }, []);
  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 return ( <AuthContext.Provider value={{ isAuthenticated, user, token, loading, handleRedirectCallback,

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

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

    getToken: (...p) => authClient.getTokenSilently(...p), logout: (...p) => authClient.logout(...p), }} > {children} </AuthContext.Provider> );
  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 Store token and user in memory Interact with auth

    SDK Handle all redirect logic Auth Utility
  25. export const wrapRootElement = ({ element }) => { return

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

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

    ( <AuthProvider // pass in any configuration here > {element} </AuthProvider> ); }; @samjulien
  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. 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.)
  37. @samjulien exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {

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

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

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

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

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

    if (stage === "build-html") { actions.setWebpackConfig({ module: { rules: [ { test: /auth-sdk/, use: loaders.null(), }, ], }, }); } };
  43. You may need to conditionally set values depending on if

    you’re in the browser. @samjulien
  44. @samjulien Store token and user in memory Interact with auth

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

    getToken: (...p) => authClient.getTokenSilently(...p), logout: (...p) => authClient.logout(...p), }} > {children} </AuthContext.Provider> );
  46. 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.)
  47. @samjulien exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {

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