Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: vanilla js sdk guide #731

Merged
merged 4 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 4 additions & 15 deletions docs/quick-starts/framework/vanilla-js/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ import ApiResources from './_api-resources.mdx';
import CheckIntegration from './_check-integration.mdx';
import GetUserInformation from './_get-user-information.mdx';
import GuideTip from './_guide-tip.mdx';
import HandleAuthenticationStatus from './_handle-authentication-status.mdx';
import ImplementSignIn from './_implement-sign-in.mdx';
import ImplementSignOut from './_implement-sign-out.mdx';
import ImplementSignInAndSignOut from './_implement-sign-in-and-sign-out.mdx';
import InitClient from './_init-client.mdx';

# Vanilla JS SDK guide

Vanilla JS: Integrate `@logto/browser`

<GuideTip />
Expand All @@ -37,17 +37,7 @@ Vanilla JS: Integrate `@logto/browser`

<InitClient />

### Implement sign-in

<ImplementSignIn />

### Implement sign-out

<ImplementSignOut />

### Handle authentication status

<HandleAuthenticationStatus />
<ImplementSignInAndSignOut />

### Checkpoint: Test your application

Expand All @@ -64,4 +54,3 @@ Vanilla JS: Integrate `@logto/browser`
## Further readings

<FurtherReadings />
./code/_scopes-and-claims-code.mdx./code/_config-resources-with-shared-scopes-code.mdx./code/_config-resources-with-scopes-code.mdx./code/_config-organization-code.mdx
20 changes: 16 additions & 4 deletions docs/quick-starts/framework/vanilla-js/_add-sdk.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import TabItem from '@theme/TabItem';
import Tabs from '@theme/Tabs';

Choose your favorite package manager or use the CDN to install the Logto Browser SDK.

<Tabs>

<TabItem value="npm" label="npm">
Expand All @@ -10,17 +12,27 @@ npm i @logto/browser
```

</TabItem>
<TabItem value="yarn" label="Yarn">
<TabItem value="pnpm" label="pnpm">

```bash
yarn add @logto/browser
pnpm add @logto/browser
```

</TabItem>
<TabItem value="pnpm" label="pnpm">
<TabItem value="yarn" label="yarn">

```bash
pnpm add @logto/browser
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/[email protected]/+esm';
</script>
```

</TabItem>
Expand Down
8 changes: 8 additions & 0 deletions docs/quick-starts/framework/vanilla-js/_api-resources.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,11 @@ import GetOrganizationAccessTokenCode from './code/_get-organization-access-toke
getOrganizationAccessTokenCode={<GetOrganizationAccessTokenCode />}
/>
./code/_scopes-and-claims-code.mdx./code/_config-organization-code.mdx

### Attach access token to request headers

Put the token in the `Authorization` field of HTTP headers with the Bearer format (`Bearer YOUR_TOKEN`), and you are good to go.

:::note
The Bearer Token's integration flow may vary based on the framework or requester you are using. Choose your own way to apply the request `Authorization` header.
:::
81 changes: 76 additions & 5 deletions docs/quick-starts/framework/vanilla-js/_get-user-information.mdx
Original file line number Diff line number Diff line change
@@ -1,9 +1,80 @@
import GetUserInfoApis from '../../fragments/_get-user-info-apis.mdx';
import CodeBlock from '@theme/CodeBlock';

import ClaimsNeedNetworkRequest from '../../fragments/_claims-need-network-request.mdx';
import FindUserInfoMissing from '../../fragments/_find-user-info-missing.mdx';
import ScopesAndClaims from '../../fragments/_scopes-and-claims.mdx';
import ScopesAndClaimsIntroduction from '../../fragments/_scopes-claims-introduction.md';

### Display user information

To display the user's information, you can use the `logtoClient.getIdTokenClaims()` method. For example, in your Home page:

```js title="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);
```

### Request additional claims

<FindUserInfoMissing method="getIdTokenClaims()" />

<ScopesAndClaimsIntroduction />

To request additional scopes, you can configure the Logto configs:

```js title="index.js"
// highlight-next-line
import LogtoClient, { UserScope } from '@logto/browser';

