File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1- import { NextResponse } from 'next/server'
1+ import { NextRequest , NextResponse } from 'next/server'
22import { cookies } from 'next/headers'
33import { createHash } from 'crypto'
44
@@ -31,12 +31,19 @@ function validateSession(sessionToken: string): boolean {
3131}
3232
3333// GET - Check auth status
34- export async function GET ( ) {
34+ export async function GET ( request : NextRequest ) {
3535 // If auth is disabled, always return authenticated
3636 if ( process . env . DISABLE_AUTH === 'true' ) {
3737 return NextResponse . json ( { authenticated : true } )
3838 }
3939
40+ // Check for token auth from headers (passed from URL params by client)
41+ const headerToken = request . headers . get ( 'X-Tinybird-Token' )
42+ const headerHost = request . headers . get ( 'X-Tinybird-Host' )
43+ if ( headerToken && headerHost ) {
44+ return NextResponse . json ( { authenticated : true } )
45+ }
46+
4047 const cookieStore = await cookies ( )
4148 const sessionCookie = cookieStore . get ( SESSION_COOKIE_NAME )
4249
Original file line number Diff line number Diff line change @@ -13,7 +13,23 @@ interface TinybirdRegionResponse {
1313 api_host : string
1414}
1515
16- // Cache for regions to avoid repeated API calls
16+ // Try to extract workspace name from JWT token payload
17+ function extractWorkspaceNameFromToken ( token : string ) : string | null {
18+ try {
19+ const payload = token . split ( '.' ) [ 1 ]
20+ if ( ! payload ) return null
21+ const base64 =
22+ payload . replace ( / - / g, '+' ) . replace ( / _ / g, '/' ) +
23+ '===' . slice ( ( payload . length + 3 ) % 4 )
24+ const json = Buffer . from ( base64 , 'base64' ) . toString ( )
25+ const data = JSON . parse ( json )
26+ // Skip 'frontend_jwt' as it's just a token label, not workspace name
27+ const name = data . workspace_name || ( data . name !== 'frontend_jwt' ? data . name : null )
28+ return name || null
29+ } catch {
30+ return null
31+ }
32+ }
1733
1834async function fetchTinybirdRegions ( ) : Promise < TinybirdRegionResponse [ ] > {
1935 try {
@@ -93,6 +109,11 @@ export async function GET(request: NextRequest) {
93109 workspaceName = tinybirdWorkspace ?. name || null
94110 }
95111
112+ // If still no workspace name and we have a token, try to decode it
113+ if ( ! workspaceName && headerToken ) {
114+ workspaceName = extractWorkspaceNameFromToken ( headerToken )
115+ }
116+
96117 const workspace =
97118 configured && host && regionInfo
98119 ? {
Original file line number Diff line number Diff line change @@ -29,7 +29,16 @@ export function getStoredCredentials(): StoredCredentials | null {
2929 }
3030}
3131
32- const fetcher = ( url : string ) => fetch ( url ) . then ( res => res . json ( ) )
32+ function createFetcher ( token : string | null , host : string | null ) {
33+ return ( url : string ) => {
34+ const headers : HeadersInit = { }
35+ if ( token && host ) {
36+ headers [ 'X-Tinybird-Token' ] = token
37+ headers [ 'X-Tinybird-Host' ] = host
38+ }
39+ return fetch ( url , { headers } ) . then ( res => res . json ( ) )
40+ }
41+ }
3342
3443export function useLogin ( ) {
3544 const searchParams = useSearchParams ( )
@@ -39,6 +48,9 @@ export function useLogin() {
3948 const host = searchParams ?. get ( 'host' )
4049 const hasTokenAuth = ! ! token && ! ! host
4150
51+ // Create fetcher with token/host to pass as headers
52+ const fetcher = createFetcher ( token , host )
53+
4254 // Check server session auth
4355 const { data, error, isLoading : isSessionLoading , mutate } = useSWR (
4456 '/api/auth' ,
Original file line number Diff line number Diff line change @@ -44,7 +44,7 @@ export function getServerClient() {
4444}
4545
4646export function createClientWithCredentials ( token : string , host : string ) {
47- return createAnalyticsClient ( { token, baseUrl : host } )
47+ return createAnalyticsClient ( { token, baseUrl : host , devMode : false } )
4848}
4949
5050export async function getWorkspace ( ) : Promise < TinybirdWorkspace | null > {
Original file line number Diff line number Diff line change @@ -24,6 +24,13 @@ export function middleware(request: NextRequest) {
2424 return NextResponse . next ( )
2525 }
2626
27+ // Check for token auth from headers (public mode)
28+ const headerToken = request . headers . get ( 'X-Tinybird-Token' )
29+ const headerHost = request . headers . get ( 'X-Tinybird-Host' )
30+ if ( headerToken && headerHost ) {
31+ return NextResponse . next ( )
32+ }
33+
2734 // Check for session cookie
2835 const sessionCookie = request . cookies . get ( SESSION_COOKIE_NAME )
2936
Original file line number Diff line number Diff line change @@ -109,19 +109,27 @@ const __configDir = dirname(fileURLToPath(import.meta.url));
109109interface CreateAnalyticsClientOptions {
110110 token ?: string ;
111111 baseUrl ?: string ;
112+ devMode ?: boolean | "branch" ;
112113}
113114
114115/**
115116 * Create a Tinybird client with custom configuration
116117 */
117118export function createAnalyticsClient ( options ?: CreateAnalyticsClientOptions ) {
118- return createTinybirdClient ( {
119+ const clientOptions : Parameters < typeof createTinybirdClient > [ 0 ] = {
119120 datasources,
120121 pipes,
121122 configDir : __configDir ,
122123 baseUrl : options ?. baseUrl ?? process . env . TINYBIRD_HOST ,
123124 token : options ?. token ?? process . env . TINYBIRD_TOKEN ,
124- } ) ;
125+ } ;
126+
127+ // Only set devMode if explicitly provided (otherwise use tinybird.json config)
128+ if ( options ?. devMode !== undefined ) {
129+ clientOptions . devMode = options . devMode ;
130+ }
131+
132+ return createTinybirdClient ( clientOptions ) ;
125133}
126134
127135/**
You can’t perform that action at this time.
0 commit comments