mirror of
https://github.com/danog/TelegramApiServer.git
synced 2024-11-26 11:54:42 +01:00
Add basic auth support
This commit is contained in:
parent
a2baf2de21
commit
8e93934e75
@ -2,6 +2,7 @@
|
||||
# Check for outdated .env files
|
||||
VERSION=1
|
||||
|
||||
# See "ports" in docker-compose.yml.
|
||||
SERVER_ADDRESS=0.0.0.0
|
||||
SERVER_PORT=9503
|
||||
|
||||
@ -21,6 +22,10 @@ REQUESTS_BULK_INTERVAL=0.5
|
||||
# 2) recreate container `docker-compose up -d`
|
||||
IP_WHITELIST=127.0.0.1
|
||||
|
||||
# Allow requests from any IP with given user and password
|
||||
# Example: {"myusername": "mySuperStrongPassword", "otherName": "otherPassword"}
|
||||
PASSWORDS={}
|
||||
|
||||
# TELEGRAM CLIENT
|
||||
TELEGRAM_API_ID=
|
||||
TELEGRAM_API_HASH=
|
||||
|
@ -20,6 +20,10 @@ REQUESTS_BULK_INTERVAL=0.5
|
||||
# Leave blanc, to allow requests from all IP (THIS WILL MAKE API UNSECURE!)
|
||||
IP_WHITELIST=127.0.0.1
|
||||
|
||||
# Allow requests from any IP with given user and password
|
||||
# Example: {"myusername": "mySuperStrongPassword", "otherName": "otherPassword"}
|
||||
PASSWORDS={}
|
||||
|
||||
# TELEGRAM CLIENT
|
||||
TELEGRAM_API_ID=
|
||||
TELEGRAM_API_HASH=
|
||||
|
108
README.md
108
README.md
@ -58,64 +58,58 @@ docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Usage
|
||||
1. Run server/parser
|
||||
```
|
||||
usage: php server.php [--help] [-a=|--address=127.0.0.1] [-p=|--port=9503] [-s=|--session=] [-e=|--env=.env] [--docker]
|
||||
|
||||
Options:
|
||||
--help Show this message
|
||||
|
||||
-a --address Server ip (optional) (default: 127.0.0.1)
|
||||
To listen external connections use 0.0.0.0 and fill IP_WHITELIST in .env
|
||||
|
||||
-p --port Server port (optional) (default: 9503)
|
||||
|
||||
-s --session Name for session file (optional)
|
||||
Multiple sessions can be specified: "--session=user --session=bot"
|
||||
|
||||
Each session is stored in `sessions/{$session}.madeline`.
|
||||
Nested folders supported.
|
||||
See README for more examples.
|
||||
|
||||
-e --env .env file name. (default: .env).
|
||||
Helpful when need multiple instances with different settings
|
||||
|
||||
--docker Apply some settings for docker: add docker network to whitelist.
|
||||
|
||||
Also some options can be set in .env file (see .env.example)
|
||||
```
|
||||
1. Access Telegram API with simple GET/POST requests.
|
||||
Regular and application/json POST supported.
|
||||
It's recommended to use http_build_query, when using GET requests.
|
||||
|
||||
**Rules:**
|
||||
* All methods from MadelineProto supported: [Methods List](https://docs.madelineproto.xyz/API_docs/methods/)
|
||||
* Url: `http://%address%:%port%/api[/%session%]/%class%.%method%/?%param%=%val%`
|
||||
* <b>Important: api available only from ip in whitelist.</b>
|
||||
By default it is: `127.0.0.1`
|
||||
You can add a client IP in .env file to `IP_WHITELIST` (separate with a comma)
|
||||
|
||||
In docker version by default api available only from localhost (127.0.0.1).
|
||||
To allow connections from the internet, need to change ports in docker-compose.yml to `9503:9503` and recreate the container: `docker compose up -d`.
|
||||
This is very insecure, because this will open TAS port to anyone from the internet.
|
||||
Only protection is the `IP_WHITELIST`, and there are no warranties that it will secure your accounts.
|
||||
* If method is inside class (messages, contacts and etc.) use '.' to separate class from method:
|
||||
`http://127.0.0.1:9503/api/contacts.getContacts`
|
||||
* If method requires array of values, use any name of array, for example 'data':
|
||||
`?data[peer]=@xtrime&data[message]=Hello!`. Order of parameters does't matter in this case.
|
||||
* If method requires one or multiple separate parameters (not inside array) then pass parameters with any names but **in strict order**:
|
||||
`http://127.0.0.1:9503/api/getInfo/?id=@xtrime` or `http://127.0.0.1:9503/api/getInfo/?abcd=@xtrime` works the same
|
||||
## Security
|
||||
Please be careful with settings, otherwise you can expose your telegram session and lose control.
|
||||
Default settings allow to access API only from localhost/127.0.0.1.
|
||||
|
||||
**Examples:**
|
||||
* get_info about channel/user: `http://127.0.0.1:9503/api/getInfo/?id=@xtrime`
|
||||
* get_info about currect account: `http://127.0.0.1:9503/api/getSelf`
|
||||
* repost: `http://127.0.0.1:9503/api/messages.forwardMessages/?data[from_peer]=@xtrime&data[to_peer]=@xtrime&data[id]=1234`
|
||||
* get messages from channel/user: `http://127.0.0.1:9503/api/getHistory/?data[peer]=@breakingmash&data[limit]=10`
|
||||
* get messages with text in HTML: `http://127.0.0.1:9503/api/getHistoryHtml/?data[peer]=@breakingmash&data[limit]=10`
|
||||
* search: `http://127.0.0.1:9503/api/searchGlobal/?data[q]=Hello%20World&data[limit]=10`
|
||||
* sendMessage: `http://127.0.0.1:9503/api/sendMessage/?data[peer]=@xtrime&data[message]=Hello!`
|
||||
* copy message from one channel to another (not repost): `http://127.0.0.1:9503/api/copyMessages/?data[from_peer]=@xtrime&data[to_peer]=@xtrime&data[id][0]=1`
|
||||
.env settings:
|
||||
- `IP_WHITELIST` - allow specific IP's to make requests without password.
|
||||
- `PASSWORDS` - protect your api with basic auth.
|
||||
Request with correct username and password overrides IP_WHITELIST.
|
||||
If you specify password, then `IP_WHITELIST` is ignored
|
||||
How to make requests with basic auth:
|
||||
```shell
|
||||
curl --user 'username:password' "http://127.0.0.1:9503/getSelf"
|
||||
curl "http://username:password@127.0.0.1:9503/getSelf"
|
||||
```
|
||||
|
||||
docker-compose.yml:
|
||||
- `port` - port forwarding rules from host to docker container.
|
||||
Remove 127.0.0.1 to listen all interfaces and forward all requests to container.
|
||||
Make sure to use IP_WHITELIST and/or PASSWORDS settings to protect your account.
|
||||
|
||||
## Usage
|
||||
Access Telegram API with simple GET/POST requests.
|
||||
Regular and application/json POST supported.
|
||||
It's recommended to use http_build_query, when using GET requests.
|
||||
|
||||
**Rules:**
|
||||
* All methods from MadelineProto supported: [Methods List](https://docs.madelineproto.xyz/API_docs/methods/)
|
||||
* Url: `http://%address%:%port%/api[/%session%]/%class%.%method%/?%param%=%val%`
|
||||
* <b>Important: api available only from ip in whitelist.</b>
|
||||
By default it is: `127.0.0.1`
|
||||
You can add a client IP in .env file to `IP_WHITELIST` (separate with a comma)
|
||||
|
||||
In docker version by default api available only from localhost (127.0.0.1).
|
||||
To allow connections from the internet, need to change ports in docker-compose.yml to `9503:9503` and recreate the container: `docker compose up -d`.
|
||||
This is very insecure, because this will open TAS port to anyone from the internet.
|
||||
Only protection is the `IP_WHITELIST`, and there are no warranties that it will secure your accounts.
|
||||
* If method is inside class (messages, contacts and etc.) use '.' to separate class from method:
|
||||
`http://127.0.0.1:9503/api/contacts.getContacts`
|
||||
* If method requires array of values, use any name of array, for example 'data':
|
||||
`?data[peer]=@xtrime&data[message]=Hello!`. Order of parameters does't matter in this case.
|
||||
* If method requires one or multiple separate parameters (not inside array) then pass parameters with any names but **in strict order**:
|
||||
`http://127.0.0.1:9503/api/getInfo/?id=@xtrime` or `http://127.0.0.1:9503/api/getInfo/?abcd=@xtrime` works the same
|
||||
|
||||
**Examples:**
|
||||
* get_info about channel/user: `http://127.0.0.1:9503/api/getInfo/?id=@xtrime`
|
||||
* get_info about currect account: `http://127.0.0.1:9503/api/getSelf`
|
||||
* repost: `http://127.0.0.1:9503/api/messages.forwardMessages/?data[from_peer]=@xtrime&data[to_peer]=@xtrime&data[id]=1234`
|
||||
* get messages from channel/user: `http://127.0.0.1:9503/api/getHistory/?data[peer]=@breakingmash&data[limit]=10`
|
||||
* get messages with text in HTML: `http://127.0.0.1:9503/api/getHistoryHtml/?data[peer]=@breakingmash&data[limit]=10`
|
||||
* search: `http://127.0.0.1:9503/api/searchGlobal/?data[q]=Hello%20World&data[limit]=10`
|
||||
* sendMessage: `http://127.0.0.1:9503/api/sendMessage/?data[peer]=@xtrime&data[message]=Hello!`
|
||||
* copy message from one channel to another (not repost): `http://127.0.0.1:9503/api/copyMessages/?data[from_peer]=@xtrime&data[to_peer]=@xtrime&data[id][0]=1`
|
||||
|
||||
## Advanced features
|
||||
### Get events/updates
|
||||
|
12
composer.lock
generated
12
composer.lock
generated
@ -476,16 +476,16 @@
|
||||
},
|
||||
{
|
||||
"name": "amphp/http",
|
||||
"version": "v2.1.0",
|
||||
"version": "v2.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/amphp/http.git",
|
||||
"reference": "9f3500bef4bb15cf41987f21136539c0a06555a3"
|
||||
"reference": "fe6b4dd50c1e70caf823092398074b5082e1d6da"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/amphp/http/zipball/9f3500bef4bb15cf41987f21136539c0a06555a3",
|
||||
"reference": "9f3500bef4bb15cf41987f21136539c0a06555a3",
|
||||
"url": "https://api.github.com/repos/amphp/http/zipball/fe6b4dd50c1e70caf823092398074b5082e1d6da",
|
||||
"reference": "fe6b4dd50c1e70caf823092398074b5082e1d6da",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -528,7 +528,7 @@
|
||||
"description": "Basic HTTP primitives which can be shared by servers and clients.",
|
||||
"support": {
|
||||
"issues": "https://github.com/amphp/http/issues",
|
||||
"source": "https://github.com/amphp/http/tree/v2.1.0"
|
||||
"source": "https://github.com/amphp/http/tree/v2.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -536,7 +536,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-08-22T19:50:46+00:00"
|
||||
"time": "2024-04-03T18:00:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "amphp/http-client",
|
||||
|
@ -64,6 +64,7 @@ $settings = [
|
||||
explode(',', (string)getenv('IP_WHITELIST'))
|
||||
)
|
||||
),
|
||||
'passwords' => (array)json_decode((string)getenv('PASSWORDS'), true),
|
||||
'bulk_interval' => (float)getenv('REQUESTS_BULK_INTERVAL')
|
||||
],
|
||||
'health_check' => [
|
||||
|
@ -13,23 +13,43 @@ class Authorization implements Middleware
|
||||
{
|
||||
private array $ipWhitelist;
|
||||
private int $selfIp;
|
||||
/**
|
||||
* @var array<string,string>
|
||||
*/
|
||||
private array $passwords;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->ipWhitelist = (array)Config::getInstance()->get('api.ip_whitelist', []);
|
||||
$this->selfIp = ip2long(getHostByName(php_uname('n')));
|
||||
$this->ipWhitelist = (array)Config::getInstance()->get('api.ip_whitelist', []);
|
||||
$this->passwords = Config::getInstance()->get('api.passwords', []);
|
||||
if (!$this->ipWhitelist && !$this->passwords) {
|
||||
throw new \InvalidArgumentException('API is unprotected! Please specify IP_WHITELIST or PASSWORD in .env.docker');
|
||||
}
|
||||
}
|
||||
|
||||
public function handleRequest(Request $request, RequestHandler $requestHandler): Response
|
||||
{
|
||||
$host = explode(':', $request->getClient()->getRemoteAddress()->toString())[0];
|
||||
if ($this->isIpAllowed($host)) {
|
||||
$response = $requestHandler->handleRequest($request);
|
||||
} else {
|
||||
$response = ErrorResponses::get(HttpStatus::FORBIDDEN, 'Your host is not allowed: ' . $host);
|
||||
[$host] = explode(':', $request->getClient()->getRemoteAddress()->toString(), 2);
|
||||
|
||||
if ($this->passwords) {
|
||||
$header = (string)$request->getHeader('Authorization');
|
||||
if ($header) {
|
||||
sscanf($header, "Basic %s", $encodedPassword);
|
||||
[$username, $password] = explode(':', base64_decode($encodedPassword), 2);
|
||||
if (array_key_exists($username, $this->passwords) && $this->passwords[$username] === $password) {
|
||||
return $requestHandler->handleRequest($request);
|
||||
}
|
||||
}
|
||||
|
||||
return ErrorResponses::get(HttpStatus::UNAUTHORIZED, 'Username or password is incorrect');
|
||||
}
|
||||
|
||||
return $response;
|
||||
if ($this->isIpAllowed($host)) {
|
||||
return $requestHandler->handleRequest($request);
|
||||
}
|
||||
|
||||
return ErrorResponses::get(HttpStatus::UNAUTHORIZED, 'Your host is not allowed: ' . $host);
|
||||
}
|
||||
|
||||
private function isIpAllowed(string $host): bool
|
||||
|
Loading…
Reference in New Issue
Block a user