From 211c3576d75db30682fb8d8a2b106dcd4d992d1e Mon Sep 17 00:00:00 2001 From: wangsijie Date: Thu, 27 Jun 2024 17:29:25 +0800 Subject: [PATCH] refactor(console): update next guide (#6119) --- .../assets/docs/fragments/_redirect_uris.mdx | 2 +- .../guides/web-next-app-router/README.mdx | 183 ++++++------------ .../assets/docs/guides/web-next/README.mdx | 165 +++++----------- 3 files changed, 107 insertions(+), 243 deletions(-) diff --git a/packages/console/src/assets/docs/fragments/_redirect_uris.mdx b/packages/console/src/assets/docs/fragments/_redirect_uris.mdx index 780f4f97e..24847fd39 100644 --- a/packages/console/src/assets/docs/fragments/_redirect_uris.mdx +++ b/packages/console/src/assets/docs/fragments/_redirect_uris.mdx @@ -26,7 +26,7 @@ To learn more about the rationale and benefits of redirect-based sign-in, see [L In the following steps, we assume your app is running on http://localhost:3000. -Now, let's enter your redirect URI. E.g. `http://localhost:3000/callback`. +Now, let's enter your redirect URI. E.g. {`${props.callbackUri ?? 'http://localhost:3000/callback'}`}. diff --git a/packages/console/src/assets/docs/guides/web-next-app-router/README.mdx b/packages/console/src/assets/docs/guides/web-next-app-router/README.mdx index 26915db22..2ed05e28e 100644 --- a/packages/console/src/assets/docs/guides/web-next-app-router/README.mdx +++ b/packages/console/src/assets/docs/guides/web-next-app-router/README.mdx @@ -1,17 +1,18 @@ -import UriInputField from '@/mdx-components/UriInputField'; import Tabs from '@mdx/components/Tabs'; import TabItem from '@mdx/components/TabItem'; -import InlineNotification from '@/ds-components/InlineNotification'; import { generateStandardSecret } from '@logto/shared/universal'; import Steps from '@/mdx-components/Steps'; import Step from '@/mdx-components/Step'; +import Checkpoint from '../../fragments/_checkpoint.md'; +import RedirectUris from '../../fragments/_redirect_uris.mdx'; + @@ -41,13 +42,9 @@ pnpm add @logto/next title="Prepare configs" > - - In the following steps, we assume your app is running on http://localhost:3000. - +Prepare configuration for the Logto client: -Prepare configuration for the Logto client. Create a new file `app/logto.ts` and add the following code: - - + {`export const logtoConfig = { endpoint: '${props.endpoint}', appId: '${props.app.id}', @@ -61,21 +58,12 @@ Prepare configuration for the Logto client. Create a new file `app/logto.ts` and -### Configure Redirect URI +Add a callback route to your app: -First, let’s enter your redirect URI. E.g. `http://localhost:3000/callback`. - - - -### Implement callback page - -Add a callback page to your app: - -```tsx -// pages/callback/page.tsx +```tsx title="/app/callback/route.ts" import { handleSignIn } from '@logto/next/server-actions'; import { redirect } from 'next/navigation'; import { NextRequest } from 'next/server'; @@ -89,12 +77,26 @@ export async function GET(request: NextRequest) { } ``` -### Implement sign-in button + -The sign-in button will call the method we just created, it is a client component: - -```tsx -// app/sign-in.tsx + + + + + + + + +### Implement sign-in and sign-out button + +In Next.js App Router, events are handled in client components, so we need to create two components first: `SignIn` and `SignOut`. + +```tsx title="/app/sign-in.tsx" 'use client'; type Props = { @@ -116,53 +118,7 @@ const SignIn = ({ onSignIn }: Props) => { export default SignIn; ``` -### Add sign in button to home page - -We're almost there! Add this button to home page at `/app/page.tsx` and implement the `onSignIn` function: - -```tsx -import { signIn } from '@logto/next/server-actions'; -import SignIn from './sign-in'; -import { logtoConfig } from './logto'; - -export default async function Home() { - return ( -
-

Hello Logto.

-
- { - 'use server'; - - await signIn(logtoConfig); - }} - /> -
-
- ); -} -``` - -Now you will be navigated to Logto sign-in page when you click the button. - -
- - - -### Configure URI - -After signing out, it'll be great to redirect user back to your website. Let's add `http://localhost:3000` as the Post Sign-out URI below. - - - -### Implement a sign-out button - -The sign-out button is also a client component, so we will create it in `/app/sign-out.tsx`: - -```tsx -// app/sign-out.tsx +```tsx title="/app/sign-out.tsx" 'use client'; type Props = { @@ -184,63 +140,26 @@ const SignOut = ({ onSignOut }: Props) => { export default SignOut; ``` -### Add sign out button to home page +Remember to add `'use client'` to the top of the file to indicate that these components are client components. -Then add the sign-out button to the home page in `/app/page.tsx`: +### Add buttons to home page -```tsx -import { signIn, signOut } from '@logto/next/server-actions'; -import SignIn from './sign-in'; -import SignOut from './sign-out'; -import { logtoConfig } from './logto'; +Now let's add the sign-in and sign-out buttons in your hoem page. We need to call the server actions in SDK when needed. To help with this, use `getLogtoContext` to fetch authentication status. -export default async function Home() { - return ( -
-

Hello Logto.

