{"_id":"@alexec0de/id-widget","name":"@alexec0de/id-widget","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@alexec0de/id-widget","version":"0.1.0","description":"«Войти через alexec0de ID» — умная кнопка входа (OAuth2/OIDC + PKCE). Vanilla, React и Vue.","type":"module","license":"MIT","author":{"name":"alexec0de"},"keywords":["oauth2","oidc","openid-connect","pkce","login-button","sso","authentication","react","vue","alexec0de-id"],"sideEffects":["**/auto.js","**/axid-widget.global.js"],"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","unpkg":"./dist/axid-widget.global.js","jsdelivr":"./dist/axid-widget.global.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js","require":"./dist/vue.cjs"},"./auto":"./dist/axid-widget.global.js","./package.json":"./package.json"},"repository":{"type":"git","url":"git+https://github.com/alexec0de/alexec0de-id.git","directory":"id-widget"},"homepage":"https://id.alexec0de.lol/docs","scripts":{"build":"tsup","dev":"tsup --watch","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"peerDependencies":{"react":">=17","react-dom":">=17","vue":">=3"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true},"vue":{"optional":true}},"devDependencies":{"@types/react":"^19.1.8","react":"^19.1.0","tsup":"^8.5.0","typescript":"^5.8.3","vue":"^3.5.18"},"engines":{"node":">=18"},"publishConfig":{"access":"public"},"_id":"@alexec0de/id-widget@0.1.0","bugs":{"url":"https://github.com/alexec0de/alexec0de-id/issues"},"_nodeVersion":"22.22.1","_npmVersion":"11.11.1","dist":{"integrity":"sha512-L7fKtMxiIpsoM/JQBvaoSj/o88xm4IWZ8vZ50nldCUnN5ToXPZsGJpUypi1TxNJi4rJTg2T4jLSP0x3yHODFJA==","shasum":"2b7c001cc5fad66f17acf543dde3cd4d46acde4b","tarball":"https://registry.npmjs.org/@alexec0de/id-widget/-/id-widget-0.1.0.tgz","fileCount":27,"unpackedSize":224296,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIEiFnD4HBcvfx7uMQnghUzcgalCI6lWMLi7WQvdaQvsTAiB6df5SgB9wSFlB14+3M6AO+6QDSILmsNacT05JH/CP+Q=="}]},"_npmUser":{"name":"alexec0de","email":"serostanaleksej50@gmail.com"},"directories":{},"maintainers":[{"name":"alexec0de","email":"serostanaleksej50@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/id-widget_0.1.0_1784232041787_0.5503836289863422"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-16T20:00:41.646Z","0.1.0":"2026-07-16T20:00:41.922Z","modified":"2026-07-16T20:00:42.097Z"},"maintainers":[{"name":"alexec0de","email":"serostanaleksej50@gmail.com"}],"description":"«Войти через alexec0de ID» — умная кнопка входа (OAuth2/OIDC + PKCE). Vanilla, React и Vue.","homepage":"https://id.alexec0de.lol/docs","keywords":["oauth2","oidc","openid-connect","pkce","login-button","sso","authentication","react","vue","alexec0de-id"],"repository":{"type":"git","url":"git+https://github.com/alexec0de/alexec0de-id.git","directory":"id-widget"},"author":{"name":"alexec0de"},"bugs":{"url":"https://github.com/alexec0de/alexec0de-id/issues"},"license":"MIT","readme":"# @alexec0de/id-widget\n\nУмная кнопка **«Войти через alexec0de ID»** — OAuth 2.0 / OpenID Connect с PKCE.\nОдин пакет, три способа подключения: **vanilla JS**, **React** и **Vue 3**, плюс\nготовый бандл для чистого HTML через `<script>`.\n\nЧто делает «умная» кнопка:\n\n1. При загрузке **тихо проверяет сессию** через скрытый iframe на домене провайдера.\n2. Показывает ник/аватар **только если пользователь уже давал доступ этому приложению**\n   (иначе это утечка приватности — сервер это гарантирует).\n3. Если доступ уже выдан — кнопка меняется на **«Продолжить как @nickname»**, и клик\n   уходит на авторизацию с `prompt=none` — мгновенный вход без экрана согласия.\n4. PKCE (S256) генерируется в браузере; `code_verifier` и `state` кладутся в\n   `sessionStorage` для обмена на токены на вашем бэкенде.\n\n## Установка\n\n```bash\nnpm i @alexec0de/id-widget\n```\n\nReact / Vue — это `peerDependencies` (опциональные): ставится то, что уже есть в проекте.\n\n> `baseUrl` по умолчанию — `https://id.alexec0de.lol` (канонический инстанс). Для него\n> параметр можно не указывать; для своего развёртывания задайте свой origin.\n\n---\n\n## React\n\n```tsx\nimport { AxidLoginButton } from \"@alexec0de/id-widget/react\";\n\nexport function LoginPage() {\n  return (\n    <AxidLoginButton\n      clientId=\"axid_ВАШ_CLIENT_ID\"\n      baseUrl=\"https://id.example.com\"\n      redirectUri=\"https://your.app/callback\"\n      scope=\"openid profile email\"\n      onStatus={(s) => console.log(\"session:\", s)}\n    />\n  );\n}\n```\n\nЧерез `ref` доступны `refresh()`, `getStatus()`, `login()`:\n\n```tsx\nconst ref = useRef<AxidLoginButtonHandle>(null);\n// ref.current?.login();\n```\n\n## Vue 3\n\n```vue\n<script setup lang=\"ts\">\nimport { AxidLoginButton } from \"@alexec0de/id-widget/vue\";\n</script>\n\n<template>\n  <AxidLoginButton\n    client-id=\"axid_ВАШ_CLIENT_ID\"\n    base-url=\"https://id.example.com\"\n    redirect-uri=\"https://your.app/callback\"\n    scope=\"openid profile email\"\n    @status=\"(s) => console.log('session:', s)\"\n  />\n</template>\n```\n\n## Чистый HTML (`<script>`, без сборки)\n\n```html\n<div id=\"alexec0de-id-button\"></div>\n<script\n  src=\"https://unpkg.com/@alexec0de/id-widget/dist/axid-widget.global.js\"\n  data-client-id=\"axid_ВАШ_CLIENT_ID\"\n  data-base-url=\"https://id.example.com\"\n  data-redirect-uri=\"https://your.app/callback\"\n  data-scope=\"openid profile email\"\n></script>\n```\n\nПолный API также доступен на `window.AxidWidget`.\n\n## Vanilla JS / TypeScript (программно)\n\n```ts\nimport { mount } from \"@alexec0de/id-widget\";\n\nconst widget = mount(\"#login\", {\n  clientId: \"axid_ВАШ_CLIENT_ID\",\n  baseUrl: \"https://id.example.com\",\n  redirectUri: \"https://your.app/callback\",\n  scope: \"openid profile email\",\n});\n// widget.refresh(); widget.getStatus(); widget.login(); widget.destroy();\n```\n\n---\n\n## Обработка callback\n\nНа странице `redirect_uri` прочитайте код и PKCE-verifier, проверив `state`:\n\n```ts\nimport { readCallback } from \"@alexec0de/id-widget\";\n\nconst result = readCallback();\nif (result.ok) {\n  // Отправьте на СВОЙ бэкенд для обмена на токены (client_secret не в браузере!)\n  await fetch(\"/api/oauth/exchange\", {\n    method: \"POST\",\n    headers: { \"Content-Type\": \"application/json\" },\n    body: JSON.stringify({ code: result.code, codeVerifier: result.codeVerifier }),\n  });\n} else {\n  console.error(\"OAuth error:\", result.error, result.errorDescription);\n}\n```\n\nВаш бэкенд делает `POST {baseUrl}/oauth/token` с `grant_type=authorization_code`,\n`code`, `redirect_uri`, `code_verifier` и Basic-авторизацией `client_id:client_secret`.\n\n## Опции (`AxidConfig`)\n\n| Поле | Тип | По умолчанию | Описание |\n|---|---|---|---|\n| `clientId` | `string` | — (обязательно) | client_id из дашборда |\n| `baseUrl` | `string` | канонический инстанс | Origin провайдера alexec0de ID |\n| `redirectUri` | `string` | — | Куда вернётся `code` (обязательно, если нет `authorizeUrl`) |\n| `scope` | `string` | `\"openid profile\"` | Запрашиваемые scope через пробел |\n| `theme` | `\"dark\" \\| \"light\"` | `\"dark\"` | Тема кнопки |\n| `variant` | `\"button\" \\| \"icon\"` | `\"button\"` | Кнопка с текстом или только иконка |\n| `text` | `string` | «Войти через alexec0de ID» | Подпись в дефолтном состоянии |\n| `authorizeUrl` | `string` | — | Свой серверный старт флоу (PKCE на бэкенде); тогда `redirectUri`/sessionStorage не нужны |\n| `onStatus` | `(s) => void` | — | Колбэк при получении статуса сессии |\n| `onBeforeRedirect` | `(url) => void` | — | Колбэк перед переходом на провайдера |\n\nHTML-атрибуты соответствуют опциям в kebab-case: `data-client-id`, `data-base-url`,\n`data-redirect-uri`, `data-scope`, `data-theme`, `data-variant`, `data-text`,\n`data-authorize-url`, `data-target`.\n\n## Требования\n\n- Браузер с Web Crypto (`crypto.subtle`) — то есть **HTTPS или `localhost`**.\n- На стороне провайдера у приложения должен быть зарегистрирован точный `redirect_uri`\n  (сравнение побайтовое), а его origin — среди разрешённых для виджета.\n\n## Сборки в пакете\n\n| Экспорт | Формат | Назначение |\n|---|---|---|\n| `@alexec0de/id-widget` | ESM + CJS + d.ts | vanilla-ядро |\n| `@alexec0de/id-widget/react` | ESM + CJS + d.ts | React-компонент |\n| `@alexec0de/id-widget/vue` | ESM + CJS + d.ts | Vue 3-компонент |\n| `dist/axid-widget.global.js` | IIFE (`window.AxidWidget`) | `<script>` / CDN |\n\n## Лицензия\n\nMIT\n","readmeFilename":"README.md","_rev":"1-70037c7be9e9fa17bef5ad29078c58b6"}