Skip to content

Commit 8bbcf9a

Browse files
authored
Merge pull request #13 from CodeShellDev/dev
Update Main
2 parents f57a5c2 + d439a1c commit 8bbcf9a

File tree

12 files changed

+629
-354
lines changed

12 files changed

+629
-354
lines changed

.github/templates/README.template.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,31 @@ environment:
171171
DEFAULT_RECIPIENTS: ' [ "user.id", "000", "001", "group.id" ] '
172172
```
173173

174+
#### Message Aliases
175+
176+
To improve compatibility with other services Secured Signal API provides aliases for the `message` attribute by default:
177+
178+
| Alias | Priority |
179+
| ----------- | ----------- |
180+
| msg | 100 |
181+
| content | 99 |
182+
| description | 98 |
183+
| text | 20 |
184+
| body | 15 |
185+
| summary | 10 |
186+
| details | 9 |
187+
| payload | 2 |
188+
| data | 1 |
189+
190+
Secured Signal API will use the highest priority Message Alias to get the correct message from the Request Body.
191+
192+
If you are missing a Message Alias to have Secured Signal API integrated with a Service you can simply set `MESSAGE_ALIASES` in ENV:
193+
194+
```yaml
195+
environment:
196+
MESSAGE_ALIASES: ' [{ "alias": "note", "priority": 4 }, { "alias": "test", "priority": 3 }] '
197+
```
198+
174199
## Contributing
175200

176201
Found a bug? Want to change or add something?

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,31 @@ environment:
232232
DEFAULT_RECIPIENTS: ' [ "user.id", "000", "001", "group.id" ] '
233233
```
234234
235+
#### Message Aliases
236+
237+
To improve compatibility with other services Secured Signal API provides aliases for the `message` attribute by default:
238+
239+
| Alias | Priority |
240+
| ----------- | ----------- |
241+
| msg | 100 |
242+
| content | 99 |
243+
| description | 98 |
244+
| text | 20 |
245+
| body | 15 |
246+
| summary | 10 |
247+
| details | 9 |
248+
| payload | 2 |
249+
| data | 1 |
250+
251+
Secured Signal API will use the highest priority Message Alias to get the correct message from the Request Body.
252+
253+
If you are missing a Message Alias to have Secured Signal API integrated with a Service you can simply set `MESSAGE_ALIASES` in ENV:
254+
255+
```yaml
256+
environment:
257+
MESSAGE_ALIASES: ' [{ "alias": "note", "priority": 4 }, { "alias": "test", "priority": 3 }] '
258+
```
259+
235260
## Contributing
236261

237262
Found a bug? Want to change or add something?

internals/proxy/middlewares/auth.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package middlewares
2+
3+
import (
4+
"encoding/base64"
5+
"net/http"
6+
"net/url"
7+
"strings"
8+
9+
log "github.com/codeshelldev/secured-signal-api/utils/logger"
10+
)
11+
12+
type AuthMiddleware struct {
13+
Next http.Handler
14+
Token string
15+
}
16+
17+
type authType string
18+
19+
const (
20+
Bearer authType = "Bearer"
21+
Basic authType = "Basic"
22+
Query authType = "Query"
23+
None authType = "None"
24+
)
25+
26+
func getAuthType(str string) authType {
27+
switch str {
28+
case "Bearer":
29+
return Bearer
30+
case "Basic":
31+
return Basic
32+
default:
33+
return None
34+
}
35+
}
36+
37+
func (data AuthMiddleware) Use() http.Handler {
38+
next := data.Next
39+
token := data.Token
40+
41+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
42+
if token == "" {
43+
next.ServeHTTP(w, req)
44+
return
45+
}
46+
47+
authHeader := req.Header.Get("Authorization")
48+
49+
authQuery := req.URL.Query().Get("@authorization")
50+
51+
var authType authType = None
52+
53+
success := false
54+
55+
if authHeader != "" {
56+
authBody := strings.Split(authHeader, " ")
57+
58+
authType = getAuthType(authBody[0])
59+
authToken := authBody[1]
60+
61+
switch authType {
62+
case Bearer:
63+
if authToken == token {
64+
success = true
65+
}
66+
67+
case Basic:
68+
basicAuthBody, err := base64.StdEncoding.DecodeString(authToken)
69+
70+
if err != nil {
71+
log.Error("Could not decode Basic Auth Payload: ", err.Error())
72+
}
73+
74+
basicAuth := string(basicAuthBody)
75+
basicAuthParams := strings.Split(basicAuth, ":")
76+
77+
user := "api"
78+
79+
if basicAuthParams[0] == user && basicAuthParams[1] == token {
80+
success = true
81+
}
82+
}
83+
84+
} else if authQuery != "" {
85+
authType = Query
86+
87+
authToken, _ := url.QueryUnescape(authQuery)
88+
89+
if authToken == token {
90+
success = true
91+
92+
modifiedQuery := req.URL.Query()
93+
94+
modifiedQuery.Del("@authorization")
95+
96+
req.URL.RawQuery = modifiedQuery.Encode()
97+
}
98+
}
99+
100+
if !success {
101+
w.Header().Set("WWW-Authenticate", "Basic realm=\"Login Required\", Bearer realm=\"Access Token Required\"")
102+
103+
log.Warn("User failed ", string(authType), " Auth")
104+
http.Error(w, "Unauthorized", http.StatusUnauthorized)
105+
return
106+
}
107+
108+
next.ServeHTTP(w, req)
109+
})
110+
}