const logtoClient = new LogtoClient({
appId: '<your-application-id>',
endpoint: '<your-logto-endpoint>',
// highlight-next-line
scopes: [UserScope.Email, UserScope.Phone],
});
```

Then you can access the additional claims in the return value of `logtoClient.getIdTokenClaims()`:

```ts
const claims = await getIdTokenClaims();
// Now you can access additional claims `claims.email`, `claims.phone`, etc.
```

import ScopesAndClaimsCode from './code/_scopes-and-claims-code.mdx';
<ClaimsNeedNetworkRequest
type="method"
method="logtoClient.fetchUserInfo()"
codeSnippet={
<CodeBlock language="js">{`const userInfo = await logtoClient.fetchUserInfo();
// Now you can access the claim \`userInfo.custom_data\``}</CodeBlock>
}
/>

<GetUserInfoApis getIdTokenClaimsApi="getIdTokenClaims" fetchUserInfoApi="fetchUserInfo" />
### Scopes and claims

<ScopesAndClaims configScopesCode={<ScopesAndClaimsCode package={props.package} />} />
./code/_scopes-and-claims-code.mdx./code/_config-resources-with-shared-scopes-code.mdx./code/_config-resources-with-scopes-code.mdx./code/_config-organization-code.mdx
<ScopesAndClaims />
6 changes: 3 additions & 3 deletions docs/quick-starts/framework/vanilla-js/_handle-redirect.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
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. Call the callback handler in your SPA's `/callback` route to complete the sign-in flow.
There are still things to do after the user is redirected back to your application from Logto. Let's handle it properly.

```js
```js title="pages/Callback.js"
const callbackHandler = async (logtoClient) => {
await logtoClient.handleSignInCallback(window.location.href);

Expand All @@ -11,6 +11,6 @@ const callbackHandler = async (logtoClient) => {
}

// Handle successful sign-in
window.location.assign('http://localhost:3000/');
window.location.assign('/');
};
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import SignInNote from '../../fragments/_sign-in-note.mdx';
import AssumingUrl from '../../fragments/_web-assuming-url.md';
import WebConfigureRedirectUris from '../../fragments/_web-configure-redirect-uris.mdx';
import SignInFlowSummary from '../../fragments/_web-sign-in-flow-summary.mdx';
import SignOutNote from '../../fragments/_web-sign-out-note.md';

import HandleRedirect from './_handle-redirect.mdx';

### Configure redirect URIs

<SignInFlowSummary />

<AssumingUrl />

<WebConfigureRedirectUris />

### Handle redirect

<HandleRedirect />

### Implement sign-in and sign-out

`logtoClient` provides `signIn` and `signOut` methods to help you easily manage the authentication flow.

<SignInNote calling=".signIn()" />

```js title="pages/Home.js"
const isAuthenticated = await logtoClient.isAuthenticated();

const onClickSignIn = () => {
logtoClient.signIn('http://localhost:3000/callback');
};
const onClickSignOut = () => {
logtoClient.signOut('http://localhost:3000');
};

const button = document.createElement('button');
button.innerHTML = isAuthenticated ? 'Sign Out' : 'Sign In';
button.addEventListener('click', isAuthenticated ? onClickSignOut : onClickSignIn);

document.body.appendChild(button);
```

<SignOutNote />
36 changes: 0 additions & 36 deletions docs/quick-starts/framework/vanilla-js/_implement-sign-in.mdx

This file was deleted.

8 changes: 3 additions & 5 deletions docs/quick-starts/framework/vanilla-js/_init-client.mdx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import AssumingUrl from '../../fragments/_web-assuming-url.md';

Import and init a `LogtoClient` instance by passing config:

```ts
```ts title="index.js"
import LogtoClient from '@logto/browser';

