0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-04-07 23:01:25 -05:00

refactor(console): improve m2m app guide content (#4525)

This commit is contained in:
Charles Zhao 2023-09-16 10:48:39 +08:00 committed by GitHub
parent 57d564b153
commit 9bf591555e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 18 additions and 14 deletions

View file

@ -5,15 +5,18 @@ import ApplicationCredentials from '@/mdx-components/ApplicationCredentials';
import EnableAdminAccess from './components/EnableAdminAccess';
import EnableAdminAccessSrc from './assets/enable-admin-access.png';
import AppIdentifierSrc from './assets/api-identifier.png';
import { appendPath } from '@silverhand/essentials';
<Steps>
<Step title="Intro">
Machine-to-machine (M2M) is a common practice to authenticate if you have an app that needs to directly talks to resources. E.g., an API service that updates users' custom data in Logto, a statistic service that pulls daily orders, etc.
Usually, an M2M app doesn't need user interactions, i.e., it has no UI.
</Step>
<Step title="Locate the app ID and app secret">
Get your App ID and App Secret.
<ApplicationCredentials />
@ -43,7 +46,7 @@ In the API Resource tab, find the API identifier that the app needs to access. I
<ul>
<li>
Use Token Endpoint <code>{`${props.endpoint}/oidc/token`}</code> as the request endpoint, and
Use Token Endpoint <code>{`${appendPath(props.alternativeEndpoint ?? props.endpoint), '/oidc/token'}`}</code> as the request endpoint, and
use POST as the method.
</li>
<li>
@ -54,12 +57,12 @@ In the API Resource tab, find the API identifier that the app needs to access. I
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization#basic_authentication">
Basic authentication
</a>
, where username is the App ID, and password is the App Secret.
, where username is the App ID, and password is the App Secret. The credential is the username and password combined with a colon, encoded in base64.
</li>
<li>Carry the body data</li>
</ul>
```jsonc
```json
{
"grant_type": "client_credentials",
"resource": "https://shopping.api", // Replace with your API identifier
@ -72,8 +75,8 @@ If you are using cURL:
<pre>
<code className="language-bash">
{`curl --location
--request POST '${props.endpoint}/oidc/token'
--header 'Authorization: Basic eW91ci1hcHAtaWQ6eW91ci1hcHAtc2VjcmV0'
--request POST '${appendPath(props.alternativeEndpoint ?? props.endpoint, '/oidc/token')}'
--header 'Authorization: Basic ${Buffer.from(`${props.app.id}:${props.app.secret}`).toString('base64')}'
--header 'Content-Type: application/x-www-form-urlencoded'
--data-urlencode 'grant_type=client_credentials'
--data-urlencode 'resource=https://shopping.api'
@ -86,7 +89,7 @@ If you are using cURL:
A successful response body would be like:
```jsonc
```json
{
"access_token": "eyJhbG...2g", // Use this token for accessing the resource
"expires_in": 3600, // Token expiration in seconds
@ -104,7 +107,7 @@ For example, if you have requested an Access Token with the resource `https://ap
<pre>
<code className="language-bash">
{`curl --location
--request GET '${props.endpoint}/api/applications'
--request GET '${appendPath(props.alternativeEndpoint ?? props.endpoint, '/api/applications')}'
--header 'Authorization: Bearer eyJhbG...2g' # Access Token
`}
</code>

View file

@ -5,5 +5,5 @@
}
.container {
padding: _.unit(6) 0;
margin: _.unit(6) 0;
}

View file

@ -1,4 +1,4 @@
import { DomainStatus, type ApplicationResponse } from '@logto/schemas';
import { type ApplicationResponse } from '@logto/schemas';
import { conditional } from '@silverhand/essentials';
import { useContext, useMemo } from 'react';
@ -17,8 +17,7 @@ type Props = {
function AppGuide({ className, guideId, app, isCompact, onClose }: Props) {
const { tenantEndpoint } = useContext(AppDataContext);
const { data: customDomain } = useCustomDomain();
const isCustomDomainActive = customDomain?.status === DomainStatus.Active;
const { data: customDomain, applyDomain: applyCustomDomain } = useCustomDomain();
const guide = guides.find(({ id }) => id === guideId);
const memorizedContext = useMemo(
@ -29,8 +28,10 @@ function AppGuide({ className, guideId, app, isCompact, onClose }: Props) {
metadata: guide.metadata,
Logo: guide.Logo,
app,
endpoint: tenantEndpoint?.toString() ?? '',
alternativeEndpoint: conditional(isCustomDomainActive && customDomain.domain),
endpoint: tenantEndpoint?.href ?? '',
alternativeEndpoint: conditional(
customDomain && applyCustomDomain(tenantEndpoint?.href ?? '')
),
redirectUris: app.oidcClientMetadata.redirectUris,
postLogoutRedirectUris: app.oidcClientMetadata.postLogoutRedirectUris,
isCompact: Boolean(isCompact),
@ -40,7 +41,7 @@ function AppGuide({ className, guideId, app, isCompact, onClose }: Props) {
},
}
) satisfies GuideContextType | undefined,
[guide, app, tenantEndpoint, isCustomDomainActive, customDomain?.domain, isCompact]
[guide, app, tenantEndpoint?.href, customDomain, applyCustomDomain, isCompact]
);
return memorizedContext ? (