mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
[Open this suggestion in Promptless to view citations and reasoning process](https://app.gopromptless.ai/change-history/ea7c7471-778d-42ea-9845-fa380f013560) Documents the new `is_restricted` and `restricted_reason` JWT claims introduced for the onboarding/restricted users feature. Updates the JWT documentation to explain these fields in the claims section, adds them to the example payload, documents the restricted user token structure, and adds the `include_restricted` JWKS parameter for manual token verification. ### Trigger Events <details> <summary><a href="e400985754...de0f937f46">stack-auth/stack-auth commit (dev):de0f937[CHANGELOG] - 2026.01.21</a></summary> <br> **Promptless Research** (1 webpage, 1 GitHub PR) - [Read webpage from github.com](e400985754...de0f937f46) - [Reviewed stack-auth/stack-auth#1069](https://github.com/stack-auth/stack-auth/pull/1069) **Agent Response** > I've completed my analysis of the changelog entry and created the necessary documentation update. > > ## Summary > > After reviewing the changelog entry for **2026.01.21**, I identified: > > ### Already Covered by Existing Suggestions > The payment-related items were already documented by existing suggestions: > - **Payments Settings page** → covered by the "Document payment settings" suggestion > - **Subscription renewal emails** → covered by the "Document payment email templates" suggestion > - **Invoice visibility** → covered by the "Document invoice listing feature" suggestion > > ### New Documentation Created > I created a new suggestion to address the remaining item: **"Updated JWT documentation to include `isRestricted` and `restrictedReason`"** > > The suggestion updates the JWT Tokens documentation with: > - **New claims documentation**: Added `is_restricted` (boolean) and `restricted_reason` (nullable object with `type` field) to the Stack Auth Specific Claims section > - **Updated example payload**: Added the new fields to the example JWT payload > - **Restricted user tokens**: Documented how restricted user tokens differ (`:restricted` audience suffix) > - **JWKS parameter**: Added documentation for the `include_restricted=true` parameter in the Manual JWT Verification section > > These fields were introduced in PR #1069 "Onboarding app & restricted users" to support the new onboarding flow where users who haven't completed requirements (like email verification) are marked as "restricted." </details> --- **Help us improve Promptless** — If this suggestion missed the mark, please [share quick feedback](https://app.gopromptless.ai/change-history/ea7c7471-778d-42ea-9845-fa380f013560?openFeedback=1). *If you want Promptless to make further changes on this PR, feel free to leave a comment tagging Promptless (It won't show up in the user drop down but Promptless will get it!)* --------- Co-authored-by: promptless[bot] <179508745+promptless[bot]@users.noreply.github.com> Co-authored-by: Madison <madison.w.kennedy@gmail.com>
141 lines
3.8 KiB
TypeScript
141 lines
3.8 KiB
TypeScript
import { CodeExample } from '../../lib/code-examples';
|
|
|
|
export const jwtExamples = {
|
|
'client-side-usage': [
|
|
{
|
|
language: 'JavaScript',
|
|
framework: 'Next.js',
|
|
code: `import { useUser } from '@stackframe/stack';
|
|
|
|
export function UserProfile() {
|
|
const user = useUser();
|
|
|
|
if (!user) {
|
|
return <div>Please sign in</div>;
|
|
}
|
|
|
|
return <div>Welcome, {user.displayName}!</div>;
|
|
}`,
|
|
highlightLanguage: 'tsx',
|
|
filename: 'app/components/user-profile.tsx'
|
|
},
|
|
{
|
|
language: 'JavaScript',
|
|
framework: 'React',
|
|
code: `import { useUser } from '@stackframe/react';
|
|
|
|
export function UserProfile() {
|
|
const user = useUser();
|
|
|
|
if (!user) {
|
|
return <div>Please sign in</div>;
|
|
}
|
|
|
|
return <div>Welcome, {user.displayName}!</div>;
|
|
}`,
|
|
highlightLanguage: 'tsx',
|
|
filename: 'components/UserProfile.tsx'
|
|
},
|
|
] as CodeExample[],
|
|
|
|
'server-side-usage': [
|
|
{
|
|
language: 'JavaScript',
|
|
framework: 'Next.js',
|
|
code: `import { stackServerApp } from '@/stack';
|
|
|
|
export async function GET() {
|
|
const user = await stackServerApp.getUser();
|
|
|
|
if (!user) {
|
|
return new Response('Unauthorized', { status: 401 });
|
|
}
|
|
|
|
// Access user information from the JWT
|
|
return Response.json({
|
|
id: user.id,
|
|
displayName: user.displayName,
|
|
primaryEmail: user.primaryEmail,
|
|
selectedTeamId: user.selectedTeamId,
|
|
// Other user properties...
|
|
});
|
|
}`,
|
|
highlightLanguage: 'typescript',
|
|
filename: 'app/api/user/route.ts'
|
|
},
|
|
] as CodeExample[],
|
|
|
|
'manual-jwt-verification': [
|
|
{
|
|
language: 'JavaScript',
|
|
framework: 'Node.js',
|
|
code: `import * as jose from 'jose';
|
|
|
|
// Get the public key set from Stack Auth
|
|
const jwks = jose.createRemoteJWKSet(
|
|
new URL('https://api.stack-auth.com/api/v1/projects/YOUR_PROJECT_ID/.well-known/jwks.json')
|
|
);
|
|
|
|
// Verify a regular (non-anonymous) access token
|
|
try {
|
|
const { payload } = await jose.jwtVerify(token, jwks, {
|
|
issuer: 'https://api.stack-auth.com/api/v1/projects/YOUR_PROJECT_ID',
|
|
audience: 'YOUR_PROJECT_ID',
|
|
});
|
|
|
|
console.log('JWT is valid:', payload);
|
|
} catch (error) {
|
|
console.error('JWT verification failed:', error);
|
|
}`,
|
|
highlightLanguage: 'typescript',
|
|
filename: 'verify-jwt.ts'
|
|
},
|
|
] as CodeExample[],
|
|
|
|
'manual-jwt-verification-anonymous': [
|
|
{
|
|
language: 'JavaScript',
|
|
framework: 'Node.js',
|
|
code: `import * as jose from 'jose';
|
|
|
|
const jwks = jose.createRemoteJWKSet(
|
|
new URL('https://api.stack-auth.com/api/v1/projects/YOUR_PROJECT_ID/.well-known/jwks.json?include_anonymous=true')
|
|
);
|
|
|
|
const { payload } = await jose.jwtVerify(token, jwks, {
|
|
issuer: [
|
|
'https://api.stack-auth.com/api/v1/projects/YOUR_PROJECT_ID',
|
|
'https://api.stack-auth.com/api/v1/projects-anonymous-users/YOUR_PROJECT_ID',
|
|
],
|
|
audience: ['YOUR_PROJECT_ID', 'YOUR_PROJECT_ID:anon'],
|
|
});`,
|
|
highlightLanguage: 'typescript',
|
|
filename: 'verify-jwt.ts'
|
|
},
|
|
] as CodeExample[],
|
|
|
|
'manual-jwt-verification-restricted': [
|
|
{
|
|
language: 'JavaScript',
|
|
framework: 'Node.js',
|
|
code: `import * as jose from 'jose';
|
|
|
|
const jwks = jose.createRemoteJWKSet(
|
|
new URL('https://api.stack-auth.com/api/v1/projects/YOUR_PROJECT_ID/.well-known/jwks.json?include_anonymous=true&include_restricted=true')
|
|
);
|
|
|
|
// All three user types have different issuers
|
|
const { payload } = await jose.jwtVerify(token, jwks, {
|
|
issuer: [
|
|
'https://api.stack-auth.com/api/v1/projects/YOUR_PROJECT_ID',
|
|
'https://api.stack-auth.com/api/v1/projects-anonymous-users/YOUR_PROJECT_ID',
|
|
'https://api.stack-auth.com/api/v1/projects-restricted-users/YOUR_PROJECT_ID',
|
|
],
|
|
audience: ['YOUR_PROJECT_ID', 'YOUR_PROJECT_ID:anon', 'YOUR_PROJECT_ID:restricted'],
|
|
});`,
|
|
highlightLanguage: 'typescript',
|
|
filename: 'verify-jwt.ts'
|
|
},
|
|
] as CodeExample[],
|
|
};
|