@authyon/auth 0.1.5 → 0.2.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +158 -158
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,158 +1,158 @@
1
- # @authyon/auth
2
-
3
- SDK JS/TS para o [Authyon](https://authyon.com) — autenticação, sessões, multi-tenant e 2FA, com armazenamento e refresh de tokens transparentes.
4
-
5
- Cobre todos os endpoints públicos documentados em [authyon.com/docs](https://authyon.com/docs), usando a **publishable key** (`pk_...`) — segura para expor no navegador.
6
-
7
- Para gestão de organização/membros (secret key) e verificação de token no backend, veja [`@authyon/server`](../server).
8
-
9
- ## Instalação
10
-
11
- ```bash
12
- npm install @authyon/auth
13
- ```
14
-
15
- ## Uso rápido
16
-
17
- ```ts
18
- import { createClient } from "@authyon/auth";
19
-
20
- const authyon = createClient({ envKey: "pk_live_..." });
21
-
22
- // Login (com suporte a 2FA)
23
- const result = await authyon.login({
24
- email: "alice@acme.com",
25
- password: "...",
26
- organizationSlug: "acme", // opcional
27
- });
28
-
29
- if (result.twoFactorRequired) {
30
- const code = prompt(`Código 2FA (${result.methods.join(", ")})`);
31
- await authyon.verifyTwoFactor({
32
- challengeToken: result.challengeToken,
33
- method: "authenticator",
34
- code: code!,
35
- });
36
- }
37
-
38
- // Usuário atual — o access token é renovado automaticamente quando necessário
39
- const user = await authyon.user.me();
40
- ```
41
-
42
- ## Sessão e tokens
43
-
44
- - Tokens persistem em `localStorage` por padrão (`memoryStorage()` ou um `TokenStorage` próprio via opção `storage`).
45
- - `getAccessToken()` renova o token automaticamente antes de expirar (refresh token é single-use e rotacionado, com single-flight para evitar corridas).
46
- - Chamadas autenticadas que retornam 401 fazem um refresh e uma retentativa automática.
47
-
48
- ```ts
49
- const token = await authyon.getAccessToken(); // sempre válido, ou null se deslogado
50
-
51
- const unsubscribe = authyon.onAuthStateChange((event) => {
52
- // "signed_in" | "refreshed" | "signed_out"
53
- console.log(event.type);
54
- });
55
- ```
56
-
57
- ## API
58
-
59
- Métodos de sessão/auth ficam soltos no client; os que giram em torno de um recurso específico ficam agrupados em namespaces (`user`, `organization`, `twoFactor`, `webauthn`, `sso`).
60
-
61
- | Método | Endpoint |
62
- | ------------------------------------------------------------------------ | ----------------------- |
63
- | `register({ email, username, password })` | `POST /auth/register` |
64
- | `login({ email \| username, password, organizationSlug? })` | `POST /auth/login` |
65
- | `verifyTwoFactor({ challengeToken, method, code?, webAuthnAssertion? })` | `POST /auth/2fa/verify` |
66
- | `refresh()` | `POST /auth/refresh` |
67
- | `logout({ everywhere? })` | `POST /auth/logout` |
68
- | `introspect(token?)` | `POST /auth/introspect` |
69
- | `validate(token?)` | `POST /auth/validate` |
70
-
71
- ### `authyon.user`
72
-
73
- | Método | Endpoint |
74
- | ----------------------------------------------- | ----------------------------------- |
75
- | `user.me()` | `GET /auth/me` |
76
- | `user.sessions()` | `GET /auth/sessions` |
77
- | `user.revokeSession(sessionId)` | `DELETE /auth/sessions/{id}` |
78
- | `user.activities(params?)` | `GET /auth/me/activities` |
79
- | `user.requestPasswordReset(email)` | `POST /auth/password-reset/request` |
80
- | `user.confirmPasswordReset(token, newPassword)` | `POST /auth/password-reset/confirm` |
81
-
82
- ### `authyon.organization`
83
-
84
- | Método | Endpoint |
85
- | ----------------------------------------------------- | ---------------------------------------------- |
86
- | `organization.list()` | `GET /auth/tenants` |
87
- | `organization.create(params?)` | `POST /auth/tenants` |
88
- | `organization.get(organizationId)` | `GET /auth/tenants/{id}` |
89
- | `organization.rename(organizationId, name)` | `PATCH /auth/tenants/{id}` |
90
- | `organization.switch(slug)` | `POST /auth/switch-tenant` |
91
- | `organization.current()` | — (lê `activeOrganization` da sessão em cache) |
92
- | `organization.members.list(organizationId, params?)` | `GET /auth/tenants/{id}/members` |
93
- | `organization.members.invite(organizationId, params)` | `POST /auth/tenants/{id}/members` |
94
- | `organization.members.remove(organizationId, userId)` | `DELETE /auth/tenants/{id}/members/{userId}` |
95
- | `organization.roles.list(organizationId)` | `GET /auth/tenants/{id}/roles` |
96
-
97
- ### `authyon.twoFactor`
98
-
99
- | Método | Endpoint |
100
- | ---------------------------------------------------- | -------------------------------------------- |
101
- | `twoFactor.status()` | `GET /auth/2fa/status` |
102
- | `twoFactor.resendEmail(challengeToken)` | `POST /auth/2fa/resend-email` |
103
- | `twoFactor.setupAuthenticator()` | `POST /auth/2fa/authenticator/setup` |
104
- | `twoFactor.confirmAuthenticator(code)` | `POST /auth/2fa/authenticator/confirm` |
105
- | `twoFactor.enableEmail(code?)` | `POST /auth/2fa/email/enable` |
106
- | `twoFactor.disable(method, currentPassword)` | `POST /auth/2fa/disable` |
107
- | `twoFactor.regenerateRecoveryCodes(currentPassword)` | `POST /auth/2fa/recovery-codes/regenerate` |
108
- | `twoFactor.webauthn.registerStart()` | `POST /auth/2fa/webauthn/register/start` |
109
- | `twoFactor.webauthn.registerFinish(...)` | `POST /auth/2fa/webauthn/register/finish` |
110
- | `twoFactor.webauthn.credentials()` | `GET /auth/2fa/webauthn/credentials` |
111
- | `twoFactor.webauthn.renameCredential(id, nickname)` | `PATCH /auth/2fa/webauthn/credentials/{id}` |
112
- | `twoFactor.webauthn.removeCredential(id, pwd)` | `DELETE /auth/2fa/webauthn/credentials/{id}` |
113
- | `twoFactor.webauthn.assertionStart(challengeToken)` | `POST /auth/2fa/webauthn/assertion/start` |
114
-
115
- ### `authyon.webauthn` (login sem senha)
116
-
117
- | Método | Endpoint |
118
- | --------------------------------- | ---------------------------------- |
119
- | `webauthn.loginStart(email?)` | `POST /auth/webauthn/login/start` |
120
- | `webauthn.loginFinish(assertion)` | `POST /auth/webauthn/login/finish` |
121
-
122
- ### `authyon.sso` (login social)
123
-
124
- | Método | Endpoint |
125
- | -------------------------------- | ------------------------------------------------------------------------------------- |
126
- | `sso.providers()` | `GET /auth/sso/providers` |
127
- | `sso.startUrl(provider, params)` | monta a URL de `GET /auth/sso/{provider}/start` (não faz a chamada — navegue até ela) |
128
- | `sso.exchange(code)` | `POST /auth/sso/exchange` |
129
-
130
- ## Invalidação de token
131
-
132
- - **Sessão atual**: `logout()` revoga o refresh token atual; `logout({ everywhere: true })` revoga todos os refresh tokens do usuário.
133
- - **Uma sessão específica**: `user.revokeSession(sessionId)`, usando o `id` retornado por `user.sessions()` — derruba um dispositivo sem afetar a sessão atual.
134
- - **Access token**: por ser um JWT stateless, o access token continua "válido" até expirar (`expiresIn`, tipicamente 30 min) mesmo após revogar o refresh token. Para checar revogação em tempo real no seu backend, use `validate()` (cross-checa o estado no banco) em vez de `introspect()`.
135
-
136
- ## Erros
137
-
138
- Toda resposta não-2xx vira um `AuthyonError` (problem+json). Compare pelo `code` legível por máquina, nunca pelo `title`:
139
-
140
- ```ts
141
- import { AuthyonError, ErrorCodes } from "@authyon/auth";
142
-
143
- try {
144
- await authyon.register({ email, password });
145
- } catch (err) {
146
- if (err instanceof AuthyonError && err.is(ErrorCodes.EmailTaken)) {
147
- // e-mail já cadastrado
148
- }
149
- }
150
- ```
151
-
152
- ## Build
153
-
154
- ```bash
155
- npm install
156
- npm run build # dist/ (ESM + CJS + .d.ts via tsup)
157
- npm run typecheck
158
- ```
1
+ # @authyon/auth
2
+
3
+ SDK JS/TS para o [Authyon](https://authyon.com) — autenticação, sessões, multi-tenant e 2FA, com armazenamento e refresh de tokens transparentes.
4
+
5
+ Cobre todos os endpoints públicos documentados em [authyon.com/docs](https://authyon.com/docs), usando a **publishable key** (`pk_...`) — segura para expor no navegador.
6
+
7
+ Para gestão de organização/membros (secret key) e verificação de token no backend, veja [`@authyon/server`](../server).
8
+
9
+ ## Instalação
10
+
11
+ ```bash
12
+ npm install @authyon/auth
13
+ ```
14
+
15
+ ## Uso rápido
16
+
17
+ ```ts
18
+ import { createClient } from "@authyon/auth";
19
+
20
+ const authyon = createClient({ envKey: "pk_live_..." });
21
+
22
+ // Login (com suporte a 2FA)
23
+ const result = await authyon.login({
24
+ email: "alice@acme.com",
25
+ password: "...",
26
+ organizationSlug: "acme", // opcional
27
+ });
28
+
29
+ if (result.twoFactorRequired) {
30
+ const code = prompt(`Código 2FA (${result.methods.join(", ")})`);
31
+ await authyon.verifyTwoFactor({
32
+ challengeToken: result.challengeToken,
33
+ method: "authenticator",
34
+ code: code!,
35
+ });
36
+ }
37
+
38
+ // Usuário atual — o access token é renovado automaticamente quando necessário
39
+ const user = await authyon.user.me();
40
+ ```
41
+
42
+ ## Sessão e tokens
43
+
44
+ - Tokens persistem em `localStorage` por padrão (`memoryStorage()` ou um `TokenStorage` próprio via opção `storage`).
45
+ - `getAccessToken()` renova o token automaticamente antes de expirar (refresh token é single-use e rotacionado, com single-flight para evitar corridas).
46
+ - Chamadas autenticadas que retornam 401 fazem um refresh e uma retentativa automática.
47
+
48
+ ```ts
49
+ const token = await authyon.getAccessToken(); // sempre válido, ou null se deslogado
50
+
51
+ const unsubscribe = authyon.onAuthStateChange((event) => {
52
+ // "signed_in" | "refreshed" | "signed_out"
53
+ console.log(event.type);
54
+ });
55
+ ```
56
+
57
+ ## API
58
+
59
+ Métodos de sessão/auth ficam soltos no client; os que giram em torno de um recurso específico ficam agrupados em namespaces (`user`, `organization`, `twoFactor`, `webauthn`, `sso`).
60
+
61
+ | Método | Endpoint |
62
+ | ------------------------------------------------------------------------ | ----------------------- |
63
+ | `register({ email, username, password })` | `POST /auth/register` |
64
+ | `login({ email \| username, password, organizationSlug? })` | `POST /auth/login` |
65
+ | `verifyTwoFactor({ challengeToken, method, code?, webAuthnAssertion? })` | `POST /auth/2fa/verify` |
66
+ | `refresh()` | `POST /auth/refresh` |
67
+ | `logout({ everywhere? })` | `POST /auth/logout` |
68
+ | `introspect(token?)` | `POST /auth/introspect` |
69
+ | `validate(token?)` | `POST /auth/validate` |
70
+
71
+ ### `authyon.user`
72
+
73
+ | Método | Endpoint |
74
+ | ----------------------------------------------- | ----------------------------------- |
75
+ | `user.me()` | `GET /auth/me` |
76
+ | `user.sessions()` | `GET /auth/sessions` |
77
+ | `user.revokeSession(sessionId)` | `DELETE /auth/sessions/{id}` |
78
+ | `user.activities(params?)` | `GET /auth/me/activities` |
79
+ | `user.requestPasswordReset(email)` | `POST /auth/password-reset/request` |
80
+ | `user.confirmPasswordReset(token, newPassword)` | `POST /auth/password-reset/confirm` |
81
+
82
+ ### `authyon.organization`
83
+
84
+ | Método | Endpoint |
85
+ | ----------------------------------------------------- | ---------------------------------------------- |
86
+ | `organization.list()` | `GET /auth/tenants` |
87
+ | `organization.create(params?)` | `POST /auth/tenants` |
88
+ | `organization.get(organizationId)` | `GET /auth/tenants/{id}` |
89
+ | `organization.rename(organizationId, name)` | `PATCH /auth/tenants/{id}` |
90
+ | `organization.switch(slug)` | `POST /auth/switch-tenant` |
91
+ | `organization.current()` | — (lê `activeOrganization` da sessão em cache) |
92
+ | `organization.members.list(organizationId, params?)` | `GET /auth/tenants/{id}/members` |
93
+ | `organization.members.invite(organizationId, params)` | `POST /auth/tenants/{id}/members` |
94
+ | `organization.members.remove(organizationId, userId)` | `DELETE /auth/tenants/{id}/members/{userId}` |
95
+ | `organization.roles.list(organizationId)` | `GET /auth/tenants/{id}/roles` |
96
+
97
+ ### `authyon.twoFactor`
98
+
99
+ | Método | Endpoint |
100
+ | ---------------------------------------------------- | -------------------------------------------- |
101
+ | `twoFactor.status()` | `GET /auth/2fa/status` |
102
+ | `twoFactor.resendEmail(challengeToken)` | `POST /auth/2fa/resend-email` |
103
+ | `twoFactor.setupAuthenticator()` | `POST /auth/2fa/authenticator/setup` |
104
+ | `twoFactor.confirmAuthenticator(code)` | `POST /auth/2fa/authenticator/confirm` |
105
+ | `twoFactor.enableEmail(code?)` | `POST /auth/2fa/email/enable` |
106
+ | `twoFactor.disable(method, currentPassword)` | `POST /auth/2fa/disable` |
107
+ | `twoFactor.regenerateRecoveryCodes(currentPassword)` | `POST /auth/2fa/recovery-codes/regenerate` |
108
+ | `twoFactor.webauthn.registerStart()` | `POST /auth/2fa/webauthn/register/start` |
109
+ | `twoFactor.webauthn.registerFinish(...)` | `POST /auth/2fa/webauthn/register/finish` |
110
+ | `twoFactor.webauthn.credentials()` | `GET /auth/2fa/webauthn/credentials` |
111
+ | `twoFactor.webauthn.renameCredential(id, nickname)` | `PATCH /auth/2fa/webauthn/credentials/{id}` |
112
+ | `twoFactor.webauthn.removeCredential(id, pwd)` | `DELETE /auth/2fa/webauthn/credentials/{id}` |
113
+ | `twoFactor.webauthn.assertionStart(challengeToken)` | `POST /auth/2fa/webauthn/assertion/start` |
114
+
115
+ ### `authyon.webauthn` (login sem senha)
116
+
117
+ | Método | Endpoint |
118
+ | --------------------------------- | ---------------------------------- |
119
+ | `webauthn.loginStart(email?)` | `POST /auth/webauthn/login/start` |
120
+ | `webauthn.loginFinish(assertion)` | `POST /auth/webauthn/login/finish` |
121
+
122
+ ### `authyon.sso` (login social)
123
+
124
+ | Método | Endpoint |
125
+ | -------------------------------- | ------------------------------------------------------------------------------------- |
126
+ | `sso.providers()` | `GET /auth/sso/providers` |
127
+ | `sso.startUrl(provider, params)` | monta a URL de `GET /auth/sso/{provider}/start` (não faz a chamada — navegue até ela) |
128
+ | `sso.exchange(code)` | `POST /auth/sso/exchange` |
129
+
130
+ ## Invalidação de token
131
+
132
+ - **Sessão atual**: `logout()` revoga o refresh token atual; `logout({ everywhere: true })` revoga todos os refresh tokens do usuário.
133
+ - **Uma sessão específica**: `user.revokeSession(sessionId)`, usando o `id` retornado por `user.sessions()` — derruba um dispositivo sem afetar a sessão atual.
134
+ - **Access token**: por ser um JWT stateless, o access token continua "válido" até expirar (`expiresIn`, tipicamente 30 min) mesmo após revogar o refresh token. Para checar revogação em tempo real no seu backend, use `validate()` (cross-checa o estado no banco) em vez de `introspect()`.
135
+
136
+ ## Erros
137
+
138
+ Toda resposta não-2xx vira um `AuthyonError` (problem+json). Compare pelo `code` legível por máquina, nunca pelo `title`:
139
+
140
+ ```ts
141
+ import { AuthyonError, ErrorCodes } from "@authyon/auth";
142
+
143
+ try {
144
+ await authyon.register({ email, password });
145
+ } catch (err) {
146
+ if (err instanceof AuthyonError && err.is(ErrorCodes.EmailTaken)) {
147
+ // e-mail já cadastrado
148
+ }
149
+ }
150
+ ```
151
+
152
+ ## Build
153
+
154
+ ```bash
155
+ npm install
156
+ npm run build # dist/ (ESM + CJS + .d.ts via tsup)
157
+ npm run typecheck
158
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@authyon/auth",
3
- "version": "0.1.5",
3
+ "version": "0.2.0-beta.0",
4
4
  "description": "Authyon SDK for browsers — auth, sessions, multi-tenant and 2FA for vanilla JS/TS.",
5
5
  "license": "MIT",
6
6
  "type": "module",