{"id":50558112,"url":"https://github.com/interline-io/tlv2-auth","last_synced_at":"2026-06-04T09:01:46.159Z","repository":{"id":349674115,"uuid":"1203343614","full_name":"interline-io/tlv2-auth","owner":"interline-io","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-20T10:22:03.000Z","size":212,"stargazers_count":0,"open_issues_count":7,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-20T14:42:39.607Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/interline-io.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-07T00:41:32.000Z","updated_at":"2026-04-20T23:16:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/interline-io/tlv2-auth","commit_stats":null,"previous_names":["interline-io/tlv2-auth"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/interline-io/tlv2-auth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interline-io%2Ftlv2-auth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interline-io%2Ftlv2-auth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interline-io%2Ftlv2-auth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interline-io%2Ftlv2-auth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/interline-io","download_url":"https://codeload.github.com/interline-io/tlv2-auth/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/interline-io%2Ftlv2-auth/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33897568,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-04T09:01:44.978Z","updated_at":"2026-06-04T09:01:46.154Z","avatar_url":"https://github.com/interline-io.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @interline-io/tlv2-auth\n\nNuxt 4 module providing authentication and API proxying for Transitland v2 applications. Replaces client-side Auth0 SPA token flow with server-side sessions via `@auth0/auth0-nuxt` using HTTP-only cookies.\n\n## Features\n\n- Server-side Auth0 sessions (always bundled; gracefully disabled at runtime when credentials are absent)\n- Multi-backend API proxy at `/proxy/{backendName}/...` with per-backend URL configuration\n- SSR auth header injection for `$fetch` and `globalThis.fetch`\n- Session enrichment with roles from a GraphQL `me` endpoint\n- Composables: `useUser()`, `useLogin()`, `useLogout()`, `useApiEndpoint()`\n\n## Install\n\n```bash\npnpm add @interline-io/tlv2-auth\n```\n\nPeer dependencies: `nuxt`, `vue`, `h3`\n\n## Usage\n\n```ts\n// nuxt.config.ts\nexport default defineNuxtConfig({\n  modules: ['@interline-io/tlv2-auth'],\n\n  runtimeConfig: {\n    // Server-side only (use NUXT_AUTH0_* / NUXT_TLV2_* env vars)\n    auth0: {\n      domain: '',\n      clientId: '',\n      clientSecret: '',\n      sessionSecret: '', // openssl rand -hex 32\n      appBaseUrl: '',\n      audience: '',\n    },\n    tlv2: {\n      graphqlApikey: '',\n      proxyBase: {\n        default: '',        // e.g. https://transit.land/api/v2\n      },\n    },\n    public: {\n      tlv2: {\n        loginGate: false,   // show login UI\n        requireLogin: false, // redirect unauthenticated users to login\n      },\n    },\n  },\n})\n```\n\nAuth0 is always installed at build time. The build-time presence of `NUXT_AUTH0_CLIENT_ID` determines the mode:\n\n- **No-auth** (Playwright, local dev, CI rigs): `NUXT_AUTH0_CLIENT_ID` unset → placeholders baked in, auth disabled at runtime, all users anonymous.\n- **Live auth**: `NUXT_AUTH0_CLIENT_ID` set → real `NUXT_AUTH0_*` values read from env at runtime.\n\nIf credentials are supplied **only at runtime**, `NUXT_AUTH0_CLIENT_ID` must still be set at build time (any non-empty value works). Otherwise, placeholders will be baked in and runtime env vars will be silently ignored.\n\n## Module options\n\nOptions can be passed via the module array syntax:\n\n```ts\nmodules: [['@interline-io/tlv2-auth', { autoAppBaseUrl: true }]]\n```\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `proxyEnabled` | `boolean` | `false` | Enable the API proxy |\n| `proxyBase` | `string \\| Record\u003cstring, string\u003e` | — | Backend URL(s) for the API proxy |\n| `requireLogin` | `boolean` | `false` | Redirect unauthenticated users to Auth0 login; also rejects unauthenticated proxy requests with 401 |\n| `loginGate` | `boolean` | `false` | Show login UI gate |\n| `authPrefix` | `string` | `'/auth'` | URL prefix for auth routes (login, logout, session) |\n| `proxyPrefix` | `string` | `'/proxy'` | URL prefix for the proxy route |\n| `autoAppBaseUrl` | `boolean` | `false` | Derive auth0 `appBaseUrl` from request `Host` header (see below) |\n\n### `autoAppBaseUrl`\n\nWhen enabled, the module derives `appBaseUrl` from the request's `Host` and `x-forwarded-proto` headers instead of using the static `NUXT_AUTH0_APP_BASE_URL` value. This is useful for branch/preview deploys where the URL isn't known at build time (e.g., Cloudflare Pages, Vercel preview deployments).\n\n**Caveat:** This trusts the `Host` and `x-forwarded-proto` headers. Only enable on platforms where these are set by a trusted edge proxy (Cloudflare, Vercel, Netlify, etc.). Do not enable when the application is directly exposed to the internet without a trusted reverse proxy.\n\n## Cloudflare Workers\n\nThe module includes a synchronous Nitro plugin that works around a race condition in `@auth0/auth0-nuxt`, where its async server plugin doesn't complete before the first request on Cloudflare Workers. This runs automatically when auth0 is enabled and no-ops on platforms where the async plugin completes normally (e.g., Node.js).\n\n## API proxy\n\nThe proxy at `/proxy/{backendName}/...` (configurable via `proxyPrefix`) forwards requests to the backend URL configured in `runtimeConfig.tlv2.proxyBase.{backendName}`.\n\n- Unauthenticated requests get the server's default API key injected\n- Authenticated requests additionally get the user's JWT\n- Callers may provide their own API key via `?apikey=` query param or `apikey` header, which takes precedence over the default\n- When `requireLogin` is `true`, unauthenticated proxy requests are rejected with 401\n\n**CSRF protection:** This module does not include CSRF protection. The proxy injects server-side credentials on behalf of the user, so consuming applications should configure their own CSRF protection (e.g. [`nuxt-csurf`](https://github.com/Morgbn/nuxt-csurf)) on proxy routes. This is especially important when `requireLogin` is `false`, as the proxy will forward requests with the server's API key for any caller. Note that `nuxt-csurf` only intercepts Nuxt's `$fetch` — if your app uses `globalThis.fetch` directly (e.g. Apollo), you will need a client plugin to inject the CSRF token on same-origin requests.\n\n## Composables\n\n- `useUser()` — returns current user state (`loggedIn`, `id`, `name`, `email`, `roles`, `hasRole()`)\n- `useLogin(targetUrl)` — redirects to Auth0 login, returns to `targetUrl` after\n- `useLogout()` — redirects to Auth0 logout\n- `useApiEndpoint(path, backendName)` — returns the correct endpoint URL (direct backend on server, proxy on client)\n\nComposables are auto-imported by Nuxt, but explicit imports are recommended for type safety:\n\n```ts\nimport { useUser, useApiEndpoint } from '@interline-io/tlv2-auth/composables'\nimport type { TlUser } from '@interline-io/tlv2-auth/composables'\n```\n\n## Development\n\n```bash\npnpm install          # Install (requires NODE_AUTH_TOKEN for GitHub Packages)\npnpm dev              # Start playground dev server (http://localhost:3000)\npnpm build            # Build the module\npnpm test             # Run unit tests\npnpm lint             # ESLint\n```\n\nCopy `playground/.env.example` to `playground/.env` and fill in your Auth0 and API credentials to test the full login flow.\n\n## Release workflow\n\nChangesets drives versioning and publishing:\n\n1. PRs include a `.changeset/*.md` file (created by `pnpm changeset`)\n2. On merge to `main`, the `@changesets/action` bot opens or updates a **\"Version Packages\"** PR that bumps versions and generates CHANGELOGs\n3. Merging the Version Packages PR triggers publish to GitHub Packages\n\nEvery push to `main` also publishes a SHA pre-release (`0.0.0-sha.\u003csha\u003e`) for internal testing.\n\n## Dependencies\n\n- `@auth0/auth0-nuxt` — server-side Auth0 sessions\n- `defu` — config merging\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finterline-io%2Ftlv2-auth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finterline-io%2Ftlv2-auth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finterline-io%2Ftlv2-auth/lists"}