feat(stytch-auth): Add support for custom domain usage (#1267)

* feat(stytch-auth): Add support for custom domain usage

* clarify environment variable usage
pull/1268/head
Max Gerber 2025-06-26 14:27:26 -07:00 committed by GitHub
parent fe1e1851e9
commit 8196e225e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 35 additions and 4 deletions

View File

@ -0,0 +1,5 @@
---
'@hono/stytch-auth': patch
---
Add support for custom domain usage by setting the STYTCH_DOMAIN environment variable

View File

@ -262,6 +262,14 @@ app.get('/advanced-org-ops', async (c) => {
### Custom Configuration
**Custom Base URL:**
Set `STYTCH_DOMAIN` as an environment variable to instruct the SDK to use your [custom domain](https://stytch.com/docs/guides/custom-domains/overview) for all API calls.
```bash
STYTCH_DOMAIN=https://login.example.com
```
**Custom Cookie Name:**
```ts

View File

@ -46,9 +46,10 @@ vi.mock(import('stytch'), async (importOriginal) => {
// Forcing the mocked class constructor to be a real type causes tsc to crash
// e.g. same error as https://github.com/microsoft/TypeScript/issues/52952 but probably different bug
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const ConsumerClient: any = vi.fn(function (this: any, { project_id, secret }) {
const ConsumerClient: any = vi.fn(function (this: any, { project_id, secret, custom_base_url }) {
this.project_id = project_id
this.secret = secret
this.custom_base_url = custom_base_url
this.sessions = ConsumerSessions
this.idp = ConsumerOAuth
})
@ -56,9 +57,10 @@ vi.mock(import('stytch'), async (importOriginal) => {
// Forcing the mocked class constructor to be a real type causes tsc to crash
// e.g. same error as https://github.com/microsoft/TypeScript/issues/52952 but probably different bug
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const B2BClientMock: any = vi.fn(function (this: any, { project_id, secret }) {
const B2BClientMock: any = vi.fn(function (this: any, { project_id, secret, custom_base_url }) {
this.project_id = project_id
this.secret = secret
this.custom_base_url = custom_base_url
this.sessions = B2BSessions
this.idp = B2BIdp
})
@ -77,6 +79,7 @@ describe('Consumer', () => {
beforeEach(() => {
vi.stubEnv('STYTCH_PROJECT_ID', 'project-test-xxxxx')
vi.stubEnv('STYTCH_PROJECT_SECRET', 'secret-key-test-xxxxx')
vi.stubEnv('STYTCH_DOMAIN', 'https://login.example.com')
})
describe('getClient', () => {
test('Instantiates client from ctx for handlers to use', async () => {
@ -86,7 +89,11 @@ describe('Consumer', () => {
app.get('/', (ctx) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const client = Consumer.getClient(ctx) as any
return ctx.json({ project_id: client.project_id, secret: client.secret })
return ctx.json({
project_id: client.project_id,
secret: client.secret,
custom_base_url: client.custom_base_url,
})
})
const response = await app.request(req)
@ -95,6 +102,7 @@ describe('Consumer', () => {
expect(await response.json()).toEqual({
project_id: 'project-test-xxxxx',
secret: 'secret-key-test-xxxxx',
custom_base_url: 'https://login.example.com',
})
})
})
@ -488,6 +496,7 @@ describe('B2B', () => {
beforeEach(() => {
vi.stubEnv('STYTCH_PROJECT_ID', 'project-test-b2b-xxxxx')
vi.stubEnv('STYTCH_PROJECT_SECRET', 'secret-key-test-b2b-xxxxx')
vi.stubEnv('STYTCH_DOMAIN', 'https://login.example.com')
})
describe('getClient', () => {
test('Instantiates B2B client from ctx for handlers to use', async () => {
@ -497,7 +506,11 @@ describe('B2B', () => {
app.get('/', (ctx) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const client = B2B.getClient(ctx) as any
return ctx.json({ project_id: client.project_id, secret: client.secret })
return ctx.json({
project_id: client.project_id,
secret: client.secret,
custom_base_url: client.custom_base_url,
})
})
const response = await app.request(req)
@ -506,6 +519,7 @@ describe('B2B', () => {
expect(await response.json()).toEqual({
project_id: 'project-test-b2b-xxxxx',
secret: 'secret-key-test-b2b-xxxxx',
custom_base_url: 'https://login.example.com',
})
})
})

View File

@ -13,6 +13,8 @@ type StytchEnv = {
STYTCH_PROJECT_ID: string
/** The Stytch project secret */
STYTCH_PROJECT_SECRET: string
/** The Stytch Project domain */
STYTCH_DOMAIN?: string
}
type ConsumerTokenClaims = Awaited<ReturnType<Client['idp']['introspectTokenLocal']>>
@ -193,6 +195,7 @@ const getConsumerClient = (c: Context) => {
new Client({
project_id: stytchEnv.STYTCH_PROJECT_ID,
secret: stytchEnv.STYTCH_PROJECT_SECRET,
custom_base_url: stytchEnv.STYTCH_DOMAIN,
})
return consumerClients[stytchEnv.STYTCH_PROJECT_ID]
}
@ -214,6 +217,7 @@ const getB2BClient = (c: Context) => {
new B2BClient({
project_id: stytchEnv.STYTCH_PROJECT_ID,
secret: stytchEnv.STYTCH_PROJECT_SECRET,
custom_base_url: stytchEnv.STYTCH_DOMAIN,
})
return b2bClients[stytchEnv.STYTCH_PROJECT_ID]
}