binoauth 0.0.1

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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # binoauth
2
+
3
+ ## 0.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Initial
package/README.md ADDED
@@ -0,0 +1,265 @@
1
+ # binoauth
2
+
3
+ A simplified Node.js SDK for BinoAuth authentication that provides OAuth2-compatible tokens without the complexity of traditional OAuth2 flows.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install binoauth
9
+ # or
10
+ yarn add binoauth
11
+ # or
12
+ bun add binoauth
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import BinoAuth from 'binoauth';
19
+
20
+ const auth = new BinoAuth({
21
+ apiKey: 'ak_live_your_api_key',
22
+ tenant: 'your-tenant-id'
23
+ });
24
+
25
+ // Email OTP
26
+ const resp = await auth.sendEmailOTP('user@example.com');
27
+ if (resp.ok) {
28
+ console.log('OTP sent successfully');
29
+ }
30
+
31
+ // Login with password
32
+ const loginResp = await auth.login('password', {
33
+ email: 'user@example.com',
34
+ password: 'password123'
35
+ });
36
+
37
+ if (loginResp.ok) {
38
+ console.log('Login successful:', loginResp.data);
39
+ }
40
+ ```
41
+
42
+ ## Features
43
+
44
+ ### Authentication Methods
45
+ - **Email OTP**: Send and verify email-based one-time passwords
46
+ - **Phone OTP**: Send and verify SMS-based one-time passwords
47
+ - **Password Login**: Traditional email/password authentication
48
+ - **Magic Links**: Passwordless email-based authentication
49
+ - **Device Code Flow**: For CLI applications and IoT devices
50
+
51
+ ### Token Management
52
+ - **OAuth2 Compatible**: All tokens work with existing OAuth2 resource servers
53
+ - **Refresh Tokens**: Automatic token refresh capabilities
54
+ - **Session Management**: Secure logout and session invalidation
55
+
56
+ ### User Management
57
+ - **Profile Access**: Get and update user profiles
58
+ - **User Administration**: Create, read, update, delete users (admin API)
59
+
60
+ ## API Reference
61
+
62
+ ### Constructor
63
+
64
+ ```typescript
65
+ const auth = new BinoAuth({
66
+ apiKey: string; // Your BinoAuth API key
67
+ tenant: string; // Your tenant ID
68
+ baseUrl?: string; // Optional: Custom API base URL
69
+ });
70
+ ```
71
+
72
+ ### Authentication Methods
73
+
74
+ #### `sendEmailOTP(email: string)`
75
+ Send an OTP code to the user's email address.
76
+
77
+ ```typescript
78
+ const result = await auth.sendEmailOTP('user@example.com');
79
+ ```
80
+
81
+ #### `sendPhoneOTP(phone: string)`
82
+ Send an OTP code to the user's phone number.
83
+
84
+ ```typescript
85
+ const result = await auth.sendPhoneOTP('+1234567890');
86
+ ```
87
+
88
+ #### `sendMagicLink(email: string)`
89
+ Send a magic link to the user's email address.
90
+
91
+ ```typescript
92
+ const result = await auth.sendMagicLink('user@example.com');
93
+ ```
94
+
95
+ #### `login(type: 'password' | 'otp', credentials: LoginCredentials)`
96
+ Authenticate a user with different methods.
97
+
98
+ ```typescript
99
+ // Password login
100
+ const result = await auth.login('password', {
101
+ email: 'user@example.com',
102
+ password: 'password123'
103
+ });
104
+
105
+ // OTP login
106
+ const result = await auth.login('otp', {
107
+ otp: '123456',
108
+ phone: '+1234567890' // Optional: specify if phone OTP
109
+ });
110
+ ```
111
+
112
+ ### Password Reset
113
+
114
+ #### `sendResetPasswordEmailOTP(email: string)`
115
+ Send a password reset OTP to email.
116
+
117
+ ```typescript
118
+ const result = await auth.sendResetPasswordEmailOTP('user@example.com');
119
+ ```
120
+
121
+ #### `sendResetPasswordPhoneOTP(phone: string)`
122
+ Send a password reset OTP to phone.
123
+
124
+ ```typescript
125
+ const result = await auth.sendResetPasswordPhoneOTP('+1234567890');
126
+ ```
127
+
128
+ #### `resetPassword(params: ResetPasswordParams)`
129
+ Reset user password with OTP verification.
130
+
131
+ ```typescript
132
+ const result = await auth.resetPassword({
133
+ otp: '123456',
134
+ newPassword: 'newpassword123',
135
+ repeatNewPassword: 'newpassword123'
136
+ });
137
+ ```
138
+
139
+ ### Token Management
140
+
141
+ #### `refreshToken(refreshToken: string)`
142
+ Refresh an access token using a refresh token.
143
+
144
+ ```typescript
145
+ const result = await auth.refreshToken('refresh_token_here');
146
+ ```
147
+
148
+ #### `logout(accessToken?: string)`
149
+ Logout and invalidate session.
150
+
151
+ ```typescript
152
+ const result = await auth.logout('access_token_here');
153
+ ```
154
+
155
+ ### User Profile
156
+
157
+ #### `getProfile()`
158
+ Get the current user's profile information.
159
+
160
+ ```typescript
161
+ const result = await auth.getProfile();
162
+ ```
163
+
164
+ ### Device Code Flow
165
+
166
+ #### `requestDeviceCode()`
167
+ Request a device code for CLI/IoT authentication.
168
+
169
+ ```typescript
170
+ const result = await auth.requestDeviceCode();
171
+ console.log(`Visit: ${result.data.verification_uri}`);
172
+ console.log(`Code: ${result.data.user_code}`);
173
+ ```
174
+
175
+ #### `pollDeviceToken(deviceCode: string)`
176
+ Poll for device authorization completion.
177
+
178
+ ```typescript
179
+ const result = await auth.pollDeviceToken('device_code_here');
180
+ ```
181
+
182
+ ### User Management (Admin API)
183
+
184
+ #### `getUser(userId: string)`
185
+ Get user information by ID.
186
+
187
+ ```typescript
188
+ const result = await auth.getUser('user_id_here');
189
+ ```
190
+
191
+ #### `getUsers(params?: { page?: number; limit?: number })`
192
+ Get paginated list of users.
193
+
194
+ ```typescript
195
+ const result = await auth.getUsers({ page: 1, limit: 10 });
196
+ ```
197
+
198
+ #### `createUser(userData: any)`
199
+ Create a new user (not implemented in current admin SDK).
200
+
201
+ #### `updateUser(userId: string, userData: any)`
202
+ Update user information (not implemented in current admin SDK).
203
+
204
+ #### `deleteUser(userId: string)`
205
+ Delete a user (not implemented in current admin SDK).
206
+
207
+ ## Response Format
208
+
209
+ All methods return a `BinoAuthResponse` object:
210
+
211
+ ```typescript
212
+ interface BinoAuthResponse<T = any> {
213
+ ok: boolean; // Success indicator
214
+ data?: T; // Response data (if successful)
215
+ error?: string; // Error message (if failed)
216
+ error_description?: string; // Detailed error description (if failed)
217
+ }
218
+ ```
219
+
220
+ ## Error Handling
221
+
222
+ ```typescript
223
+ const result = await auth.login('password', {
224
+ email: 'user@example.com',
225
+ password: 'wrong_password'
226
+ });
227
+
228
+ if (!result.ok) {
229
+ console.error('Login failed:', result.error);
230
+ console.error('Details:', result.error_description);
231
+ } else {
232
+ console.log('Login successful:', result.data);
233
+ }
234
+ ```
235
+
236
+ ## OAuth2 Compatibility
237
+
238
+ All tokens generated by this SDK are OAuth2-compatible JWT tokens that can be used with:
239
+ - Resource servers expecting OAuth2 Bearer tokens
240
+ - Existing OAuth2 middleware and libraries
241
+ - Standard Authorization headers: `Authorization: Bearer <token>`
242
+
243
+ ## Development
244
+
245
+ ```bash
246
+ # Install dependencies
247
+ bun install
248
+
249
+ # Build the package
250
+ bun run build
251
+
252
+ # Watch mode for development
253
+ bun run dev
254
+ ```
255
+
256
+ ## License
257
+
258
+ MIT
259
+
260
+ ## Support
261
+
262
+ For issues and questions:
263
+ - GitHub Issues: [binoauth/binoauth](https://github.com/binoauth/binoauth/issues)
264
+ - Email: support@binoauth.com
265
+ - Documentation: [docs.binoauth.com](https://docs.binoauth.com)
@@ -0,0 +1,51 @@
1
+ export interface BinoAuthConfig {
2
+ apiKey: string;
3
+ tenant: string;
4
+ baseUrl?: string;
5
+ }
6
+ export interface LoginCredentials {
7
+ email?: string;
8
+ password?: string;
9
+ otp?: string;
10
+ phone?: string;
11
+ }
12
+ export interface BinoAuthResponse<T = any> {
13
+ ok: boolean;
14
+ data?: T;
15
+ error?: string;
16
+ error_description?: string;
17
+ }
18
+ export declare class BinoAuth {
19
+ private tenantConfig;
20
+ private adminConfig;
21
+ private authApi;
22
+ private oauthApi;
23
+ private userProfileApi;
24
+ private adminApi;
25
+ constructor(config: BinoAuthConfig);
26
+ sendEmailOTP(email: string): Promise<BinoAuthResponse>;
27
+ sendPhoneOTP(phone: string): Promise<BinoAuthResponse>;
28
+ sendMagicLink(email: string): Promise<BinoAuthResponse>;
29
+ login(type: 'password' | 'otp', credentials: LoginCredentials): Promise<BinoAuthResponse>;
30
+ sendResetPasswordEmailOTP(email: string): Promise<BinoAuthResponse>;
31
+ sendResetPasswordPhoneOTP(phone: string): Promise<BinoAuthResponse>;
32
+ resetPassword(params: {
33
+ otp: string;
34
+ newPassword: string;
35
+ repeatNewPassword: string;
36
+ }): Promise<BinoAuthResponse>;
37
+ refreshToken(refreshToken: string): Promise<BinoAuthResponse>;
38
+ logout(accessToken?: string): Promise<BinoAuthResponse>;
39
+ getProfile(): Promise<BinoAuthResponse>;
40
+ requestDeviceCode(): Promise<BinoAuthResponse>;
41
+ pollDeviceToken(deviceCode: string): Promise<BinoAuthResponse>;
42
+ createUser(userData: any): Promise<BinoAuthResponse>;
43
+ getUser(userId: string): Promise<BinoAuthResponse>;
44
+ getUsers(params?: {
45
+ page?: number;
46
+ limit?: number;
47
+ }): Promise<BinoAuthResponse>;
48
+ updateUser(userId: string, userData: any): Promise<BinoAuthResponse>;
49
+ deleteUser(userId: string): Promise<BinoAuthResponse>;
50
+ }
51
+ export default BinoAuth;
@@ -0,0 +1,343 @@
1
+ import { AuthenticationApi, OAuth2Api, UserProfileApi, Configuration as TenantConfiguration } from '@binoauth/tenant-sdk';
2
+ import { AdminApi, Configuration as AdminConfiguration } from '@binoauth/admin-sdk';
3
+ export class BinoAuth {
4
+ constructor(config) {
5
+ const baseUrl = config.baseUrl || 'https://api.binoauth.com';
6
+ // Configure tenant SDK
7
+ this.tenantConfig = new TenantConfiguration({
8
+ basePath: baseUrl,
9
+ headers: {
10
+ 'X-API-Key': config.apiKey,
11
+ 'X-Tenant-ID': config.tenant
12
+ }
13
+ });
14
+ // Configure admin SDK
15
+ this.adminConfig = new AdminConfiguration({
16
+ basePath: baseUrl,
17
+ headers: {
18
+ 'X-API-Key': config.apiKey,
19
+ 'X-Tenant-ID': config.tenant
20
+ }
21
+ });
22
+ // Initialize APIs
23
+ this.authApi = new AuthenticationApi(this.tenantConfig);
24
+ this.oauthApi = new OAuth2Api(this.tenantConfig);
25
+ this.userProfileApi = new UserProfileApi(this.tenantConfig);
26
+ this.adminApi = new AdminApi(this.adminConfig);
27
+ }
28
+ // Authentication Methods
29
+ async sendEmailOTP(email) {
30
+ try {
31
+ const response = await this.authApi.requestMagicLinkApiV1AuthMlPost({
32
+ magicLinkRequest: { email }
33
+ });
34
+ return { ok: true, data: response };
35
+ }
36
+ catch (error) {
37
+ return {
38
+ ok: false,
39
+ error: error.message || 'Failed to send email OTP',
40
+ error_description: error.response?.data?.detail || error.message
41
+ };
42
+ }
43
+ }
44
+ async sendPhoneOTP(phone) {
45
+ try {
46
+ const response = await this.authApi.requestOtpViaPhoneApiV1AuthPhonePost({
47
+ phoneOTPRequest: { phone }
48
+ });
49
+ return { ok: true, data: response };
50
+ }
51
+ catch (error) {
52
+ return {
53
+ ok: false,
54
+ error: error.message || 'Failed to send phone OTP',
55
+ error_description: error.response?.data?.detail || error.message
56
+ };
57
+ }
58
+ }
59
+ async sendMagicLink(email) {
60
+ try {
61
+ const response = await this.authApi.requestMagicLinkApiV1AuthMlPost({
62
+ magicLinkRequest: { email }
63
+ });
64
+ return { ok: true, data: response };
65
+ }
66
+ catch (error) {
67
+ return {
68
+ ok: false,
69
+ error: error.message || 'Failed to send magic link',
70
+ error_description: error.response?.data?.detail || error.message
71
+ };
72
+ }
73
+ }
74
+ async login(type, credentials) {
75
+ try {
76
+ let response;
77
+ if (type === 'password') {
78
+ if (!credentials.email || !credentials.password) {
79
+ return {
80
+ ok: false,
81
+ error: 'Missing credentials',
82
+ error_description: 'Email and password are required for password login'
83
+ };
84
+ }
85
+ response = await this.authApi.loginApiV1AuthLoginPost({
86
+ loginRequest: {
87
+ email: credentials.email,
88
+ password: credentials.password
89
+ }
90
+ });
91
+ }
92
+ else if (type === 'otp') {
93
+ if (!credentials.otp) {
94
+ return {
95
+ ok: false,
96
+ error: 'Missing OTP',
97
+ error_description: 'OTP code is required for OTP login'
98
+ };
99
+ }
100
+ // For OTP login, we need to verify the OTP
101
+ if (credentials.phone) {
102
+ response = await this.authApi.verifyPhoneOtpApiV1AuthPhoneVerifyPost({
103
+ phoneOTPVerificationRequest: {
104
+ otp: credentials.otp.toString()
105
+ }
106
+ });
107
+ }
108
+ else {
109
+ response = await this.authApi.verifyMagicLinkCodeApiV1AuthMlCodeVerifyPost({
110
+ verifyMagicLinkCodeRequest: {
111
+ code: credentials.otp.toString()
112
+ }
113
+ });
114
+ }
115
+ }
116
+ return { ok: true, data: response };
117
+ }
118
+ catch (error) {
119
+ return {
120
+ ok: false,
121
+ error: error.message || 'Login failed',
122
+ error_description: error.response?.data?.detail || error.message
123
+ };
124
+ }
125
+ }
126
+ // Password Reset
127
+ async sendResetPasswordEmailOTP(email) {
128
+ try {
129
+ const response = await this.authApi.requestMagicLinkApiV1AuthMlPost({
130
+ magicLinkRequest: { email }
131
+ });
132
+ return { ok: true, data: response };
133
+ }
134
+ catch (error) {
135
+ return {
136
+ ok: false,
137
+ error: error.message || 'Failed to send reset password email',
138
+ error_description: error.response?.data?.detail || error.message
139
+ };
140
+ }
141
+ }
142
+ async sendResetPasswordPhoneOTP(phone) {
143
+ try {
144
+ const response = await this.authApi.requestOtpViaPhoneApiV1AuthPhonePost({
145
+ phoneOTPRequest: { phone }
146
+ });
147
+ return { ok: true, data: response };
148
+ }
149
+ catch (error) {
150
+ return {
151
+ ok: false,
152
+ error: error.message || 'Failed to send reset password phone OTP',
153
+ error_description: error.response?.data?.detail || error.message
154
+ };
155
+ }
156
+ }
157
+ async resetPassword(params) {
158
+ try {
159
+ if (params.newPassword !== params.repeatNewPassword) {
160
+ return {
161
+ ok: false,
162
+ error: 'Password mismatch',
163
+ error_description: 'New password and repeat password do not match'
164
+ };
165
+ }
166
+ // This would typically be handled by verifying the OTP first, then updating password
167
+ // For now, we'll verify the magic link code
168
+ const response = await this.authApi.verifyMagicLinkCodeApiV1AuthMlCodeVerifyPost({
169
+ verifyMagicLinkCodeRequest: {
170
+ code: params.otp
171
+ }
172
+ });
173
+ return { ok: true, data: response };
174
+ }
175
+ catch (error) {
176
+ return {
177
+ ok: false,
178
+ error: error.message || 'Failed to reset password',
179
+ error_description: error.response?.data?.detail || error.message
180
+ };
181
+ }
182
+ }
183
+ // Token Management
184
+ async refreshToken(refreshToken) {
185
+ try {
186
+ const response = await this.oauthApi.getTokensApiV1OauthTokenPost({
187
+ tokenRequest: {
188
+ grantType: 'refresh_token',
189
+ clientId: 'binoauth-sdk',
190
+ refreshToken: refreshToken
191
+ }
192
+ });
193
+ return { ok: true, data: response };
194
+ }
195
+ catch (error) {
196
+ return {
197
+ ok: false,
198
+ error: error.message || 'Failed to refresh token',
199
+ error_description: error.response?.data?.detail || error.message
200
+ };
201
+ }
202
+ }
203
+ async logout(accessToken) {
204
+ try {
205
+ const response = await this.authApi.logoutApiV1AuthLogoutPost({
206
+ sessionBinoauth: accessToken || ''
207
+ });
208
+ return { ok: true, data: response };
209
+ }
210
+ catch (error) {
211
+ return {
212
+ ok: false,
213
+ error: error.message || 'Failed to logout',
214
+ error_description: error.response?.data?.detail || error.message
215
+ };
216
+ }
217
+ }
218
+ // User Profile
219
+ async getProfile() {
220
+ try {
221
+ const response = await this.userProfileApi.getCurrentUserApiV1AuthUserinfoGet();
222
+ return { ok: true, data: response };
223
+ }
224
+ catch (error) {
225
+ return {
226
+ ok: false,
227
+ error: error.message || 'Failed to get profile',
228
+ error_description: error.response?.data?.detail || error.message
229
+ };
230
+ }
231
+ }
232
+ // Device Code Flow
233
+ async requestDeviceCode() {
234
+ try {
235
+ const response = await this.oauthApi.deviceAuthorizationApiV1OauthDeviceCodePost({
236
+ deviceAuthorizationRequest: {
237
+ clientId: 'binoauth-sdk'
238
+ }
239
+ });
240
+ return { ok: true, data: response };
241
+ }
242
+ catch (error) {
243
+ return {
244
+ ok: false,
245
+ error: error.message || 'Failed to request device code',
246
+ error_description: error.response?.data?.detail || error.message
247
+ };
248
+ }
249
+ }
250
+ async pollDeviceToken(deviceCode) {
251
+ try {
252
+ const response = await this.oauthApi.getTokensApiV1OauthTokenPost({
253
+ tokenRequest: {
254
+ grantType: 'urn:ietf:params:oauth:grant-type:device_code',
255
+ clientId: 'binoauth-sdk',
256
+ deviceCode: deviceCode
257
+ }
258
+ });
259
+ return { ok: true, data: response };
260
+ }
261
+ catch (error) {
262
+ return {
263
+ ok: false,
264
+ error: error.message || 'Failed to poll device token',
265
+ error_description: error.response?.data?.detail || error.message
266
+ };
267
+ }
268
+ }
269
+ // User Management (Admin API)
270
+ async createUser(userData) {
271
+ try {
272
+ // Admin API user creation method may not be available - this is a placeholder
273
+ throw new Error('User creation not implemented in admin SDK');
274
+ }
275
+ catch (error) {
276
+ return {
277
+ ok: false,
278
+ error: error.message || 'Failed to create user',
279
+ error_description: error.response?.data?.detail || error.message
280
+ };
281
+ }
282
+ }
283
+ async getUser(userId) {
284
+ try {
285
+ const response = await this.adminApi.getUserApiV1UsersUserIdGet({
286
+ userId,
287
+ xTenantId: ''
288
+ });
289
+ return { ok: true, data: response };
290
+ }
291
+ catch (error) {
292
+ return {
293
+ ok: false,
294
+ error: error.message || 'Failed to get user',
295
+ error_description: error.response?.data?.detail || error.message
296
+ };
297
+ }
298
+ }
299
+ async getUsers(params = {}) {
300
+ try {
301
+ const response = await this.adminApi.getUsersApiV1UsersGet({
302
+ page: params.page || 1,
303
+ limit: params.limit || 10,
304
+ xTenantId: ''
305
+ });
306
+ return { ok: true, data: response };
307
+ }
308
+ catch (error) {
309
+ return {
310
+ ok: false,
311
+ error: error.message || 'Failed to get users',
312
+ error_description: error.response?.data?.detail || error.message
313
+ };
314
+ }
315
+ }
316
+ async updateUser(userId, userData) {
317
+ try {
318
+ // Admin API user update method may not be available - this is a placeholder
319
+ throw new Error('User update not implemented in admin SDK');
320
+ }
321
+ catch (error) {
322
+ return {
323
+ ok: false,
324
+ error: error.message || 'Failed to update user',
325
+ error_description: error.response?.data?.detail || error.message
326
+ };
327
+ }
328
+ }
329
+ async deleteUser(userId) {
330
+ try {
331
+ // Admin API user delete method may not be available - this is a placeholder
332
+ throw new Error('User delete not implemented in admin SDK');
333
+ }
334
+ catch (error) {
335
+ return {
336
+ ok: false,
337
+ error: error.message || 'Failed to delete user',
338
+ error_description: error.response?.data?.detail || error.message
339
+ };
340
+ }
341
+ }
342
+ }
343
+ export default BinoAuth;