@mspkapps/auth-client 0.1.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.
- package/README.md +88 -0
- package/package.json +26 -0
- package/src/AuthClient.js +73 -0
- package/src/errors.js +9 -0
- package/src/index.js +2 -0
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Auth Client SDK
|
|
2
|
+
|
|
3
|
+
Lightweight JavaScript client for Your Auth Service.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
```bash
|
|
7
|
+
npm install @your-scope/auth-client
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Quick Start (Browser / React)
|
|
11
|
+
```javascript
|
|
12
|
+
import { AuthClient } from '@mspk-apps/auth-client';
|
|
13
|
+
const auth = new AuthClient({ baseUrl: 'https://api.mspkapps.in/api/v1', apiKey: 'PUBLIC_KEY' });
|
|
14
|
+
|
|
15
|
+
async function doLogin() {
|
|
16
|
+
try {
|
|
17
|
+
const res = await auth.login({ email: 'user@example.com', password: 'Pass123!' });
|
|
18
|
+
console.log('Logged in user:', res.data.user);
|
|
19
|
+
} catch (e) {
|
|
20
|
+
console.error(e);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Store `auth.token` (access token) in memory or secure cookie. Avoid localStorage for high-security apps.
|
|
26
|
+
|
|
27
|
+
## Node (Server-side proxy)
|
|
28
|
+
```javascript
|
|
29
|
+
import { AuthClient } from '@mspk-apps/auth-client';
|
|
30
|
+
const auth = new AuthClient({
|
|
31
|
+
baseUrl: process.env.AUTH_BASE_URL,
|
|
32
|
+
apiKey: process.env.AUTH_API_KEY,
|
|
33
|
+
apiSecret: process.env.AUTH_API_SECRET // keep secret server-side only
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Methods
|
|
38
|
+
- `register({ email, password, name?, username? })`
|
|
39
|
+
- `login({ email, password })`
|
|
40
|
+
- `getProfile()`
|
|
41
|
+
- `verifyEmail(token)`
|
|
42
|
+
- `authed('/custom-endpoint', { method:'POST', body:{...} })`
|
|
43
|
+
|
|
44
|
+
## Error Handling
|
|
45
|
+
Errors throw `AuthError`:
|
|
46
|
+
```javascript
|
|
47
|
+
try {
|
|
48
|
+
await auth.login({ email, password });
|
|
49
|
+
} catch (err) {
|
|
50
|
+
if (err.status === 401) { /* invalid credentials */ }
|
|
51
|
+
console.log(err.code, err.message);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## React Native
|
|
56
|
+
Use same API. For token persistence use `expo-secure-store`:
|
|
57
|
+
```javascript
|
|
58
|
+
import * as SecureStore from 'expo-secure-store';
|
|
59
|
+
const auth = new AuthClient({ baseUrl: 'https://api.mspkapps.in/api/v1', apiKey: 'PUBLIC_KEY' });
|
|
60
|
+
await auth.login({ email, password });
|
|
61
|
+
await SecureStore.setItemAsync('auth_token', auth.token);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Security
|
|
65
|
+
- Never bundle apiSecret in client apps.
|
|
66
|
+
- Use HTTPS.
|
|
67
|
+
- Rotate keys via dashboard.
|
|
68
|
+
- Implement refresh token endpoint (future) for long sessions.
|
|
69
|
+
|
|
70
|
+
## Publish
|
|
71
|
+
1. Set fields in package.json (name, version, author).
|
|
72
|
+
2. Login to npm: `npm login`
|
|
73
|
+
3. Publish: `npm publish --access public`
|
|
74
|
+
|
|
75
|
+
## Local Development Test
|
|
76
|
+
From `SDK` folder:
|
|
77
|
+
```bash
|
|
78
|
+
npm link
|
|
79
|
+
```
|
|
80
|
+
In app project:
|
|
81
|
+
```bash
|
|
82
|
+
npm link @mspk-apps/auth-client
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Future Expansion
|
|
86
|
+
- Add `refreshToken()` when backend supports it.
|
|
87
|
+
- Add TypeScript definitions.
|
|
88
|
+
- Add revoke & password reset helpers.
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mspkapps/auth-client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Lightweight client for Your Auth Service",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"keywords": ["auth","sdk","jwt","client"],
|
|
16
|
+
"author": "MSPK Apps",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"publishConfig": { "access": "public" },
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/mspk5196/authServiceNpm.git"
|
|
22
|
+
},
|
|
23
|
+
"bugs": { "url": "https://github.com/mspk5196/authServiceNpm/issues" },
|
|
24
|
+
"homepage": "https://github.com/mspk5196/authServiceNpm#readme",
|
|
25
|
+
"engines": { "node": ">=18" }
|
|
26
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { AuthError } from './errors.js';
|
|
2
|
+
|
|
3
|
+
export class AuthClient {
|
|
4
|
+
constructor(opts = {}) {
|
|
5
|
+
this.baseUrl = opts.baseUrl?.replace(/\/+$/,'') || 'http://localhost:5001/api/v1';
|
|
6
|
+
this.apiKey = opts.apiKey || null; // Public key (optional)
|
|
7
|
+
this.apiSecret = opts.apiSecret || null; // NEVER use secret in browser
|
|
8
|
+
this.token = null;
|
|
9
|
+
this.fetchFn = opts.fetch || fetch;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
setToken(token) {
|
|
13
|
+
this.token = token;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
clearToken() {
|
|
17
|
+
this.token = null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async register({ email, password, name, username }) {
|
|
21
|
+
return this._request('POST', '/register', { email, password, name, username });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async login({ email, password }) {
|
|
25
|
+
const res = await this._request('POST', '/login', { email, password });
|
|
26
|
+
if (res?.data?.access_token) this.token = res.data.access_token;
|
|
27
|
+
return res;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async getProfile() {
|
|
31
|
+
return this._request('GET', '/user/profile');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async verifyEmail(token) {
|
|
35
|
+
return this._request('GET', `/verify-email?token=${encodeURIComponent(token)}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Generic authed request to your protected API (public layer)
|
|
39
|
+
async authed(path, options = {}) {
|
|
40
|
+
return this._request(options.method || 'GET', path, options.body, options);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async _request(method, path, body, extra = {}) {
|
|
44
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
45
|
+
|
|
46
|
+
// Optional API key/secret (only server-side for secret)
|
|
47
|
+
if (this.apiKey) headers['X-API-Key'] = this.apiKey;
|
|
48
|
+
if (this.apiSecret) headers['X-API-Secret'] = this.apiSecret;
|
|
49
|
+
|
|
50
|
+
if (this.token) headers['Authorization'] = `Bearer ${this.token}`;
|
|
51
|
+
|
|
52
|
+
const url = path.startsWith('http') ? path : this.baseUrl + path;
|
|
53
|
+
|
|
54
|
+
const resp = await this.fetchFn(url, {
|
|
55
|
+
method,
|
|
56
|
+
headers,
|
|
57
|
+
body: body && method !== 'GET' ? JSON.stringify(body) : undefined
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const json = await resp.json().catch(() => ({}));
|
|
61
|
+
|
|
62
|
+
if (!resp.ok || json.success === false) {
|
|
63
|
+
throw new AuthError(
|
|
64
|
+
json.message || 'Request failed',
|
|
65
|
+
resp.status,
|
|
66
|
+
json.error || 'REQUEST_FAILED',
|
|
67
|
+
json
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return json;
|
|
72
|
+
}
|
|
73
|
+
}
|
package/src/errors.js
ADDED
package/src/index.js
ADDED