const logtoClient = new LogtoClient({
endpoint: '<your-logto-endpoint>', // E.g. http://localhost:3001
endpoint: '<your-logto-endpoint>',
appId: '<your-application-id>',
});
```

<AssumingUrl />
The `endpoint` and `appId` can be found in the application details page in Logto Console.
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{/* eslint-disable prettier/prettier */}
import CodeBlock from '@theme/CodeBlock';

<CodeBlock language='js'>{`import LogtoClient, { UserScope } from '${props.package || '@logto/browser'}';
<CodeBlock language='js' title="index.js">{`import LogtoClient, { UserScope } from '${props.package || '@logto/browser'}';

const logtoClient = new LogtoClient({
endpoint,
appId,
resources: resourceIndicators,
scopes: [UserScope.Organizations],
// ...other configs
scopes: [UserScope.Organizations],
});`}</CodeBlock>
{/* eslint-enable prettier/prettier */}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
```js
const resources = ['http://localhost:3001/api/test']; // Replace with your own resource indicators registered in Logto dashboard
```js title="index.js"
import LogtoClient from '@logto/browser';

const logtoClient = new LogtoClient({
endpoint,
appId,
resources: resourceIndicators,
// ...other configs
// highlight-next-line
resources: ['https://shopping.your-app.com/api', 'https://store.your-app.com/api'], // Add API resources
});
```
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
{/* eslint-disable prettier/prettier */}
import CodeBlock from '@theme/CodeBlock';

<CodeBlock language='js'>{`import LogtoClient, { UserScope } from '${props.package || '@logto/browser'}';

const resources = ['http://localhost:3001/api/test']; // Replace with your own resource indicators registered in Logto dashboard
const resourceScopes = ['read', 'write']; // Replace with your own resource scopes defined in Logto dashboard under the resources listed above
<CodeBlock language='js' title='index.js'>{`import LogtoClient from '${props.package || '@logto/browser'}';

const logtoClient = new LogtoClient({
endpoint,
appId,
resources: resourceIndicators,
scopes: [
UserScope.Email,
UserScope.Phone,
UserScope.CustomData,
UserScope.Identities,
...resourceScopes,
],
// ...other configs
// highlight-start
scopes: ['shopping:read', 'shopping:write', 'store:read', 'store:write'],
resources: ['https://shopping.your-app.com/api', 'https://store.your-app.com/api'], // Add API resources
// highlight-end
});`}</CodeBlock>
{/* eslint-enable prettier/prettier */}
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
{/* eslint-disable prettier/prettier */}
import CodeBlock from '@theme/CodeBlock';

<CodeBlock language='js'>{`import LogtoClient, { UserScope } from '${props.package || '@logto/browser'}';

const resources = ['http://localhost:3001/api/test', 'http://localhost:5001/api/test']; // Replace with your own resource indicators registered in Logto dashboard
const resourceScopes = ['read', 'write']; // Shared scopes for all the resources. (Declare these scopes in Logto dashboard under all the resources listed above)
<CodeBlock language='js' title='index.js'>{`import LogtoClient, { UserScope } from '${props.package || '@logto/browser'}';

const logtoClient = new LogtoClient({
endpoint,
appId,
resources: resourceIndicators,
scopes: [
UserScope.Email,
UserScope.Phone,
UserScope.CustomData,
UserScope.Identities,
...resourceScopes,
],
// ...other configs
// highlight-start
scopes: ['read', 'write'],
resources: ['https://shopping.your-app.com/api', 'https://store.your-app.com/api'],
// highlight-end
});`}</CodeBlock>
{/* eslint-enable prettier/prettier */}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
```js
// e.g. Get the access token for the API resource http://localhost:3000/api/test

const accessToken = await logtoClient.getAccessToken('http://localhost:3000/api/test');
const accessToken = await logtoClient.getAccessToken('https://store.your-app.com/api');
console.log('Access token', accessToken);
```
Loading
Loading