{"id":27442914,"url":"https://github.com/sansjack/svoauth","last_synced_at":"2026-04-28T18:31:06.244Z","repository":{"id":287760443,"uuid":"962245408","full_name":"sansjack/svoauth","owner":"sansjack","description":"lightweight config-driven svelte OAuth wrapper","archived":false,"fork":false,"pushed_at":"2025-05-15T14:24:52.000Z","size":32,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-24T19:29:49.908Z","etag":null,"topics":["oauth2","oauth2-server","svelte","svelte5","sveltekit"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sansjack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2025-04-07T21:43:26.000Z","updated_at":"2025-06-11T07:35:05.000Z","dependencies_parsed_at":"2025-04-15T01:17:23.708Z","dependency_job_id":"bf95c17b-9dda-4e2e-85d7-cda7bf3275ad","html_url":"https://github.com/sansjack/svoauth","commit_stats":null,"previous_names":["sansjack/svauth"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/sansjack/svoauth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sansjack%2Fsvoauth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sansjack%2Fsvoauth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sansjack%2Fsvoauth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sansjack%2Fsvoauth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sansjack","download_url":"https://codeload.github.com/sansjack/svoauth/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sansjack%2Fsvoauth/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32394189,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T14:34:11.604Z","status":"ssl_error","status_checked_at":"2026-04-28T14:32:37.009Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["oauth2","oauth2-server","svelte","svelte5","sveltekit"],"created_at":"2025-04-15T01:17:20.521Z","updated_at":"2026-04-28T18:31:06.238Z","avatar_url":"https://github.com/sansjack.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## 🔐 svoauth — Lightweight Config-Driven OAuth for SvelteKit\n\n`svoauth` is a minimal and flexible OAuth 2.0 wrapper designed for SvelteKit projects. It uses a config-driven approach so you can easily plug in providers like GitHub, Google, and more.\n\n---\n\n\n\n### 📦 Features\n\n- ⚙️ Config-driven approach\n- ⚡️ Minimal SvelteKit integration\n- 🏋️‍♀️ Lightweight and \u003c 20kb\n- 🔄 Supports token exchange, refresh, and revoke\n- 💻 Server side rendering only (no client-side code)\n- 🔐 PKCE support (e.g., for Google)\n- 🌐 Easily configurable for multiple providers\n\n### ❓ Why Did I Make This?\nI was working on a SaaS project of mine that needs a lot of integrations with different providers. I wanted to try abstract as much as possible out of my codebase for dealing with the OAuth side of things as i will be adding A LOT of different integrations in the future.\n\nThis was really made for my own use but I decided to make a public package so that others can use it as well. The main use of this is so I can get the users access tokens and refresh tokens so i can use them on their behalf to fetch data. \n\n\u003e [!WARNING]  \n\u003e This package is not meant for the use of authentication but rather for the use of authorization and retrieving access tokens. This should also ONLY be used on the server-side.\n\n## 🗺️ Roadmap / TODO\n\nMy Plans for `svoauth`:\n\n- [ ] Improve error handling and response structure\n- [ ] Expand config options (custom headers, custom callbacks)\n- [ ] Add some tests\n- [ ] Create a proper documentation site with more in-depth examples and explanations\n\nHave ideas? Feel free to open an issue or PR!\n\n### ⚙️ Configuration\n\nDefine your OAuth clients in a central `oauth.ts` config file:\n\n```ts\n// src/lib/server/oauth.ts\nimport { env } from '$env/dynamic/private';\nimport { OAuthHandler, type OAuthConfigs } from 'svoauth';\n\nconst clients: OAuthConfigs = {\n    github: {\n        clientId: env.GITHUB_CLIENT_ID,\n        clientSecret: env.GITHUB_CLIENT_SECRET,\n        authorizeUrl: 'https://github.com/login/oauth/authorize',\n        tokenUrl: 'https://github.com/login/oauth/access_token',\n        redirectUri: 'http://localhost:5173/integration/callback/github',\n        scopes: {\n            values: ['read:user', 'read:org', 'repo:status', 'read:project']\n        }\n    },\n    google: {\n        clientId: env.GOOGLE_CLIENT_ID,\n        clientSecret: env.GOOGLE_CLIENT_SECRET,\n        pkce: true,\n        authorizeUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n        tokenUrl: 'https://oauth2.googleapis.com/token',\n        refreshTokenUrl: 'https://oauth2.googleapis.com/token',\n        revokeTokenUrl: 'https://oauth2.googleapis.com/revoke',\n        redirectUri: 'http://localhost:5173/integration/callback/google',\n        params: [{ access_type: 'offline' }],\n        scopes: {\n            values: ['email', 'profile', 'https://www.googleapis.com/auth/calendar.readonly']\n        }\n    }\n};\n\nexport const svoAuth = new OAuthHandler(clients);\n```\n\n---\n\n### 🔗 Link Route\n\nCreate a route that redirects users to the provider's authorization page.\n\n```ts\n// src/routes/link/[client]/+server.ts\nimport { svoAuth } from '$lib/server/oauth';\nimport { redirect } from '@sveltejs/kit';\n\nexport const GET = async (event) =\u003e {\n    const clientName = event.params.client;\n    const authUrl = svoAuth.get(clientName).generateAuthorizeUrl(event);\n    throw redirect(303, authUrl);\n};\n```\n---\n\n### 🎯 Callback Route\n\nCreate a callback route to handle the OAuth response and exchange the code for a token.\n\n```ts\n// src/routes/callback/[client]/+server.ts\nimport { json } from '@sveltejs/kit';\nimport { svoAuth } from '$lib/server/oauth';\n\nexport const GET = async (event) =\u003e {\n    const clientName = event.params.client;\n    const tokens = await svoAuth.get(clientName).exchangeCodeForToken(event);\n\n    const accessToken = tokens.accessToken();\n    return json({ token: accessToken });\n};\n```\n\n---\n\n### ♻️ Refresh Token\n\nCreate a route to refresh the access token using a refresh token.\n\n```ts\n// src/routes/refresh/[client]/+server.ts\nimport { svoAuth } from '$lib/server/oauth';\nimport { json, error } from '@sveltejs/kit';\n\ntype RefreshReqest = {\n    token: string;\n};\n\nexport const POST = async (event) =\u003e {\n    const { params, request } = event;\n    const clientName = params.client;\n\n    const result = (await request.json()) as RefreshReqest;\n    const { token } = result;\n\n    if (!token) {\n        throw error(422);\n    }\n\n    const newTokens = await svoAuth.get(clientName).refreshToken(token);\n    const access_token = newTokens.accessToken();\n\n    return json({ message: access_token });\n};\n```\n\n---\n\n### 🚫 Revoke Token\n\nCreate a route to revoke a refresh token.\n\n```ts\n// src/routes/revoke/[client]/+server.ts\nimport { svoAuth } from '$lib/server/oauth';\nimport { json, error } from '@sveltejs/kit';\n\ntype RevokeRequest = {\n    refresh_token: string;\n};\n\nexport const POST = async (event) =\u003e {\n    const { params, request } = event;\n    const clientName = params.client;\n\n    const result = (await request.json()) as RevokeRequest;\n    const { refresh_token } = result;\n\n    if (!refresh_token) {\n        throw error(422);\n    }\n\n    await svoAuth.get(clientName).revokeToken(refresh_token);\n\n    return json({ message: `${clientName} token has been revoked` });\n};\n```\n\n---\n\n### ✅ Example Flow\n\n1. Navigate to `/link/github`\n2. You get redirected to GitHub to authorize\n3. After auth, GitHub redirects to `/callback/github`\n4. The access token is extracted and returned as JSON\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsansjack%2Fsvoauth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsansjack%2Fsvoauth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsansjack%2Fsvoauth/lists"}