Skip to content

Commit f9abb7f

Browse files
committed
Follow up changes
- Create a list of authenticators for each issuer. Remove the requirement for providing a clientID. - This allows adding self signed authenticators to the same multi authenticators interface. Signed-off-by: Aditya Dani <[email protected]>
1 parent 1272fd5 commit f9abb7f

File tree

4 files changed

+146
-67
lines changed

4 files changed

+146
-67
lines changed

pkg/auth/auth.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ type Authenticator interface {
6262
type MultiAuthenticatorWithClientID interface {
6363
Authenticator
6464
GetAuthenticators(issuer string) []Authenticator
65-
ListIssuersWithClientID() []IssuerWithClientID
65+
ListIssuers() []string
6666
}
6767

6868
// Enabled returns whether auth is enabled.

pkg/auth/multiauthenticator.go

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,53 +5,41 @@ import (
55
"fmt"
66
)
77

8-
type IssuerWithClientID struct {
9-
// Issuer of the token. The issuer cannot be empty.
10-
Issuer string
11-
// ClientID of the token. The clientID cannot be empty.
12-
ClientID string
8+
type multiAuthenticatorImpl struct {
9+
authenticators map[string][]Authenticator
1310
}
1411

15-
type multiAuthenticatorWithClientIDImpl struct {
16-
authenticators map[IssuerWithClientID]Authenticator
17-
}
18-
19-
func NewMultiAuthenticatorWithClientID(
20-
authenticators map[IssuerWithClientID]Authenticator) (MultiAuthenticatorWithClientID, error) {
21-
authMap := make(map[IssuerWithClientID]Authenticator)
22-
for issuerWithClientID, authenticator := range authenticators {
23-
if issuerWithClientID.ClientID == "" {
24-
return nil, fmt.Errorf("clientID cannot be empty")
25-
}
26-
if issuerWithClientID.Issuer == "" {
27-
return nil, fmt.Errorf("issuer cannot be empty")
12+
// NewMultiAuthenticator maintains a list of authenticators for a given issuer.
13+
// The input argument is a map of issuers to a list of authenticators for that issuer.
14+
// NOTE: This interface does not check if there are duplicate authenticators.
15+
func NewMultiAuthenticator(
16+
authenticators map[string][]Authenticator,
17+
) (MultiAuthenticatorWithClientID, error) {
18+
authMap := make(map[string][]Authenticator)
19+
for issuer, authenticatorsList := range authenticators {
20+
if len(authenticatorsList) == 0 {
21+
return nil, fmt.Errorf("empty authenticators list for issuer %v", issuer)
2822
}
29-
authMap[issuerWithClientID] = authenticator
23+
authMap[issuer] = authenticatorsList
3024
}
31-
return &multiAuthenticatorWithClientIDImpl{
25+
return &multiAuthenticatorImpl{
3226
authenticators: authMap,
3327
}, nil
3428
}
3529

36-
func (m *multiAuthenticatorWithClientIDImpl) ListIssuersWithClientID() []IssuerWithClientID {
37-
var issuerWithClientIDs []IssuerWithClientID
38-
for issuerWithClientID, _ := range m.authenticators {
39-
issuerWithClientIDs = append(issuerWithClientIDs, issuerWithClientID)
40-
}
41-
return issuerWithClientIDs
30+
func (m *multiAuthenticatorImpl) GetAuthenticators(issuer string) []Authenticator {
31+
return m.authenticators[issuer]
4232
}
4333

44-
func (m *multiAuthenticatorWithClientIDImpl) GetAuthenticators(issuer string) []Authenticator {
45-
var authenticators []Authenticator
46-
for issuerWithClientID, authenticator := range m.authenticators {
47-
if issuerWithClientID.Issuer == issuer {
48-
authenticators = append(authenticators, authenticator)
49-
}
34+
func (m *multiAuthenticatorImpl) ListIssuers() []string {
35+
var issuers []string
36+
for issuer, _ := range m.authenticators {
37+
issuers = append(issuers, issuer)
5038
}
51-
return authenticators
39+
return issuers
5240
}
5341

54-
func (m *multiAuthenticatorWithClientIDImpl) AuthenticateToken(ctx context.Context, idToken string) (*Claims, error) {
42+
func (m *multiAuthenticatorImpl) AuthenticateToken(ctx context.Context, idToken string) (*Claims, error) {
5543
tokenClaims, err := TokenClaims(idToken)
5644
if err != nil {
5745
return nil, fmt.Errorf("failed to get claims from token: %w", err)
@@ -68,9 +56,9 @@ func (m *multiAuthenticatorWithClientIDImpl) AuthenticateToken(ctx context.Conte
6856
tokenClaims.Issuer, tokenClaims.Audience)
6957
}
7058

71-
func (m *multiAuthenticatorWithClientIDImpl) Username(claims *Claims) string {
59+
func (m *multiAuthenticatorImpl) Username(claims *Claims) string {
7260
var username string
73-
// TODO: This code does not handle the case where there are mulitple authenticators
61+
// TODO: This code does not handle the case where there are multiple authenticators
7462
// registered with the same issuer but different UsernameClaimTypes.
7563
for _, authenticator := range m.GetAuthenticators(claims.Issuer) {
7664
if username = authenticator.Username(claims); username != "" {

pkg/auth/multiauthenticator_test.go

Lines changed: 119 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,57 @@ import (
99
"github.com/stretchr/testify/assert"
1010
)
1111

12-
func TestNewMultiAuthenticatorWithClientID_EmptyClientID(t *testing.T) {
12+
func TestNewMultiAuthenticator_EmptyAuthenticators(t *testing.T) {
1313
// Given.
14-
jwtAuth, err := NewJwtAuthenticator(&JwtAuthConfig{
15-
SharedSecret: []byte("my-secret"),
16-
UsernameClaim: UsernameClaimTypeSubject,
14+
15+
m, err := NewMultiAuthenticator(map[string][]Authenticator{
16+
"issuer-1": []Authenticator{},
1717
})
18-
assert.NoError(t, err)
19-
m, err := NewMultiAuthenticatorWithClientID(map[IssuerWithClientID]Authenticator{IssuerWithClientID{"issuer-1", ""}: jwtAuth})
2018
assert.Error(t, err)
21-
assert.Nil(t, m)
19+
20+
// When.
21+
authenticators := m.GetAuthenticators("issuer-1")
22+
23+
// Then.
24+
assert.Equal(t, 0, len(authenticators))
2225
}
2326

24-
func TestNewMultiAuthenticatorWithClientID_EmptyIssuer(t *testing.T) {
27+
func TestNewMultiAuthenticator_ListIssuers(t *testing.T) {
2528
// Given.
2629
jwtAuth, err := NewJwtAuthenticator(&JwtAuthConfig{
2730
SharedSecret: []byte("my-secret"),
2831
UsernameClaim: UsernameClaimTypeSubject,
2932
})
3033
assert.NoError(t, err)
31-
m, err := NewMultiAuthenticatorWithClientID(map[IssuerWithClientID]Authenticator{IssuerWithClientID{"", "1"}: jwtAuth})
32-
assert.Error(t, err)
33-
assert.Nil(t, m)
34-
}
34+
m, err := NewMultiAuthenticator(map[string][]Authenticator{
35+
"issuer-1": []Authenticator{jwtAuth},
36+
// TODO: MultiAuthenticator does not check for duplicate authenticators across issuers.
37+
"issuer-2": []Authenticator{jwtAuth},
38+
})
39+
assert.NoError(t, err)
3540

36-
func TestMultiAuthenticatorWithClientID_GetAuthenticators_Ok(t *testing.T) {
41+
// When.
42+
issuers := m.ListIssuers()
43+
44+
// Then.
45+
assert.Equal(t, 2, len(issuers))
46+
}
47+
func TestMultiAuthenticator_GetAuthenticators_Ok(t *testing.T) {
3748
// Given.
38-
jwtAuth, err := NewJwtAuthenticator(&JwtAuthConfig{
39-
SharedSecret: []byte("my-secret"),
49+
jwtAuth1, err := NewJwtAuthenticator(&JwtAuthConfig{
50+
SharedSecret: []byte("my-secret1"),
4051
UsernameClaim: UsernameClaimTypeSubject,
4152
})
4253
assert.NoError(t, err)
43-
m, err := NewMultiAuthenticatorWithClientID(map[IssuerWithClientID]Authenticator{
44-
IssuerWithClientID{"issuer-1", "1"}: jwtAuth,
45-
IssuerWithClientID{"issuer-1", "2"}: jwtAuth,
54+
55+
jwtAuth2, err := NewJwtAuthenticator(&JwtAuthConfig{
56+
SharedSecret: []byte("my-secret2"),
57+
UsernameClaim: UsernameClaimTypeSubject,
58+
})
59+
assert.NoError(t, err)
60+
61+
m, err := NewMultiAuthenticator(map[string][]Authenticator{
62+
"issuer-1": []Authenticator{jwtAuth1, jwtAuth2},
4663
})
4764
assert.NoError(t, err)
4865

@@ -53,9 +70,9 @@ func TestMultiAuthenticatorWithClientID_GetAuthenticators_Ok(t *testing.T) {
5370
assert.Equal(t, 2, len(authenticators))
5471
}
5572

56-
func TestMultiAuthenticatorWithClientID_GetAuthenticator_FailNoIssuer(t *testing.T) {
73+
func TestMultiAuthenticator_GetAuthenticator_FailNoIssuer(t *testing.T) {
5774
// Given.
58-
m, err := NewMultiAuthenticatorWithClientID(map[IssuerWithClientID]Authenticator{})
75+
m, err := NewMultiAuthenticator(map[string][]Authenticator{})
5976
assert.NoError(t, err)
6077

6178
// When.
@@ -65,21 +82,26 @@ func TestMultiAuthenticatorWithClientID_GetAuthenticator_FailNoIssuer(t *testing
6582
assert.Empty(t, authenticators)
6683
}
6784

68-
func TestMultiAuthenticatorWithClientID_AuthenticateToken_Ok(t *testing.T) {
85+
func TestMultiAuthenticator_AuthenticateToken_Ok(t *testing.T) {
6986
// Given.
7087
jwtAuth1, err := NewJwtAuthenticator(&JwtAuthConfig{
7188
SharedSecret: []byte("my-secret-1"),
7289
UsernameClaim: UsernameClaimTypeSubject,
7390
})
7491
assert.NoError(t, err)
7592

76-
m, err := NewMultiAuthenticatorWithClientID(map[IssuerWithClientID]Authenticator{
77-
IssuerWithClientID{"issuer-1", "1"}: jwtAuth1,
78-
IssuerWithClientID{"issuer-1", "2"}: jwtAuth1,
93+
jwtAuth2, err := NewJwtAuthenticator(&JwtAuthConfig{
94+
SharedSecret: []byte("my-secret-2"),
95+
UsernameClaim: UsernameClaimTypeSubject,
7996
})
8097
assert.NoError(t, err)
8198

82-
rawToken, err := Token(&Claims{
99+
m, err := NewMultiAuthenticator(map[string][]Authenticator{
100+
"issuer-1": []Authenticator{jwtAuth1, jwtAuth2},
101+
})
102+
assert.NoError(t, err)
103+
104+
rawToken1, err := Token(&Claims{
83105
Audience: "1",
84106
Issuer: "issuer-1",
85107
@@ -88,20 +110,89 @@ func TestMultiAuthenticatorWithClientID_AuthenticateToken_Ok(t *testing.T) {
88110
Roles: []string{"tester"},
89111
}, &Signature{
90112
Type: jwt.SigningMethodHS256,
91-
Key: []byte("my-secret-1"),
113+
Key: []byte("my-secret-2"),
92114
}, &Options{
93115
Expiration: time.Now().Add(time.Minute * 10).Unix(),
94116
})
95117
assert.NoError(t, err)
96-
assert.NotEmpty(t, rawToken)
118+
assert.NotEmpty(t, rawToken1)
97119

98120
// When.
99-
authenticateClaims, err := m.AuthenticateToken(context.Background(), rawToken)
121+
authenticateClaims, err := m.AuthenticateToken(context.Background(), rawToken1)
100122

101123
// Then.
102124
assert.NoError(t, err)
103125
assert.Equal(t, "issuer-1", authenticateClaims.Issuer)
104126
assert.Equal(t, "[email protected]", authenticateClaims.Email)
105127
assert.Equal(t, "my-name", authenticateClaims.Name)
106128
assert.Equal(t, []string{"tester"}, authenticateClaims.Roles)
129+
130+
rawToken2, err := Token(&Claims{
131+
Audience: "1",
132+
Issuer: "issuer-1",
133+
134+
Name: "my-name",
135+
Subject: "my-sub",
136+
Roles: []string{"tester"},
137+
}, &Signature{
138+
Type: jwt.SigningMethodHS256,
139+
Key: []byte("my-secret-2"),
140+
}, &Options{
141+
Expiration: time.Now().Add(time.Minute * 10).Unix(),
142+
})
143+
assert.NoError(t, err)
144+
assert.NotEmpty(t, rawToken2)
145+
146+
// When.
147+
authenticateClaims, err = m.AuthenticateToken(context.Background(), rawToken2)
148+
149+
// Then.
150+
assert.NoError(t, err)
151+
assert.Equal(t, "issuer-1", authenticateClaims.Issuer)
152+
assert.Equal(t, "[email protected]", authenticateClaims.Email)
153+
assert.Equal(t, "my-name", authenticateClaims.Name)
154+
assert.Equal(t, []string{"tester"}, authenticateClaims.Roles)
155+
}
156+
157+
func TestMultiAuthenticator_AuthenticateToken_Fail(t *testing.T) {
158+
// Given.
159+
jwtAuth1, err := NewJwtAuthenticator(&JwtAuthConfig{
160+
SharedSecret: []byte("my-secret-1"),
161+
UsernameClaim: UsernameClaimTypeSubject,
162+
})
163+
assert.NoError(t, err)
164+
165+
jwtAuth2, err := NewJwtAuthenticator(&JwtAuthConfig{
166+
SharedSecret: []byte("my-secret-2"),
167+
UsernameClaim: UsernameClaimTypeSubject,
168+
})
169+
assert.NoError(t, err)
170+
171+
m, err := NewMultiAuthenticator(map[string][]Authenticator{
172+
"issuer-1": []Authenticator{jwtAuth1, jwtAuth2},
173+
})
174+
assert.NoError(t, err)
175+
176+
rawToken1, err := Token(&Claims{
177+
Audience: "1",
178+
Issuer: "issuer-1",
179+
180+
Name: "my-name",
181+
Subject: "my-sub",
182+
Roles: []string{"tester"},
183+
}, &Signature{
184+
Type: jwt.SigningMethodHS256,
185+
Key: []byte("my-secret-3"),
186+
}, &Options{
187+
Expiration: time.Now().Add(time.Minute * 10).Unix(),
188+
})
189+
assert.NoError(t, err)
190+
assert.NotEmpty(t, rawToken1)
191+
192+
// When.
193+
authenticateClaims, err := m.AuthenticateToken(context.Background(), rawToken1)
194+
195+
// Then.
196+
assert.Error(t, err)
197+
assert.Nil(t, authenticateClaims)
107198
}

server/grpc_framework_server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ func NewGrpcFrameworkServer(config *ServerConfig) (*GrpcFrameworkServer, error)
8181
return nil, fmt.Errorf("must supply role manager when authentication is enabled and default authZ is used")
8282
}
8383
if config.Security.Authenticators != nil {
84-
for _, issuerWithClientID := range config.Security.Authenticators.ListIssuersWithClientID() {
85-
log.Infof("Authentication enabled for issuer: %s with clientID %s", issuerWithClientID.Issuer, issuerWithClientID.ClientID)
84+
for _, issuer := range config.Security.Authenticators.ListIssuers() {
85+
log.Infof("Authentication enabled for issuer: %s ", issuer)
8686
}
8787
}
8888

0 commit comments

Comments
 (0)