ory / kratos-selfservice-ui-react-nextjs

A full reference implementation for designing your own login, registration, recovery, verification, ... pages using Ory Kratos' APIs.
https://www.ory.sh/
Apache License 2.0
135 stars 56 forks source link

This example is overcomplicated #21

Closed rodocite closed 2 years ago

aeneasr commented 2 years ago

Did you see https://www.ory.sh/nextjs-authentication-spa-custom-flows-open-source ?

rodocite commented 2 years ago

Apologies. I didn't realize the Ory Cloud offering was still in alpha and figured the examples will improve over time so I removed my previous comment. I did see that link, but I still think it's an overcomplicated implementation as a quickstart example. As a reference implementation, it's good, though.

I ended up just using Ory Cloud w/ the Managed UI for now (which seems to be using the reference implementation).

On Fri, Jan 7, 2022 at 1:10 AM hackerman @.***> wrote:

Did you see https://www.ory.sh/nextjs-authentication-spa-custom-flows-open-source ?

— Reply to this email directly, view it on GitHub https://github.com/ory/kratos-selfservice-ui-react-nextjs/issues/21#issuecomment-1007248965, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABJFIAF44PMHJU5NU4UHVM3UU2UZ3ANCNFSM5LOABF6Q . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you modified the open/close state.Message ID: @.*** com>

aeneasr commented 2 years ago

No problem! There's is also a guide that is a bit easier to understand because it is just about using ory for login and not implementing your own screens - you can find the info here: https://www.ory.sh/login-spa-react-nextjs-authentication-example-api-open-source/

We are also planning a full month to spend with the whole team on restructuring the documentation and making it easier to digest. If you have some ideas we would definitely appreciate them! @vinckr would love your input. If you're interested just comment hear or reach out on slack.ory.sh :)

As a goody we also have the ory start up plan free for a year if you're interested :)

rodocite commented 2 years ago

I'll be looking into this more over the weekend, but I think this pattern seems to be easier to digest for some use cases:

Create an AuthProvider:

import { createContext, useEffect, useState, useContext } from "react";
import { Configuration, Session, V0alpha2Api } from "@ory/kratos-client";
import { edgeConfig } from "@ory/integrations/next";

export const AuthContext = createContext();

const kratos = new V0alpha2Api(new Configuration(edgeConfig));

export const useAuth = () => useContext(AuthContext);

export const AuthProvider = ({ children }) => {
  const [session, setSession] = useState();
  const [logoutUrl, setLogoutUrl] = useState();
  const [error, setError] = useState();

  useEffect(() => {
    // If the session or error have been loaded, do nothing.
    if (session || error) {
      return;
    }
    // Try to load the session.
    kratos
      .toSession()
      .then(({ data: session }) => {
        setSession(session);

        kratos
          .createSelfServiceLogoutFlowUrlForBrowsers()
          .then(({ data }) => {
            setLogoutUrl(data.logout_url);
          });
      })
      .catch((err) => {
        // An error occurred while loading the session or fetching
        // the logout URL. Let's show that!
        setError({
          error: err.toString(),
          data: err.response?.data,
        });
      });
  }, [session, error]);

  const value = {
    session,
    logoutUrl,
  }

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};

Wrap your app with the AuthProvider:

import { AuthProvider } from '../contexts/AuthProvider'

function MyApp({ Component, pageProps }) {
  return (
    <AuthProvider>
          <Component {...pageProps} />
    </AuthProvider>
  );
}

export default MyApp;

Use hooks to grab session state:

import { useAuth } from '../contexts/AuthProvider';

function Index() {
  const { session, logoutUrl } = useAuth();

  return (
    <div>
      stuff here
    </div>
  );
}

export default Index;

I will be working on this pattern over the weekend. Please let me know if there are issues. Thanks. (Also this example is a incomplete since I'm doing it a bit last-minute. Hope it galvanizes some ideas.)

rodocite commented 2 years ago

Also, you may want to check the original example. I just realized the multiple set calls are firing re-renders.

vinckr commented 2 years ago

Thanks a lot for your contribution @rodocite ! I will check out the example and see how we can integrate it into the documentation.

OliverGeneser commented 2 years ago

@rodocite Did you solve the problem with set calls firing re-renders in your example? @vinckr is an example with providers on the roadmap?

MadsKelberg commented 2 years ago

@rodocite @OliverGeneser I appear to have the same problem. Any solutions?

rodocite commented 2 years ago

Let me take a look this weekend. I didn't even know this was a thing still.

But it could be as simple as wrapping that fetch in a useCallback to prevent re-renders.

MadsKelberg commented 2 years ago

@rodocite That would be awesome 😄 Thanks in advance 💯

OliverGeneser commented 1 year ago

@rodocite Would be appreciated :blush: