mirror of
https://github.com/logto-io/logto.git
synced 2025-01-06 20:40:08 -05:00
refactor(console): update vanilla js integration guide (#6156)
* refactor(console): update vanilla js integration guide * refactor(console): improve content --------- Co-authored-by: Gao Sun <gao@silverhand.io>
This commit is contained in:
parent
b52ef323cb
commit
414f62aed3
1 changed files with 86 additions and 93 deletions
|
@ -5,6 +5,9 @@ import InlineNotification from '@/ds-components/InlineNotification';
|
||||||
import Steps from '@/mdx-components/Steps';
|
import Steps from '@/mdx-components/Steps';
|
||||||
import Step from '@/mdx-components/Step';
|
import Step from '@/mdx-components/Step';
|
||||||
|
|
||||||
|
import Checkpoint from '../../fragments/_checkpoint.md';
|
||||||
|
import RedirectUrisWeb, { defaultRedirectUri, defaultPostSignOutUri } from '../../fragments/_redirect-uris-web.mdx';
|
||||||
|
|
||||||
<Steps>
|
<Steps>
|
||||||
|
|
||||||
<Step
|
<Step
|
||||||
|
@ -18,13 +21,6 @@ import Step from '@/mdx-components/Step';
|
||||||
npm i @logto/browser
|
npm i @logto/browser
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yarn" label="Yarn">
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn add @logto/browser
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="pnpm" label="pnpm">
|
<TabItem value="pnpm" label="pnpm">
|
||||||
|
|
||||||
|
@ -32,6 +28,22 @@ yarn add @logto/browser
|
||||||
pnpm add @logto/browser
|
pnpm add @logto/browser
|
||||||
```
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="yarn" label="yarn">
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn add @logto/browser
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="cdn" label="CDN">
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- Special thanks to jsdelivr -->
|
||||||
|
<script type="module">
|
||||||
|
import LogtoClient from 'https://cdn.jsdelivr.net/npm/@logto/browser@latest/+esm';
|
||||||
|
</script>
|
||||||
|
```
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Step>
|
</Step>
|
||||||
|
@ -40,7 +52,7 @@ pnpm add @logto/browser
|
||||||
|
|
||||||
Import and init `LogtoClient` with configs:
|
Import and init `LogtoClient` with configs:
|
||||||
|
|
||||||
<Code className="language-ts">
|
<Code className="language-ts" title="index.js">
|
||||||
{`import LogtoClient from '@logto/browser';
|
{`import LogtoClient from '@logto/browser';
|
||||||
|
|
||||||
const logtoClient = new LogtoClient({
|
const logtoClient = new LogtoClient({
|
||||||
|
@ -51,116 +63,97 @@ const logtoClient = new LogtoClient({
|
||||||
|
|
||||||
</Step>
|
</Step>
|
||||||
|
|
||||||
<Step
|
<Step title="Configure redirect URIs">
|
||||||
title="Implement sign-in"
|
|
||||||
subtitle="3 steps"
|
|
||||||
>
|
|
||||||
|
|
||||||
<InlineNotification>
|
<RedirectUrisWeb />
|
||||||
In the following steps, we assume your app is running on <code>http://localhost:3000</code>.
|
|
||||||
</InlineNotification>
|
|
||||||
|
|
||||||
### Configure Redirect URI
|
</Step>
|
||||||
|
|
||||||
First, let’s enter your redirect URI. E.g. `http://localhost:3000/callback`.
|
<Step title="Handle redirect">
|
||||||
|
|
||||||
<UriInputField name="redirectUris" />
|
There are still things to do after the user is redirected back to your application from Logto. Let's handle it properly.
|
||||||
|
|
||||||
### Implement a sign-in button
|
```ts title="pages/Callback.js"
|
||||||
|
const callbackHandler = async (logtoClient) => {
|
||||||
|
await logtoClient.handleSignInCallback(window.location.href);
|
||||||
|
|
||||||
Go back to your IDE/editor, use the following code to implement the sign-in button:
|
if (!logtoClient.isAuthenticated) {
|
||||||
|
// Handle failed sign-in
|
||||||
|
alert('Failed to sign in');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
<Code className="language-html">
|
// Handle successful sign-in
|
||||||
{`<button onclick="logtoClient.signIn('${
|
window.location.assign('/');
|
||||||
props.redirectUris[0] ?? 'http://localhost:3000/callback'
|
};
|
||||||
}')">
|
|
||||||
Sign In
|
|
||||||
</button>`}
|
|
||||||
</Code>
|
|
||||||
|
|
||||||
### Handle redirect
|
|
||||||
|
|
||||||
We're almost there! In the last step, we use `http://localhost:3000/callback` as the Redirect URI, and now we need to handle it properly.
|
|
||||||
|
|
||||||
Insert the code below in your `/callback` route:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
await logtoClient.handleSignInCallback(window.location.href);
|
|
||||||
|
|
||||||
if (!logtoClient.isAuthenticated) {
|
|
||||||
// Handle failed sign-in
|
|
||||||
alert('Failed to sign in');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle successful sign-in. E.g. redirect to home page.
|
|
||||||
window.location.assign('http://localhost:3000/');
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you can test the sign-in flow.
|
|
||||||
|
|
||||||
</Step>
|
</Step>
|
||||||
|
|
||||||
<Step title="Implement sign-out">
|
<Step title="Implement sign-in and sign-out">
|
||||||
|
|
||||||
Calling `.signOut()` will clear all the Logto data in memory and localStorage if they exist.
|
`logtoClient` provides `signIn` and `signOut` methods to help you easily manage the authentication flow.
|
||||||
|
|
||||||
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, and use it as the parameter when calling `.signOut()`.
|
<Code className="language-js" title="pages/Home.js">
|
||||||
|
{`const isAuthenticated = await logtoClient.isAuthenticated();
|
||||||
|
|
||||||
<UriInputField
|
const onClickSignIn = () => {
|
||||||
appId={props.app.id}
|
logtoClient.signIn('${props.redirectUris[0] ?? defaultRedirectUri}');
|
||||||
name="postLogoutRedirectUris"
|
};
|
||||||
title="application_details.post_sign_out_redirect_uri"
|
const onClickSignOut = () => {
|
||||||
/>
|
logtoClient.signOut('${props.postLogoutRedirectUris[0] ?? defaultPostSignOutUri}');
|
||||||
|
};
|
||||||
### Implement a sign-out button
|
|
||||||
|
|
||||||
<Code className="language-html">
|
|
||||||
{`<button onclick="logtoClient.signOut('${
|
|
||||||
props.postLogoutRedirectUris[0] ?? 'http://localhost:3000'
|
|
||||||
}')">
|
|
||||||
Sign Out
|
|
||||||
</button>`}
|
|
||||||
</Code>
|
|
||||||
|
|
||||||
</Step>
|
|
||||||
|
|
||||||
<Step title="Handle authentication status">
|
|
||||||
|
|
||||||
In Logto SDK, generally we can use `logtoClient.isAuthenticated` to check the authentication status, if the user is signed in, the value will be `true`, otherwise, the value will be `false`.
|
|
||||||
|
|
||||||
In your vanilla JS app, you can use the `isAuthenticated` status to programmatically show and hide the sign-in and sign-out buttons. Let's see how to do it.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
const redirectUrl = 'http://localhost:3000/callback';
|
|
||||||
const baseUrl = 'http://localhost:3000';
|
|
||||||
|
|
||||||
// Conditional rendering of sign-in and sign-out buttons
|
|
||||||
const isAuthenticated = await logtoClient.isAuthenticated();
|
|
||||||
|
|
||||||
// Assuming there's a div with id 'container' in your HTML
|
|
||||||
const container = document.querySelector('#container');
|
|
||||||
|
|
||||||
const onClickSignIn = () => logtoClient.signIn(redirectUrl);
|
|
||||||
const onClickSignOut = () => logtoClient.signOut(baseUrl);
|
|
||||||
|
|
||||||
const button = document.createElement('button');
|
const button = document.createElement('button');
|
||||||
button.innerHTML = isAuthenticated ? 'Sign Out' : 'Sign In';
|
button.innerHTML = isAuthenticated ? 'Sign Out' : 'Sign In';
|
||||||
button.addEventListener('click', isAuthenticated ? onClickSignOut : onClickSignIn);
|
button.addEventListener('click', isAuthenticated ? onClickSignOut : onClickSignIn);
|
||||||
|
|
||||||
container.append(button);
|
document.body.appendChild(button);`}
|
||||||
```
|
</Code>
|
||||||
|
|
||||||
|
Calling `.signOut()` will clear all the Logto data in memory and `localStorage` if they exist.
|
||||||
|
|
||||||
</Step>
|
</Step>
|
||||||
|
|
||||||
<Step title="Checkpoint: Test your application">
|
<Step title="Checkpoint: Test your application">
|
||||||
|
|
||||||
Now, you can test your application:
|
<Checkpoint />
|
||||||
|
|
||||||
1. Run your application, you will see the sign-in button.
|
</Step>
|
||||||
2. Click the sign-in button, the SDK will init the sign-in process and redirect you to the Logto sign-in page.
|
|
||||||
3. After you signed in, you will be redirected back to your application and see user ID and the sign-out button.
|
<Step title="Display user information">
|
||||||
4. Click the sign-out button to sign-out.
|
|
||||||
|
To display the user's information, you can use the `logtoClient.getIdTokenClaims()` method. For example, in your Home page:
|
||||||
|
|
||||||
|
```js title="pages/Home.js"
|
||||||
|
const userInfo = await logtoClient.getIdTokenClaims();
|
||||||
|
|
||||||
|
// Generate display table for ID token claims
|
||||||
|
const table = document.createElement('table');
|
||||||
|
const thead = document.createElement('thead');
|
||||||
|
const tr = document.createElement('tr');
|
||||||
|
const thName = document.createElement('th');
|
||||||
|
const thValue = document.createElement('th');
|
||||||
|
thName.innerHTML = 'Name';
|
||||||
|
thValue.innerHTML = 'Value';
|
||||||
|
tr.append(thName, thValue);
|
||||||
|
thead.append(tr);
|
||||||
|
table.append(thead);
|
||||||
|
|
||||||
|
const tbody = document.createElement('tbody');
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(userInfo)) {
|
||||||
|
const tr = document.createElement('tr');
|
||||||
|
const tdName = document.createElement('td');
|
||||||
|
const tdValue = document.createElement('td');
|
||||||
|
tdName.innerHTML = key;
|
||||||
|
tdValue.innerHTML = typeof value === 'string' ? value : JSON.stringify(value);
|
||||||
|
tr.append(tdName, tdValue);
|
||||||
|
tbody.append(tr);
|
||||||
|
}
|
||||||
|
|
||||||
|
table.append(tbody);
|
||||||
|
```
|
||||||
|
|
||||||
</Step>
|
</Step>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue