0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-06 20:40:08 -05:00

refactor(console): react sdk integration guide

This commit is contained in:
Charles Zhao 2022-06-29 18:36:35 +08:00
parent 06d279816f
commit f7c574c8d0
No known key found for this signature in database
GPG key ID: 4858774754C92DF2
5 changed files with 184 additions and 188 deletions

View file

@ -2,9 +2,10 @@ import UriInputField from '@mdx/components/UriInputField';
import Step from '@mdx/components/Step';
import Tabs from '@mdx/components/Tabs';
import TabItem from '@mdx/components/TabItem';
import Alert from '@/components/Alert';
<Step
title="Install SDK"
title="Add Logto SDK as a dependency"
subtitle="Please select your favorite package manager"
index={0}
activeIndex={props.activeStepIndex}
@ -31,67 +32,34 @@ yarn add @logto/react
pnpm add @logto/react
```
</TabItem>
<TabItem value="script" label="script">
```html
<script src="https://logto.io/js/logto-sdk-react/0.1.0/logto-sdk-react.production.js" />
```
</TabItem>
<TabItem value="git" label="Git">
```bash
git clone https://github.com/logto-io/js.git
pnpm build
```
</TabItem>
</Tabs>
</Step>
<Step
title="Initiate LogtoClient"
title="Init LogtoClient"
subtitle="1 step"
index={1}
activeIndex={props.activeStepIndex}
onButtonClick={() => props.onNext(2)}
>
Add the following code to your main html file. You may need client ID and authorization domain.
Import and use `LogtoProvider` to provide a Logto context:
<pre>
<code className="language-tsx">
{`import { LogtoProvider, LogtoConfig } from '@logto/react';
import React from 'react';
//...
const config: LogtoConfig = {
endpoint: '${props.endpoint}',
clientId: '${props.appId}',
};
const App = () => {
const config: LogtoConfig = {
clientId: '${props.appId}',
endpoint: '${props.endpoint}',
};
return (
<BrowserRouter>
<LogtoProvider config={config}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/callback" element={<Callback />} />
<Route
path="/protected-resource"
element={
<RequireAuth>
<ProtectedResource />
</RequireAuth>
}
/>
</Routes>
</LogtoProvider>
</BrowserRouter>
);
};`}
const App = () => (
<LogtoProvider config={config}>
<YourAppContent />
</LogtoProvider>
);`}
</code>
</pre>
@ -99,54 +67,74 @@ const App = () => {
<Step
title="Sign In"
subtitle="2 steps"
subtitle="3 steps"
index={2}
activeIndex={props.activeStepIndex}
onButtonClick={() => props.onNext(3)}
>
### Step 1: Setup your login
<Alert>
In the following steps, we assume your app is running on <code>http://localhost:1234</code>.
</Alert>
The Logto React SDK provides you tools and hooks to quickly implement your own authorization flow. First, lets enter your redirect URI
### Configure Redirect URI
First, lets enter your redirect URI. E.g. `http://localhost:1234/callback`.
<UriInputField appId={props.appId} isSingle={!props.isCompact} name="redirectUris" title="Redirect URI" />
Add the following code to your web app
### Implement a sign-in button
We provide two hooks `useHandleSignInCallback()` and `useLogto()` which can help you easily manage the authentication flow.
Go back to your IDE/editor, use the following code to implement the sign-in button:
```tsx
import React from 'react';
import { useLogto } from '@logto/react';
const SignInButton = () => {
const { signIn } = useLogto();
const redirectUrl = window.location.origin + '/callback';
const SignIn = () => {
const { signIn, isAuthenticated } = useLogto();
return <button onClick={() => signIn(redirectUrl)}>Sign In</button>;
};
export default SignInButton;
```
### Step 2: Retrieve Auth Status
```tsx
import React from "react";
import { useLogto } from '@logto/react';
const App = () => {
const { isAuthenticated, signIn } = useLogto();
if !(isAuthenticated) {
return <SignInButton />
if (isAuthenticated) {
return <div>Signed in</div>;
}
return <>
<AppContent />
<SignOutButton />
</>
return (
<button onClick={() => signIn('http://localhost:1234/callback')}>
Sign In
</button>
);
};
```
### Handle redirect
We're almost there! In the last step, we use `http://localhost:1234/callback` as the Redirect URI, and now we need to handle it properly.
First let's create a callback component:
```tsx
import { useHandleSignInCallback } from '@logto/react';
const Callback = () => {
const { isLoading } = useHandleSignInCallback(() => {
// Navigate to root path when finished
});
// When it's working in progress
if (isLoading) {
return <div>Redirecting...</div>;
}
};
```
Finally insert the code below to create a `/callback` route which does NOT require authentication:
```tsx
// Assuming react-router
<Route path="/callback" element={<Callback />} />
```
</Step>
<Step
@ -157,30 +145,31 @@ const App = () => {
onButtonClick={() => props.onNext(4)}
>
Execute signOut() methods will redirect users to the Logto sign out page. After a success sign out, all use session data and auth status will be cleared.
Calling `.signOut()` will clear all the Logto data in memory and localStorage if they exist.
After signing out, it'll be great to redirect user back to your website. Let's add `http://localhost:1234` as the Post Sign-out URI below, and use it as the parameter when calling `.signOut()`.
<UriInputField appId={props.appId} isSingle={!props.isCompact} name="postLogoutRedirectUris" title="Post Sign-out Redirect URI" />
Add the following code to your web app
### Implement a sign-out button
```tsx
import React from 'react';
import { useLogto } from '@logto/react';
const SignOutButton = () => {
const SignOut = () => {
const { signOut } = useLogto();
return <button onClick={() => signOut(window.location.origin)}>Sign out</button>;
return (
<button onClick={() => signOut('http://localhost:1234')}>
Sign out
</button>
);
};
export default SignOutButton;
```
</Step>
<Step
title="Further Readings"
subtitle="3 steps"
title="Further readings"
subtitle="4 articles"
index={4}
activeIndex={props.activeStepIndex}
buttonText="admin_console.general.done"
@ -188,8 +177,9 @@ export default SignOutButton;
onButtonClick={props.onComplete}
>
- [SDK Documentation](https://link-url-here.org)
- [OIDC Documentation](https://link-url-here.org)
- [Calling API to fetch accessToken](https://link-url-here.org)
- [Customize sign-in experience](https://docs.logto.io/docs/recipes/customize-sie)
- [Enable SMS or email passcode sign-in](https://docs.logto.io/docs/tutorials/get-started/enable-passcode-sign-in)
- [Enable social sign-in](https://docs.logto.io/docs/tutorials/get-started/enable-social-sign-in)
- [Protect your API](https://docs.logto.io/docs/recipes/protect-your-api)
</Step>

View file

@ -2,10 +2,11 @@ import UriInputField from '@mdx/components/UriInputField';
import Step from '@mdx/components/Step';
import Tabs from '@mdx/components/Tabs';
import TabItem from '@mdx/components/TabItem';
import Alert from '@/components/Alert';
<Step
title="安装 SDK"
subtitle="选择您熟悉的安装方式"
title="将 Logto SDK 添加至依赖"
subtitle="选择你熟悉的包管理工具"
index={0}
activeIndex={props.activeStepIndex}
onButtonClick={() => props.onNext(1)}
@ -31,156 +32,144 @@ yarn add @logto/react
pnpm add @logto/react
```
</TabItem>
<TabItem value="script" label="script">
```html
<script src="https://logto.io/js/logto-sdk-react/0.1.0/logto-sdk-react.production.js" />
```
</TabItem>
<TabItem value="git" label="Git">
```bash
git clone https://github.com/logto-io/js.git
pnpm build
```
</TabItem>
</Tabs>
</Step>
<Step
title="Initiate LogtoClient"
subtitle="1 step"
title="初始化 LogtoClient"
subtitle="共 1 步"
index={1}
activeIndex={props.activeStepIndex}
onButtonClick={() => props.onNext(2)}
>
在项目的 App.tsx 文件中,加入如下代码(需提前准备好 client ID 以及 authorization domain
Import 并使用 `LogtoProvider` 来提供 Logto context:
<pre>
<code className="language-tsx">
{`import { LogtoProvider, LogtoConfig } from '@logto/react';
import React from 'react';
//...
const config: LogtoConfig = {
endpoint: '${props.endpoint}',
clientId: '${props.appId}',
};
const App = () => {
const config: LogtoConfig = {
clientId: '${props.appId}',
endpoint: '${props.endpoint}',
};
return (
<BrowserRouter>
<LogtoProvider config={config}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/callback" element={<Callback />} />
<Route
path="/protected-resource"
element={
<RequireAuth>
<ProtectedResource />
</RequireAuth>
}
/>
</Routes>
</LogtoProvider>
</BrowserRouter>
);
};`}
const App = () => (
<LogtoProvider config={config}>
<YourAppContent />
</LogtoProvider>
);`}
</code>
</pre>
</Step>
<Step
title="Sign In"
subtitle="2 steps"
title="登录"
subtitle="共 3 步"
index={2}
activeIndex={props.activeStepIndex}
onButtonClick={() => props.onNext(3)}
>
### Step 1: Setup your login
<Alert>
在如下代码示例中, 我们均先假设你的 React 应用运行在 <code>http://localhost:1234</code> 上。
</Alert>
The Logto React SDK provides you tools and hooks to quickly implement your own authorization flow. First, lets enter your redirect URI
### 配置 Redirect URI
首先,我们来添加 Redirect URI`http://localhost:1234/callback`
<UriInputField appId={props.appId} isSingle={!props.isCompact} name="redirectUris" title="Redirect URI" />
Add the following code to your web app
### 实现登录按钮
我们提供了两个 hook 方法 `useHandleSignInCallback()` 和 `useLogto()`,它们可以帮助你轻松完成登录认证流程。
返回你的 IDE 或编辑器,使用如下代码来实现一个登录按钮:
```tsx
import React from 'react';
import { useLogto } from '@logto/react';
const SignInButton = () => {
const { signIn } = useLogto();
const redirectUrl = window.location.origin + '/callback';
const SignIn = () => {
const { signIn, isAuthenticated } = useLogto();
return <button onClick={() => signIn(redirectUrl)}>Sign In</button>;
};
export default SignInButton;
```
### Step 2: Retrieve Auth Status
```tsx
import React from "react";
import { useLogto } from '@logto/react';
const App = () => {
const { isAuthenticated, signIn } = useLogto();
if !(isAuthenticated) {
return <SignInButton />
if (isAuthenticated) {
return <div>已登录</div>;
}
return <>
<AppContent />
<SignOutButton />
</>
return (
<button onClick={() => signIn('http://localhost:1234/callback')}>
登录
</button>
);
};
```
### 处理重定向
马上就要大功告成!在上一步,我们将 `http://localhost:1234/callback` 用作 Redirect URI现在我们需要对其妥善处理。
首先,让我们来创建一个 callback 组件:
```tsx
import { useHandleSignInCallback } from '@logto/react';
const Callback = () => {
const { isLoading } = useHandleSignInCallback(() => {
// 完成时跳转至根路由
});
// 当登录认证尚未完成时
if (isLoading) {
return <div>正在重定向...</div>;
}
};
```
最后我们插入如下代码来实现一个 _无需_ 登录的 `/callback` 路由:
```tsx
// 假设用 react-router
<Route path="/callback" element={<Callback />} />
```
</Step>
<Step
title="Sign Out"
subtitle="1 step"
title="退出登录"
subtitle="共 1 步"
index={3}
activeIndex={props.activeStepIndex}
onButtonClick={() => props.onNext(4)}
>
Execute signOut() methods will redirect users to the Logto sign out page. After a success sign out, all use session data and auth status will be cleared.
调用 `.signOut()` 将清理内存与 localStorage 中的所有 Logto 数据(如果有)。
在退出登录后,让你的用户重新回到你的网站是个不错的选择。让我们将 `http://localhost:1234` 添加至下面的输入框,并将其作为调用 `.signOut()` 的参数。
<UriInputField appId={props.appId} isSingle={!props.isCompact} name="postLogoutRedirectUris" title="Post Sign-out Redirect URI" />
Add the following code to your web app
### 实现退出登录按钮
```tsx
import React from 'react';
import { useLogto } from '@logto/react';
const SignOutButton = () => {
const SignOut = () => {
const { signOut } = useLogto();
return <button onClick={() => signOut(window.location.origin)}>Sign out</button>;
return (
<button onClick={() => signOut('http://localhost:1234')}>
退出登录
</button>
);
};
export default SignOutButton;
```
</Step>
<Step
title="Further Readings"
subtitle="3 steps"
title="延展阅读"
subtitle="共 4 篇"
index={4}
activeIndex={props.activeStepIndex}
buttonText="admin_console.general.done"
@ -188,8 +177,9 @@ export default SignOutButton;
onButtonClick={props.onComplete}
>
- [SDK Documentation](https://link-url-here.org)
- [OIDC Documentation](https://link-url-here.org)
- [Calling API to fetch accessToken](https://link-url-here.org)
- [Customize sign-in experience](https://docs.logto.io/zh-cn/docs/recipes/customize-sie)
- [Enable SMS or email passcode sign-in](https://docs.logto.io/zh-cn/docs/tutorials/get-started/enable-passcode-sign-in)
- [Enable social sign-in](https://docs.logto.io/zh-cn/docs/tutorials/get-started/enable-social-sign-in)
- [Protect your API](https://docs.logto.io/zh-cn/docs/recipes/protect-your-api)
</Step>

View file

@ -83,6 +83,13 @@
font: var(--font-body-medium);
margin: _.unit(6) 0;
}
code:not(pre > code) {
background: var(--color-layer-2);
font: var(--font-body-medium);
padding: _.unit(1) _.unit(1);
border-radius: 4px;
}
}
.card + .card {

View file

@ -4,14 +4,14 @@
display: flex;
align-items: flex-start;
position: relative;
.saveButton {
position: absolute;
left: calc(556px + _.unit(3));
top: 0;
}
}
.field {
width: 556px;
}
.saveButton {
position: absolute;
left: calc(556px + _.unit(3));
top: 0;
}

View file

@ -62,8 +62,17 @@ const Guide = ({ app, isCompact, onClose }: Props) => {
code: ({ className, children }) => {
const [, language] = /language-(\w+)/.exec(className ?? '') ?? [];
return <CodeEditor isReadonly language={language} value={String(children)} />;
return language ? (
<CodeEditor isReadonly language={language} value={String(children)} />
) : (
<code>{String(children)}</code>
);
},
a: ({ children, ...props }) => (
<a {...props} target="_blank" rel="noopener noreferrer">
{children}
</a>
),
}}
>
<Suspense fallback={<StepsSkeleton />}>