Docker, Token-Refresh mit Puppeteer, 401-Hinweise
- Dockerfile + .dockerignore - token-refresh: Chromium öffnet drive.internxt.com, extrahiert Tokens - 401-Antworten: Link zu drive.internxt.com - Docs: Token-Erneuerung Option A (automatisch) / B (manuell) Made-with: Cursor
This commit is contained in:
7
.dockerignore
Normal file
7
.dockerignore
Normal file
@@ -0,0 +1,7 @@
|
||||
node_modules
|
||||
.git
|
||||
.env
|
||||
.env.*
|
||||
*.log
|
||||
docs
|
||||
drive-web
|
||||
13
Dockerfile
Normal file
13
Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM node:20-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci --omit=dev
|
||||
|
||||
COPY src ./src
|
||||
|
||||
ENV NODE_ENV=production
|
||||
EXPOSE 3005
|
||||
|
||||
CMD ["node", "src/server.js"]
|
||||
21
README.md
21
README.md
@@ -19,6 +19,25 @@ npm start
|
||||
|
||||
Server läuft auf `http://127.0.0.1:3005`.
|
||||
|
||||
## Docker
|
||||
|
||||
```bash
|
||||
# Image bauen
|
||||
docker build -t internxt-webdav .
|
||||
|
||||
# Container starten (Umgebungsvariablen aus .env)
|
||||
docker run -d --name internxt-webdav -p 3005:3005 --env-file .env internxt-webdav
|
||||
|
||||
# Oder einzelne Variablen übergeben
|
||||
docker run -d -p 3005:3005 \
|
||||
-e INXT_TOKEN="..." \
|
||||
-e INXT_MNEMONIC="..." \
|
||||
-e CRYPTO_SECRET="6KYQBP847D4ATSFA" \
|
||||
internxt-webdav
|
||||
```
|
||||
|
||||
WebDAV erreichbar unter `http://localhost:3005`.
|
||||
|
||||
## WebDAV-Funktionen
|
||||
|
||||
- **PROPFIND** – Verzeichnis auflisten
|
||||
@@ -50,5 +69,5 @@ Server läuft auf `http://127.0.0.1:3005`.
|
||||
|-------|--------------|
|
||||
| `npm start` | WebDAV-Server starten |
|
||||
| `npm run token-test` | Token prüfen |
|
||||
| `npm run auth-test` | API-Login testen (E-Mail/Passwort) |
|
||||
| `npm run token-refresh` | Browser öffnen, einloggen → Tokens automatisch extrahieren |
|
||||
| `npm run debug-names` | Namensentschlüsselung testen |
|
||||
|
||||
@@ -87,9 +87,27 @@ robocopy "i:\" "." /NFL /NDL
|
||||
# Variante 3: Explorer – Datei per Drag & Drop kopieren
|
||||
``` Windows Explorer: Netzlaufwerk verbinden → `http://127.0.0.1:3005`.
|
||||
|
||||
## Token erneuern (bei 401 / abgelaufen)
|
||||
|
||||
Tokens laufen nach einiger Zeit ab (typisch Stunden). Bei 401-Fehlern oder „Nicht autorisiert“:
|
||||
|
||||
### Option A: Automatisch (Chromium)
|
||||
|
||||
```bash
|
||||
npm run token-refresh
|
||||
```
|
||||
|
||||
Öffnet einen Browser mit drive.internxt.com. Einloggen – die Tokens werden automatisch extrahiert und in der Konsole ausgegeben. In `.env` eintragen, Server neu starten.
|
||||
|
||||
### Option B: Manuell
|
||||
|
||||
1. **[https://drive.internxt.com](https://drive.internxt.com)** öffnen und erneut einloggen
|
||||
2. Token und Mnemonic wie oben (Schritt 2) aus der Console auslesen
|
||||
3. `.env` mit den neuen Werten aktualisieren
|
||||
4. WebDAV-Server neu starten
|
||||
|
||||
## Hinweise
|
||||
|
||||
- **Bridge-API**: Der Download nutzt die Internxt Bridge mit `x-api-version: 2` und den Headern `internxt-version`/`internxt-client`. Ohne diese liefert die Bridge 400.
|
||||
- **Token-Ablauf**: Tokens laufen nach einiger Zeit ab (typisch Stunden). Bei 401-Fehlern erneut einloggen und Token aktualisieren.
|
||||
- **Sicherheit**: Mnemonic und Token sind hochsensibel. Nicht in Git committen, `.env` in `.gitignore` belassen.
|
||||
- **Nur für Sie**: Die Tokens sind an Ihre Session gebunden. Für andere Nutzer funktioniert dieser Ansatz nicht.
|
||||
|
||||
1378
package-lock.json
generated
1378
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,7 @@
|
||||
"scripts": {
|
||||
"auth-test": "node src/auth-poc.js",
|
||||
"token-test": "node src/token-test.js",
|
||||
"token-refresh": "node src/token-refresh.js",
|
||||
"debug-names": "node src/debug-name-decrypt.js",
|
||||
"start": "node src/server.js"
|
||||
},
|
||||
@@ -15,6 +16,7 @@
|
||||
"bip39": "^3.1.0",
|
||||
"crypto-js": "^4.1.1",
|
||||
"dotenv": "^16.0.0",
|
||||
"express": "^4.18.0"
|
||||
"express": "^4.18.0",
|
||||
"puppeteer": "^24.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ async function handlePropfind(req, res) {
|
||||
} catch (err) {
|
||||
console.error('PROPFIND Fehler:', err.message);
|
||||
if (err.message?.includes('Token') || err.response?.status === 401) {
|
||||
res.status(401).send('Nicht autorisiert – Token erneuern');
|
||||
res.status(401).send('Nicht autorisiert – Token abgelaufen. Neu einloggen: https://drive.internxt.com');
|
||||
return;
|
||||
}
|
||||
res.status(500).send(err.message || 'Interner Fehler');
|
||||
@@ -304,7 +304,7 @@ async function handleMkcol(req, res) {
|
||||
} catch (err) {
|
||||
console.error('MKCOL Fehler:', err.message);
|
||||
if (err.message?.includes('Token') || err.response?.status === 401) {
|
||||
res.status(401).send('Nicht autorisiert');
|
||||
res.status(401).send('Nicht autorisiert – Token erneuern: https://drive.internxt.com');
|
||||
return;
|
||||
}
|
||||
res.status(500).send(err.message || 'Interner Fehler');
|
||||
@@ -343,7 +343,7 @@ async function handleDelete(req, res) {
|
||||
} catch (err) {
|
||||
console.error('DELETE Fehler:', err.message);
|
||||
if (err.message?.includes('Token') || err.response?.status === 401) {
|
||||
res.status(401).send('Nicht autorisiert');
|
||||
res.status(401).send('Nicht autorisiert – Token erneuern: https://drive.internxt.com');
|
||||
return;
|
||||
}
|
||||
res.status(500).send(err.message || 'Interner Fehler');
|
||||
@@ -429,7 +429,7 @@ async function handleMove(req, res) {
|
||||
} catch (err) {
|
||||
console.error('MOVE Fehler:', err.message);
|
||||
if (err.message?.includes('Token') || err.response?.status === 401) {
|
||||
res.status(401).send('Nicht autorisiert');
|
||||
res.status(401).send('Nicht autorisiert – Token erneuern: https://drive.internxt.com');
|
||||
return;
|
||||
}
|
||||
res.status(500).send(err.message || 'Interner Fehler');
|
||||
@@ -499,7 +499,7 @@ async function handleGet(req, res) {
|
||||
} catch (err) {
|
||||
console.error('GET Fehler:', err.message);
|
||||
if (err.message?.includes('Token') || err.response?.status === 401) {
|
||||
res.status(401).send('Nicht autorisiert');
|
||||
res.status(401).send('Nicht autorisiert – Token erneuern: https://drive.internxt.com');
|
||||
return;
|
||||
}
|
||||
if (!res.headersSent) res.status(500).send(err.message || 'Interner Fehler');
|
||||
@@ -666,7 +666,7 @@ async function handlePut(req, res) {
|
||||
} catch (err) {
|
||||
console.error('PUT Fehler:', err.message);
|
||||
if (err.message?.includes('Token') || err.response?.status === 401) {
|
||||
res.status(401).send('Nicht autorisiert');
|
||||
res.status(401).send('Nicht autorisiert – Token erneuern: https://drive.internxt.com');
|
||||
return;
|
||||
}
|
||||
if (!res.headersSent) res.status(500).send(err.message || 'Interner Fehler');
|
||||
|
||||
58
src/token-refresh.js
Normal file
58
src/token-refresh.js
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Token-Refresh: Öffnet drive.internxt.com im Browser, wartet auf Login,
|
||||
* extrahiert Token und Mnemonic aus localStorage.
|
||||
*
|
||||
* Aufruf: npm run token-refresh
|
||||
*
|
||||
* Browser öffnet sich (headed). Einloggen, dann werden die Tokens ausgegeben.
|
||||
*/
|
||||
|
||||
import puppeteer from 'puppeteer';
|
||||
|
||||
const DRIVE_URL = 'https://drive.internxt.com';
|
||||
const POLL_MS = 2000;
|
||||
const TIMEOUT_MS = 5 * 60 * 1000; // 5 Min
|
||||
|
||||
async function getTokens(page) {
|
||||
return page.evaluate(() => {
|
||||
const token = localStorage.getItem('xNewToken') || localStorage.getItem('xToken');
|
||||
const mnemonic = localStorage.getItem('xMnemonic');
|
||||
return { token, mnemonic };
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('Starte Browser – bitte auf', DRIVE_URL, 'einloggen.\n');
|
||||
|
||||
const browser = await puppeteer.launch({
|
||||
headless: false,
|
||||
defaultViewport: null,
|
||||
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
||||
});
|
||||
|
||||
const page = (await browser.pages())[0] || (await browser.newPage());
|
||||
await page.goto(DRIVE_URL, { waitUntil: 'networkidle2' });
|
||||
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < TIMEOUT_MS) {
|
||||
const { token, mnemonic } = await getTokens(page);
|
||||
if (token && mnemonic) {
|
||||
console.log('\n=== Tokens gefunden – in .env eintragen ===\n');
|
||||
console.log('INXT_TOKEN=' + token);
|
||||
console.log('INXT_MNEMONIC=' + mnemonic);
|
||||
console.log('\n===========================================\n');
|
||||
await browser.close();
|
||||
return;
|
||||
}
|
||||
await new Promise((r) => setTimeout(r, POLL_MS));
|
||||
}
|
||||
|
||||
console.log('Timeout – keine Tokens gefunden. Bitte einloggen und erneut ausführen.');
|
||||
await browser.close();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user