Skip to content

Commit 56976f6

Browse files
authored
Authenticator improvements (#32)
RSA and EC support added. Clock skew tolerance support added.
1 parent 5d0424a commit 56976f6

File tree

5 files changed

+431
-95
lines changed

5 files changed

+431
-95
lines changed

main.go

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,24 @@ import (
99
"net/http/httputil"
1010
"net/url"
1111
"os"
12+
"strconv"
1213

1314
"github.com/kaancfidan/bouncer/services"
1415
)
1516

1617
const version = "0.0.0-VERSION" // to be replaced in CI
1718

1819
type flags struct {
19-
hmacKey string
20+
signingKey string
21+
signingMethod string
2022
configPath string
2123
upstreamURL string
2224
listenAddress string
2325
validIssuer string
2426
validAudience string
2527
expRequired string
2628
nbfRequired string
29+
clockSkew string
2730
}
2831

2932
func main() {
@@ -37,7 +40,7 @@ func main() {
3740

3841
server, err := newServer(f, configReader)
3942
if err != nil {
40-
log.Fatalf("server could not be created: %v", err)
43+
log.Fatalf("could not create server: %v", err)
4144
}
4245

4346
http.HandleFunc("/", server.Handle)
@@ -77,16 +80,34 @@ func newServer(f *flags, configReader io.Reader) (*services.Server, error) {
7780
return nil, fmt.Errorf("invalid config: %w", err)
7881
}
7982

83+
var clockSkew int
84+
if f.clockSkew != "" {
85+
clockSkew, err = strconv.Atoi(f.clockSkew)
86+
if err != nil {
87+
return nil, fmt.Errorf("clock skew flag %s cannot be converted to integer", f.clockSkew)
88+
}
89+
} else {
90+
clockSkew = 0
91+
}
92+
93+
authenticator, err := services.NewAuthenticator(
94+
[]byte(f.signingKey),
95+
f.signingMethod,
96+
f.validIssuer,
97+
f.validAudience,
98+
f.expRequired != "false",
99+
f.nbfRequired != "false",
100+
clockSkew)
101+
102+
if err != nil {
103+
return nil, fmt.Errorf("could not create authenticator: %w", err)
104+
}
105+
80106
s := services.NewServer(
81107
upstream,
82108
services.NewRouteMatcher(cfg.RoutePolicies),
83109
services.NewAuthorizer(cfg.ClaimPolicies),
84-
services.NewAuthenticator(
85-
[]byte(f.hmacKey),
86-
f.validIssuer,
87-
f.validAudience,
88-
f.expRequired != "false",
89-
f.nbfRequired != "false"))
110+
authenticator)
90111

91112
return s, nil
92113
}
@@ -99,9 +120,13 @@ func parseFlags() *flags {
99120
nbfRequired: "true",
100121
}
101122

102-
flag.StringVar(&f.hmacKey, "k",
123+
flag.StringVar(&f.signingKey, "k",
103124
lookupEnv("BOUNCER_SIGNING_KEY", ""),
104-
"symmetric signing key to validate tokens")
125+
"cryptographic signing key")
126+
127+
flag.StringVar(&f.signingMethod, "m",
128+
lookupEnv("BOUNCER_SIGNING_METHOD", ""),
129+
"signing method, accepted values = [HMAC, RSA, EC]")
105130

106131
flag.StringVar(&f.configPath, "p",
107132
lookupEnv("BOUNCER_CONFIG_PATH", f.configPath),
@@ -131,6 +156,10 @@ func parseFlags() *flags {
131156
lookupEnv("BOUNCER_REQUIRE_NOT_BEFORE", f.nbfRequired),
132157
fmt.Sprintf("require token not before timestamp claims, default = %s", f.nbfRequired))
133158

159+
flag.StringVar(&f.clockSkew, "clk",
160+
lookupEnv("BOUNCER_CLOCK_SKEW", f.clockSkew),
161+
fmt.Sprintf("require token not before timestamp claims, default = %s", f.nbfRequired))
162+
134163
flag.Parse()
135164

136165
return &f

main_test.go

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,65 +15,105 @@ func TestNewServer(t *testing.T) {
1515
{
1616
name: "happy path",
1717
flags: &flags{
18-
hmacKey: "SuperSecretKey123!",
19-
upstreamURL: "http://localhost:8080",
18+
signingKey: "SuperSecretKey123!",
19+
signingMethod: "HMAC",
2020
},
2121
cfgContent: "claimPolicies: {}\nroutePolicies: []",
2222
wantErr: false,
2323
},
2424
{
2525
name: "no config",
2626
flags: &flags{
27-
hmacKey: "SuperSecretKey123!",
28-
upstreamURL: "http://localhost:8080",
27+
signingKey: "SuperSecretKey123!",
28+
signingMethod: "HMAC",
2929
},
3030
cfgContent: "",
3131
wantErr: true,
3232
},
3333
{
34-
name: "auth server without proxy",
34+
name: "reverse proxy",
3535
flags: &flags{
36-
hmacKey: "SuperSecretKey123!",
36+
signingKey: "SuperSecretKey123!",
37+
signingMethod: "HMAC",
38+
upstreamURL: "http://localhost:8080",
39+
},
40+
cfgContent: "claimPolicies: {}\nroutePolicies: []",
41+
wantErr: false,
42+
},
43+
{
44+
name: "clock skewed",
45+
flags: &flags{
46+
signingKey: "SuperSecretKey123!",
47+
signingMethod: "HMAC",
48+
clockSkew: "10",
3749
},
3850
cfgContent: "claimPolicies: {}\nroutePolicies: []",
3951
wantErr: false,
4052
},
4153
{
4254
name: "invalid url scheme",
4355
flags: &flags{
44-
hmacKey: "SuperSecretKey123!",
45-
upstreamURL: "tcp://localhost:8080",
56+
signingKey: "SuperSecretKey123!",
57+
signingMethod: "HMAC",
58+
upstreamURL: "tcp://localhost:8080",
4659
},
4760
cfgContent: "claimPolicies: {}\nroutePolicies: []",
4861
wantErr: true,
4962
},
5063
{
5164
name: "malformed url",
5265
flags: &flags{
53-
hmacKey: "SuperSecretKey123!",
54-
upstreamURL: "!!http://localhost:8080",
66+
signingKey: "SuperSecretKey123!",
67+
signingMethod: "HMAC",
68+
upstreamURL: "!!http://localhost:8080",
5569
},
5670
cfgContent: "claimPolicies: {}\nroutePolicies: []",
5771
wantErr: true,
5872
},
5973
{
6074
name: "invalid config yaml",
6175
flags: &flags{
62-
hmacKey: "SuperSecretKey123!",
63-
upstreamURL: "http://localhost:8080",
76+
signingKey: "SuperSecretKey123!",
77+
signingMethod: "HMAC",
6478
},
6579
cfgContent: ": invalid",
6680
wantErr: true,
6781
},
6882
{
6983
name: "invalid config content",
7084
flags: &flags{
71-
hmacKey: "SuperSecretKey123!",
72-
upstreamURL: "http://localhost:8080",
85+
signingKey: "SuperSecretKey123!",
86+
signingMethod: "HMAC",
7387
},
7488
cfgContent: "claimPolicies:\n PolicyWithoutClaim:\n - value: test\nroutePolicies: []",
7589
wantErr: true,
7690
},
91+
{
92+
name: "no signing key",
93+
flags: &flags{
94+
signingMethod: "HMAC",
95+
},
96+
cfgContent: "claimPolicies: {}\nroutePolicies: []",
97+
wantErr: true,
98+
},
99+
{
100+
name: "no signing method",
101+
flags: &flags{
102+
signingKey: "SuperSecretKey123!",
103+
},
104+
cfgContent: "claimPolicies: {}\nroutePolicies: []",
105+
wantErr: true,
106+
},
107+
{
108+
name: "invalid clock skew flag",
109+
flags: &flags{
110+
signingKey: "SuperSecretKey123!",
111+
signingMethod: "HMAC",
112+
clockSkew: "not a number",
113+
},
114+
cfgContent: "claimPolicies: {}\nroutePolicies: []",
115+
wantErr: true,
116+
},
77117
}
78118
for _, tt := range tests {
79119
t.Run(tt.name, func(t *testing.T) {

0 commit comments

Comments
 (0)