Getting Started
Get the latest version of the docker-compose.yaml
file:
services:
signal-api:
image: bbernhard/signal-cli-rest-api:latest
container_name: signal-api
environment:
- MODE=normal
volumes:
- ./data:/home/.local/share/signal-cli
networks:
backend:
aliases:
- signal-api
restart: unless-stopped
secured-signal:
image: ghcr.io/codeshelldev/secured-signal-api:latest
container_name: secured-signal
networks:
backend:
aliases:
- secured-signal-api
environment:
API__URL: http://signal-api:8080
VARIABLES__RECIPIENTS: 000,001,002
VARIABLES__NUMBER: 123456789
API__TOKENS: LOOOOOONG_STRING
ports:
- "8880:8880"
restart: unless-stopped
networks:
backend:
And add secure Token(s) to api.tokens
. See API TOKENs.
[!IMPORTANT]
This Documentation will be using sec-signal-api:8880
as the service host,
this is just for simplicty, instead use your containers or hosts IP + Port.
Or a hostname if applicable. See Reverse Proxy
Reverse proxy
Take a look at the traefik implementation:
services:
secured-signal:
image: ghcr.io/codeshelldev/secured-signal-api:latest
container_name: secured-signal
networks:
proxy:
backend:
aliases:
- secured-signal-api
environment:
API__URL: http://signal-api:8080
DEFAULT_RECIPIENTS: 000,001,002
NUMBER: 123456789
API__TOKENS: LOOOOOONG_STRING
labels:
- traefik.enable=true
- traefik.http.routers.signal-api.rule=Host(`signal-api.mydomain.com`)
- traefik.http.routers.signal-api.entrypoints=websecure
- traefik.http.routers.signal-api.tls=true
- traefik.http.routers.signal-api.tls.certresolver=cloudflare
- traefik.http.routers.signal-api.service=signal-api-svc
- traefik.http.services.signal-api-svc.loadbalancer.server.port=8880
- traefik.docker.network=proxy
restart: unless-stopped
networks:
backend:
proxy:
external: true
Setup
Before you can send messages via Secured Signal API you must first setup Signal rAPI
To be able to use the API you have to either:
- register with your Signal Account
OR
- link Signal API to an already registered Signal Device
[!TIP]
It is advised to do Setup directly with Signal rAPI
if you try to Setup with Secured Signal API you will be blocked from doing so. See Blocked Endpoints.
Usage
Secured Signal API provides 3 Ways to Authenticate
Bearer
To Authenticate add Authorization: Bearer API_TOKEN
to your request Headers
Basic Auth
To use Basic Auth as Authorization Method add Authorization: Basic BASE64_STRING
to your Headers
User is api
(LOWERCASE)
Formatting for BASE64_STRING
= user:API_TOKEN
.
example:
echo "api:API_TOKEN" | base64
=> YXBpOkFQSV9LRVkK
Query Auth
If you are working with a limited Application you may not be able to modify Headers or the Request Body
in this case you can use Query Auth.
Here is a simple example:
curl -X POST http://sec-signal-api:8880/v2/send?@authorization=API_TOKEN
Notice the @
infront of authorization
. See KeyValue Pair Injection.
Example
To send a message to 1234567:
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer API_TOKEN" -d '{"message": "Hello World!", "recipients": ["1234567"]}' http://sec-signal-api:8880/v2/send
Advanced
Placeholders
If you are not comfortable / don't want to hardcode your Number for example and/or Recipients in you, may use Placeholders in your Request. See Custom Variables.
These Placeholders can be used in the Request Query or the Body of a Request like so:
Body
{
"number": "{{ .NUMBER }}",
"recipients": "{{ .RECIPIENTS }}"
}
Query
http://sec-signal-api:8880/v1/receive/?@number={{.NUMBER}}
Path
http://sec-signal-api:8880/v1/receive/{{.NUMBER}}
KeyValue Pair Injection
In some cases you may not be able to access / modify the Request Body, in that case specify needed values in the Request Query:
http://sec-signal-api:8880/?@key=value
In order to differentiate Injection Queries and regular Queries
you have to add @
in front of any KeyValue Pair assignment.
Supported types include strings, ints and arrays. See Formatting.
Configuration
There are multiple ways to configure Secured Signal API, you can optionally use config.yml
aswell as Environment Variables to override the config.
Config Files
Config files allow YML formatting and also ${ENV}
to get Environment Variables.
To change the internal config file location set CONFIG_PATH
in your Environment to an absolute path including the filename.extension. (default: /config/config.yml
)
This example config shows all of the individual settings that can be applied:
# Example Config (all configurations shown)
api:
port: 8880
url: http://signal-api:8080
tokens: [token1, token2]
logLevel: INFO
variables:
number: "000"
recipients: ["001", "group.id", "user.id"]
messageAliases: [{ alias: "msg", score: 100 }]
blockedEndpoints:
- /v1/about
allowedEndpoints:
- /v2/send
Token Configs
You can also override the config.yml
file for each individual token by adding configs under TOKENS_PATH
(default: config/tokens/
)
This way you can permission tokens by further restricting or adding Endpoints, Placeholders, etc.
Here is an example:
token: LOOOONG_STRING
overrides:
variables: # Disable Placeholder
blockedEndpoints: # Disable Sending
- /v2/send
messageAliases: # Disable Aliases
Environment
Suppose you want to set a new Placeholder NUMBER
in your Environment...
environment:
VARIABLES__NUMBER: "000"
This would internally be converted into variables.number
matching the config formatting.
[!IMPORTANT]
Underscores _
are removed during Conversion, Double Underscores __
on the other hand convert the Variable into a nested Object (__
replaced by .
)
String To Type
[!TIP]
This formatting applies to almost every situation where the only (allowed) Input Type is a string and other Output Types are needed.
If you are using Environment Variables as an example you won't be able to specify an Array or a Dictionary of items, in that case you can provide a specifically formatted string which will be translated into the correct type...
type |
example |
string |
abc |
string |
+123 |
int |
123 |
int |
-123 |
json |
{"a":"b","c":"d"} |
array(int) |
[1,2,3] |
array(str) |
[a,b,c] |
[!NOTE]
If you have a string that should not be turned into any other type, then you will need to escape all Type Denotations, []
or {}
(also -
) with a \
Backslash.
Double Backslashes do exist but you could just leave them out completly.
An Odd number of Backslashes escape the character in front of them and an Even number leave the character as-is.
API Token(s)
During Authentication Secured Signal API will try to match the given Token against the list of Tokens inside of these Variables.
api:
tokens: [token1, token2, token3]
[!IMPORTANT]
It is highly recommended use API Tokens
What if I just don't?
Secured Signal API will still work, but important Security Features won't be available
like Blocked Endpoints and any sort of Auth.
[!NOTE]
Blocked Endpoints can be reactivated by manually configuring them
Endpoints
Because Secured Signal API is just a Proxy you can use all of the Signal REST API endpoints except for...
Endpoint |
/v1/about |
/v1/configuration |
/v1/devives |
/v1/register |
/v1/unregister |
/v1/qrcodelink |
/v1/accounts |
/v1/contacts |
[!NOTE]
Matching works by checking if the requested Endpoints startswith a Blocked or Allowed Endpoint
These Endpoints are blocked by default due to Security Risks, but can be modified by setting blockedEndpoints
in your config:
blockedEndpoints: [/v1/register, /v1/unregister, /v1/qrcodelink, /v1/contacts]
Override Blocked Endpoints by explicitly allowing endpoints in allowedEndpoints
.
Config (Allow) |
(Block) |
Result |
|
|
|
allowedEndpoints: ["/v2/send"] |
unset |
all |
🛑 |
/v2/send |
✅ |
unset |
blockedEndpoints: ["/v1/receive"] |
all |
✅ |
/v1/receive |
🛑 |
blockedEndpoints: ["/v2"] |
allowedEndpoints: ["/v2/send"] |
/v2* |
🛑 |
/v2/send |
✅ |
allowedEndpoints: [/v2/send]
Variables
Placeholders can be added under variables
and can then be referenced in the Body, Query or URL.
See Placeholders.
[!NOTE]
Every Placeholder Key will be converted into an Uppercase String.
Example: number
becomes NUMBER
in {{.NUMBER}}
variables:
number: "001",
recipients: [
"user.id", "000", "001", "group.id"
]
Message Aliases
To improve compatibility with other services Secured Signal API provides aliases for the message
attribute by default:
Alias |
Score |
msg |
100 |
content |
99 |
description |
98 |
text |
20 |
body |
15 |
summary |
10 |
details |
9 |
payload |
2 |
data |
1 |
Secured Signal API will pick the best scoring Message Alias (if available) to extract the correct message from the Request Body.
Message Aliases can be added by setting messageAliases
in your config:
messageAliases:
[
{ alias: "msg", score: 80 },
{ alias: "data.message", score: 79 },
{ alias: "array[0].message", score: 78 },
]
Port
To change the Port which Secured Signal API uses, you need to set server.port
in your config. (default: 8880
)
Log Level
To change the Log Level set logLevel
to: (default: info
)
Level |
info |
debug |
warn |
error |
fatal |
dev |
Contributing
Found a bug? Want to change or add something?
Feel free to open up an issue or create a Pull Request!
Support
Has this Repo been helpful 👍️ to you? Then consider ⭐️'ing this Project.
:)
License
MIT
Legal
Logo designed by @CodeShellDev, All Rights Reserved.
This Project is not affiliated with the Signal Foundation.