Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 469
feat(express,fastify,tanstack-react-start,react-router): Support machine auth tokens in getAuth()#6067
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
Uh oh!
There was an error while loading. Please reload this page.
feat(express,fastify,tanstack-react-start,react-router): Support machine auth tokens in getAuth()#6067
Changes from all commits
22a895d2c85eb82c2d3db662f1b2a560b3432e75a0509ed8109d430483fbbc96e7a5b2a138472d91ad25a925e4d4b3ee91c220a632a4648e88db02dd4dd19de5976564c9d741File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| '@clerk/backend': patch | ||
| '@clerk/nextjs': patch | ||
| --- | ||
| Re-organize internal types for the recently added "machine authentication" feature. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| --- | ||
| '@clerk/tanstack-react-start': minor | ||
| --- | ||
| Introduces machine authentication, supporting four token types: `api_key`, `oauth_token`, `machine_token`, and `session_token`. For backwards compatibility, `session_token` remains the default when no token type is specified. This enables machine-to-machine authentication and use cases such as API keys and OAuth integrations. Existing applications continue to work without modification. | ||
| You can specify which token types are allowed by using the `acceptsToken` option in the `getAuth()` function. This option can be set to a specific type, an array of types, or `'any'` to accept all supported tokens. | ||
| Example usage: | ||
| ```ts | ||
| import { createServerFn } from '@tanstack/react-start' | ||
| import { getAuth } from '@clerk/tanstack-react-start/server' | ||
| import { getWebRequest } from '@tanstack/react-start/server' | ||
| const authStateFn = createServerFn({ method: 'GET' }).handler(async () => { | ||
| const request = getWebRequest() | ||
| const auth = await getAuth(request, { acceptsToken: 'any' }) | ||
| if (authObject.tokenType === 'session_token') { | ||
| console.log('this is session token from a user') | ||
| } else { | ||
| console.log('this is some other type of machine token') | ||
| console.log('more specifically, a ' + authObject.tokenType) | ||
| } | ||
| return {} | ||
| }) | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| --- | ||
| '@clerk/express': minor | ||
| --- | ||
| Introduces machine authentication, supporting four token types: `api_key`, `oauth_token`, `machine_token`, and `session_token`. For backwards compatibility, `session_token` remains the default when no token type is specified. This enables machine-to-machine authentication and use cases such as API keys and OAuth integrations. Existing applications continue to work without modification. | ||
| You can specify which token types are allowed by using the `acceptsToken` option in the `getAuth()` function. This option can be set to a specific type, an array of types, or `'any'` to accept all supported tokens. | ||
| Example usage: | ||
| ```ts | ||
| import express from 'express'; | ||
| import { getAuth } from '@clerk/express'; | ||
| const app = express(); | ||
| app.get('/path', (req, res) => { | ||
| const authObject = getAuth(req, { acceptsToken: 'any' }); | ||
| if (authObject.tokenType === 'session_token') { | ||
| console.log('this is session token from a user') | ||
| } else { | ||
| console.log('this is some other type of machine token') | ||
| console.log('more specifically, a ' + authObject.tokenType) | ||
| } | ||
| }); | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| --- | ||
| '@clerk/react-router': minor | ||
| --- | ||
| Introduces machine authentication, supporting four token types: `api_key`, `oauth_token`, `machine_token`, and `session_token`. For backwards compatibility, `session_token` remains the default when no token type is specified. This enables machine-to-machine authentication and use cases such as API keys and OAuth integrations. Existing applications continue to work without modification. | ||
| You can specify which token types are allowed by using the `acceptsToken` option in the `getAuth()` function. This option can be set to a specific type, an array of types, or `'any'` to accept all supported tokens. | ||
| Example usage: | ||
| ```ts | ||
| import { getAuth } from '@clerk/react-router/ssr.server' | ||
| import type { Route } from './+types/profile' | ||
| export async function loader(args: Route.LoaderArgs) { | ||
| const authObject = await getAuth(args, { acceptsToken: 'any' }) | ||
| if (authObject.tokenType === 'session_token') { | ||
| console.log('this is session token from a user') | ||
| } else { | ||
| console.log('this is some other type of machine token') | ||
| console.log('more specifically, a ' + authObject.tokenType) | ||
| } | ||
| return {} | ||
| } | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| --- | ||
| '@clerk/fastify': minor | ||
| --- | ||
| Introduces machine authentication, supporting four token types: `api_key`, `oauth_token`, `machine_token`, and `session_token`. For backwards compatibility, `session_token` remains the default when no token type is specified. This enables machine-to-machine authentication and use cases such as API keys and OAuth integrations. Existing applications continue to work without modification. | ||
| You can specify which token types are allowed by using the `acceptsToken` option in the `getAuth()` function. This option can be set to a specific type, an array of types, or `'any'` to accept all supported tokens. | ||
| Example usage: | ||
| ```ts | ||
| import Fastify from 'fastify' | ||
| import { getAuth } from '@clerk/fastify' | ||
| const fastify = Fastify() | ||
| fastify.get('/path', (request, reply) => { | ||
| const authObject = getAuth(req, { acceptsToken: 'any' }); | ||
| if (authObject.tokenType === 'session_token') { | ||
| console.log('this is session token from a user') | ||
| } else { | ||
| console.log('this is some other type of machine token') | ||
| console.log('more specifically, a ' + authObject.tokenType) | ||
| } | ||
| }); | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2,16 +2,46 @@ import { getAuth } from '../getAuth'; | ||
| import { mockRequest, mockRequestWithAuth } from './helpers'; | ||
| describe('getAuth', () => { | ||
| it('throws error if clerkMiddleware is not executed before getAuth', async () => { | ||
| it('throws error if clerkMiddleware is not executed before getAuth', () => { | ||
| expect(() => getAuth(mockRequest())).toThrow(/The "clerkMiddleware" should be registered before using "getAuth"/); | ||
| }); | ||
| it('returns auth from request for signed-out request', async () => { | ||
| expect(getAuth(mockRequestWithAuth())).toHaveProperty('userId', null); | ||
| it('returns auth from request for signed-out request', () => { | ||
| const req = mockRequestWithAuth({ userId: null, tokenType: 'session_token' }); | ||
| const auth = getAuth(req); | ||
| expect(auth.userId).toBeNull(); | ||
| expect(auth.tokenType).toBe('session_token'); | ||
| }); | ||
| it('returns auth from request', async () => { | ||
| const req = mockRequestWithAuth({ userId: 'user_12345' }); | ||
| expect(getAuth(req)).toHaveProperty('userId', 'user_12345'); | ||
| it('returns auth from request', () => { | ||
| const req = mockRequestWithAuth({ userId: 'user_12345', tokenType: 'session_token' }); | ||
| const auth = getAuth(req); | ||
| expect(auth.userId).toBe('user_12345'); | ||
| expect(auth.tokenType).toBe('session_token'); | ||
| }); | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we wanna add a test case that asserts that the default MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the actual However, the Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, sorry, I misread lol. The changeset is saying what you're saying. So never mind :) | ||
| it('returns the actual auth object when its tokenType matches acceptsToken', () => { | ||
| const req = mockRequestWithAuth({ tokenType: 'api_key', id: 'ak_1234', subject: 'api_key_1234' }); | ||
| const result = getAuth(req, { acceptsToken: 'api_key' }); | ||
| expect(result.tokenType).toBe('api_key'); | ||
| expect(result.id).toBe('ak_1234'); | ||
| expect(result.subject).toBe('api_key_1234'); | ||
| }); | ||
| it('returns the actual auth object if its tokenType is included in the acceptsToken array', () => { | ||
| const req = mockRequestWithAuth({ tokenType: 'machine_token', id: 'mt_1234' }); | ||
| const result = getAuth(req, { acceptsToken: ['machine_token', 'api_key'] }); | ||
| expect(result.tokenType).toBe('machine_token'); | ||
| expect(result.id).toBe('mt_1234'); | ||
| expect(result.subject).toBeUndefined(); | ||
| }); | ||
| it('returns an unauthenticated auth object when the tokenType does not match acceptsToken', () => { | ||
| const req = mockRequestWithAuth({ tokenType: 'session_token', userId: 'user_12345' }); | ||
| const result = getAuth(req, { acceptsToken: 'api_key' }); | ||
| expect(result.tokenType).toBe('session_token'); // reflects the actual token found | ||
| // Properties specific to authenticated objects should be null or undefined | ||
| // @ts-expect-error - userId is not a property of the unauthenticated object | ||
| expect(result.userId).toBeNull(); | ||
| }); | ||
| }); | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.