internals/proxy/middlewares/body.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package middlewares
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"io"
7+
"net/http"
8+
"strconv"
9+
10+
log "github.com/codeshelldev/secured-signal-api/utils/logger"
11+
)
12+
13+
type MessageAlias struct {
14+
Alias string
15+
Priority int
16+
}
17+
18+
type BodyMiddleware struct {
19+
Next http.Handler
20+
MessageAliases []MessageAlias
21+
}
22+
23+
func (data BodyMiddleware) Use() http.Handler {
24+
next := data.Next
25+
messageAliases := data.MessageAliases
26+
27+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
28+
bodyBytes, err := io.ReadAll(req.Body)
29+
if err != nil {
30+
log.Error("Could not read Body: ", err.Error())
31+
http.Error(w, "Bad Request", http.StatusBadRequest)
32+
return
33+
}
34+
defer req.Body.Close()
35+
36+
if len(bodyBytes) > 0 {
37+
38+
req.Body.Close()
39+
40+
var modifiedBodyData map[string]interface{}
41+
42+
err = json.Unmarshal(bodyBytes, &modifiedBodyData)
43+
44+
if err != nil {
45+
log.Error("Could not decode Body: ", err.Error())
46+
http.Error(w, "Internal Error", http.StatusInternalServerError)
47+
return
48+
}
49+
50+
content, ok := modifiedBodyData["message"]
51+
52+
if !ok || content == "" {
53+
best := 0
54+
55+
for _, alias := range messageAliases {
56+
aliasKey := alias.Alias
57+
priority := alias.Priority
58+
59+
value, ok := modifiedBodyData[aliasKey]
60+
61+
if ok && value != "" && priority > best {
62+
content = modifiedBodyData[aliasKey]
63+
}
64+
65+
modifiedBodyData[aliasKey] = nil
66+
}
67+
68+
modifiedBodyData["message"] = content
69+
70+
bodyBytes, err = json.Marshal(modifiedBodyData)
71+
72+
if err != nil {
73+
log.Error("Could not encode Body: ", err.Error())
74+
http.Error(w, "Internal Error", http.StatusInternalServerError)
75+
return
76+
}
77+
78+
modifiedBody := string(bodyBytes)
79+
80+
req.ContentLength = int64(len(modifiedBody))
81+
req.Header.Set("Content-Length", strconv.Itoa(len(modifiedBody)))
82+
}
83+
}
84+
85+
req.Body = io.NopCloser(bytes.NewReader(bodyBytes))
86+
87+
next.ServeHTTP(w, req)
88+
})
89+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package middlewares
2+
3+
import (
4+
"net/http"
5+
"slices"
6+
7+
log "github.com/codeshelldev/secured-signal-api/utils/logger"
8+
)
9+
10+
type EndpointsMiddleware struct {
11+
Next http.Handler
12+
BlockedEndpoints []string
13+
}
14+
15+
func (data EndpointsMiddleware) Use() http.Handler {
16+
next := data.Next
17+
BLOCKED_ENDPOINTS := data.BlockedEndpoints
18+
19+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
20+
reqPath := req.URL.Path
21+
22+
if slices.Contains(BLOCKED_ENDPOINTS, reqPath) {
23+
log.Warn("User tried to access blocked endpoint: ", reqPath)
24+
http.Error(w, "Unauthorized", http.StatusUnauthorized)
25+
return
26+
}
27+
28+
next.ServeHTTP(w, req)
29+
})
30+
}

internals/proxy/middlewares/log.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package middlewares
2+
3+
import (
4+
"net/http"
5+
6+
log "github.com/codeshelldev/secured-signal-api/utils/logger"
7+
)
8+
9+
type LogMiddleware struct {
10+
Next http.Handler
11+
}
12+
13+
func (data LogMiddleware) Use() http.Handler {
14+
next := data.Next
15+
16+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
17+
log.Info(req.Method, " ", req.URL.Path, " ", req.URL.RawQuery)
18+
19+
next.ServeHTTP(w, req)
20+
})
21+
}

0 commit comments

Comments
 (0)