-
- { - 'use server'; - - await signOut(logtoConfig); - }} - /> - { - 'use server'; - - await signIn(logtoConfig); - }} - /> -
-
- ); -} -``` - -
- - - -We can call the function `getLogtoContext` to get context as the authentication state in pages, let's modify the home page: - -```tsx +```tsx title="/app/page.tsx" import { getLogtoContext, signIn, signOut } from '@logto/next/server-actions'; import SignIn from './sign-in'; import SignOut from './sign-out'; import { logtoConfig } from './logto'; -export default async function Home() { - const { isAuthenticated } = await getLogtoContext(logtoConfig); +const Home = () => { + const { isAuthenticated, claims } = await getLogtoContext(logtoConfig); return ( -
-

Hello Logto.

-
- {isAuthenticated ? ( +
-
+

+ )} + ); -} +}; + +export default Home; ```
+ + + + + +
diff --git a/packages/console/src/assets/docs/guides/web-next/README.mdx b/packages/console/src/assets/docs/guides/web-next/README.mdx index fa6100178..e806cf5eb 100644 --- a/packages/console/src/assets/docs/guides/web-next/README.mdx +++ b/packages/console/src/assets/docs/guides/web-next/README.mdx @@ -1,17 +1,18 @@ -import UriInputField from '@/mdx-components/UriInputField'; import Tabs from '@mdx/components/Tabs'; import TabItem from '@mdx/components/TabItem'; -import InlineNotification from '@/ds-components/InlineNotification'; import { generateStandardSecret } from '@logto/shared/universal'; import Steps from '@/mdx-components/Steps'; import Step from '@/mdx-components/Step'; +import Checkpoint from '../../fragments/_checkpoint.md'; +import RedirectUris from '../../fragments/_redirect_uris.mdx'; + @@ -41,15 +42,10 @@ pnpm add @logto/next title="Init LogtoClient" > - - In the following steps, we assume your app is running on http://localhost:3000. - - Import and initialize LogtoClient: - - {`// libraries/logto.js -import LogtoClient from '@logto/next'; + + {`import LogtoClient from '@logto/next'; export const logtoClient = new LogtoClient({ endpoint: '${props.endpoint}', @@ -63,24 +59,13 @@ export const logtoClient = new LogtoClient({ - - -### Configure Redirect URI - -First, let’s enter your redirect URI. E.g. `http://localhost:3000/api/logto/sign-in-callback`. - - - -### Prepare API routes + Prepare [API routes](https://nextjs.org/docs/api-routes/introduction) to connect with Logto. Go back to your IDE/editor, use the following code to implement the API routes first: -```ts -// pages/api/logto/[action].ts +```ts title="pages/api/logto/[action].ts" import { logtoClient } from '../../../libraries/logto'; export default logtoClient.handleAuthRoutes(); @@ -93,122 +78,70 @@ This will create 4 routes automatically: 3. `/api/logto/sign-out`: Sign out with Logto. 4. `/api/logto/user`: Check if user is authenticated with Logto, if yes, return user info. -### Implement sign-in button + -We're almost there! In the last step, we will create a sign-in button: + -```tsx -import { useRouter } from 'next/router'; - -const { push } = useRouter(); - -; -``` - -Now you will be navigated to Logto sign-in page when you click the button. + -Calling `/api/logto/sign-out` will clear all the Logto data in memory and cookies if they exist. - -After signing out, it'll be great to redirect user back to your website. Let's add `http://localhost:3000` as the Post Sign-out URI below before calling `/api/logto/sign-out`. - - - -### Implement a sign-out button - -```tsx - -``` - - - - - -### Through API request in the frontend - -You can fetch user info by calling `/api/logto/user`. - -```tsx -import { LogtoUser } from '@logto/next'; -import useSWR from 'swr'; - -const Home = () => { - const { data } = useSWR('/api/logto/user'); - - return
User ID: {data?.claims?.sub}
; -}; - -export default Profile; -``` +We have prepared the API routes, now let's implement the sign-in and sign-out buttons in your home page. We need to redirect the user to the sign-in or sign-out route when needed. To help with this, use `useSWR` to fetch authentication status from `/api/logto/user`. Check [this guide](https://swr.vercel.app/docs/getting-started) to learn more about `useSWR`. -### Through `getServerSideProps` in the backend +```tsx title="/pages/index.tsx" +import { type LogtoContext } from '@logto/next'; +import useSWR from 'swr'; -```tsx -import { LogtoUser } from '@logto/next'; -import { logtoClient } from '../libraries/logto'; +const Home = () => { + const { data } = useSWR('/api/logto/user'); -type Props = { - user: LogtoUser; + return ( + + ); }; -const Profile = ({ user }: Props) => { - return
User ID: {user.claims?.sub}
; -}; - -export default Profile; - -export const getServerSideProps = logtoClient.withLogtoSsr(({ request }) => { - const { user } = request; - - return { - props: { user }, - }; -}); +export default Home; ``` -Check [Next.js documentation](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props) for more details on `getServerSideProps`. - -### Protect API routes - -Wrap your handler with `logtoClient.withLogtoApiRoute`. - -```ts -// pages/api/protected-resource.ts -import { logtoClient } from '../../libraries/logto'; - -export default logtoClient.withLogtoApiRoute((request, response) => { - if (!request.user.isAuthenticated) { - response.status(401).json({ message: 'Unauthorized' }); - - return; - } - - response.json({ - data: 'this_is_protected_resource', - }); -}); -```
-Now, you can test your application: - -1. Run your application, you will see the sign-in button. -2. Click the sign-in button, and you will be redirected to the sign in route, and the SDK will then init the sign-in process and redirect to the Logto sign-in page. -3. After you signed in, you will be redirect back to your application and see user id and the sign-out button. -4. Click the sign-out button to sign-out. +