secured-signal-api

command module
v1.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 14, 2025 License: MIT Imports: 8 Imported by: 0

README

Secure Proxy for Signal REST API
Secure Proxy for Signal Messenger REST API

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

Logo designed by @CodeShellDev, All Rights Reserved. This Project is not affiliated with the Signal Foundation.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internals

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL