-
Notifications
You must be signed in to change notification settings - Fork 33
Open
Description
So far enjoying stytch so thank you for the hard work.
A few things I have noticed. The shape of the decoded JWT is not typed, cannot seem to find in the B2B lib. I decided to make my own, but running into some interface mismatches with what I would expect.
// stytch-decoded-session-jwt.ts
import { MemberSession } from "stytch";
export interface DecodedStytchSessionJwt {
// Custom Claims, Configured on https://stytch.com/dashboard/custom-claim-templates
memberId: string;
orgId: string;
emailAddress: string;
// Reserved
aud: string[];
exp: number;
iat: number;
iss: string;
nbf: number;
sub: string;
// Organization details
"https://stytch.com/organization": {
organization_id: string;
slug: string;
};
// Session Object
"https://stytch.com/session": MemberSession;
}
Here is an example decoded JWT that I received from a B2B auth.
{
"aud": [
"[REDACTED]"
],
"emailAddress": "[REDACTED]",
"exp": "[REDACTED]",
"https://stytch.com/organization": {
"organization_id": "[REDACTED]",
"slug": "[REDACTED]"
},
"https://stytch.com/session": {
"id": "[REDACTED]",
"started_at": "2025-01-18T20:52:01Z",
"last_accessed_at": "2025-01-18T20:52:01Z",
"expires_at": "2025-01-18T21:52:01Z",
"attributes": {
"user_agent": "[REDACTED]",
"ip_address": "[REDACTED]"
},
"authentication_factors": [
{
"type": "oauth",
"delivery_method": "oauth_google",
"last_authenticated_at": "2025-01-18T20:51:45Z",
"google_oauth_factor": {
"id": "[REDACTED]",
"email_id": "[REDACTED]",
"provider_subject": "[REDACTED]"
}
}
],
"roles": [
"stytch_member",
"stytch_admin"
]
},
"iat": "[REDACTED]",
"iss": "[REDACTED]",
"memberId": "[REDACTED]",
"nbf": "[REDACTED]",
"orgId": "[REDACTED]",
"orgSlug": null,
"sub": "[REDACTED]"
}
Two issues:
- The decoded JWT type is opaque
- session_custom claims are not appearing as expected. The MemberSession suggests custom claims lives on a
custom_claimsfield on the session object, whereas in the actual decoded JWT, the custom claims are flattened onto the decoded JWT object. No preference on where they live, but given that the jwt actually encodes the member session my expectation given the MemberSession type would be that they would live on the session object.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels