Skip to content

Commit a1e70f9

Browse files
authored
feat(sdk): don't require client_id in the auth token (#544)
This isn't a claim that is in any spec, except for token exchange drafts Instead we should allow the roles specified in the token to dictate access to resources.
1 parent ae8d5f9 commit a1e70f9

File tree

6 files changed

+2
-123
lines changed

6 files changed

+2
-123
lines changed

docs/configuration.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ The server configuration is used to define how the application runs its server.
4141
| `tls.key` | The path to the tls key. | |
4242
| `auth.audience` | The audience for the IDP. | |
4343
| `auth.issuer` | The issuer for the IDP. | |
44-
| `auth.clients` | A list of client id's that are allowed. | |
4544

4645
Example:
4746

@@ -58,9 +57,6 @@ server:
5857
enabled: true
5958
audience: https://example.com
6059
issuer: https://example.com
61-
clients:
62-
- client_id
63-
- client_id2
6460
```
6561

6662
## Database Configuration

opentdf-example-no-kas.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ server:
1818
enabled: false
1919
audience: "http://localhost:8080"
2020
issuer: http://localhost:8888/auth/realms/tdf
21-
clients:
22-
- "opentdf"
2321
grpc:
2422
reflectionEnabled: true # Default is false
2523
hsm:

opentdf-example.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ server:
2525
enabled: true
2626
audience: "http://localhost:8080"
2727
issuer: http://localhost:8888/auth/realms/opentdf
28-
clients:
29-
- "opentdf"
30-
- "opentdf-sdk"
3128
policy:
3229
## Default policy for all requests
3330
default: #"role:readonly"

service/internal/auth/authn.go

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,6 @@ func (a Authentication) checkToken(ctx context.Context, authHeader []string, dpo
295295
jwt.WithValidate(true),
296296
jwt.WithIssuer(issuer),
297297
jwt.WithAudience(oidc.Audience),
298-
jwt.WithValidator(jwt.ValidatorFunc(a.claimsValidator)),
299298
)
300299

301300
if err != nil {
@@ -447,45 +446,3 @@ func validateDPoP(accessToken jwt.Token, acessTokenRaw string, dpopInfo dpopInfo
447446
}
448447
return &dpopKey, nil
449448
}
450-
451-
// claimsValidator is a custom validator to check extra claims in the token.
452-
// right now it only checks for client_id
453-
func (a Authentication) claimsValidator(_ context.Context, token jwt.Token) jwt.ValidationError {
454-
var (
455-
clientID string
456-
)
457-
458-
// Need to check for cid and client_id as this claim seems to be different between idp's
459-
cidClaim, cidExists := token.Get("cid")
460-
clientIDClaim, clientIDExists := token.Get("client_id")
461-
462-
// Check to see if we have a client id claim
463-
switch {
464-
case cidExists:
465-
if cid, ok := cidClaim.(string); ok {
466-
clientID = cid
467-
break
468-
}
469-
case clientIDExists:
470-
if cid, ok := clientIDClaim.(string); ok {
471-
clientID = cid
472-
break
473-
}
474-
default:
475-
return jwt.NewValidationError(fmt.Errorf("client id required"))
476-
}
477-
478-
// Check if the client id is allowed in list of clients
479-
foundClientID := false
480-
for _, c := range a.oidcConfigurations[token.Issuer()].Clients {
481-
if c == clientID {
482-
foundClientID = true
483-
break
484-
}
485-
}
486-
if !foundClientID {
487-
return jwt.NewValidationError(fmt.Errorf("invalid client id"))
488-
}
489-
490-
return nil
491-
}

service/internal/auth/authn_test.go

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ func (s *AuthSuite) SetupTest() {
142142
auth, err := NewAuthenticator(AuthNConfig{
143143
Issuer: s.server.URL,
144144
Audience: "test",
145-
Clients: []string{"client1", "client2", "client3"},
146145
}, nil)
147146

148147
s.Require().NoError(err)
@@ -254,69 +253,6 @@ func (s *AuthSuite) Test_CheckToken_When_Audience_Invalid_Expect_Error() {
254253
s.Equal("\"aud\" not satisfied", err.Error())
255254
}
256255

257-
func (s *AuthSuite) Test_CheckToken_When_ClientID_Missing_Expect_Error() {
258-
tok := jwt.New()
259-
s.Require().NoError(tok.Set(jwt.ExpirationKey, time.Now().Add(time.Hour)))
260-
s.Require().NoError(tok.Set("iss", s.server.URL))
261-
s.Require().NoError(tok.Set("aud", "test"))
262-
signedTok, err := jwt.Sign(tok, jwt.WithKey(jwa.RS256, s.key))
263-
264-
s.NotNil(signedTok)
265-
s.Require().NoError(err)
266-
267-
_, _, err = s.auth.checkToken(context.Background(), []string{fmt.Sprintf("Bearer %s", string(signedTok))}, dpopInfo{})
268-
s.Require().Error(err)
269-
s.Equal("client id required", err.Error())
270-
}
271-
272-
func (s *AuthSuite) Test_CheckToken_When_ClientID_Invalid_Expect_Error() {
273-
tok := jwt.New()
274-
s.Require().NoError(tok.Set(jwt.ExpirationKey, time.Now().Add(time.Hour)))
275-
s.Require().NoError(tok.Set("iss", s.server.URL))
276-
s.Require().NoError(tok.Set("aud", "test"))
277-
s.Require().NoError(tok.Set("client_id", "invalid"))
278-
signedTok, err := jwt.Sign(tok, jwt.WithKey(jwa.RS256, s.key))
279-
280-
s.NotNil(signedTok)
281-
s.Require().NoError(err)
282-
283-
_, _, err = s.auth.checkToken(context.Background(), []string{fmt.Sprintf("Bearer %s", string(signedTok))}, dpopInfo{})
284-
s.Require().Error(err)
285-
s.Equal("invalid client id", err.Error())
286-
}
287-
288-
func (s *AuthSuite) Test_CheckToken_When_CID_Invalid_Expect_Error() {
289-
tok := jwt.New()
290-
s.Require().NoError(tok.Set(jwt.ExpirationKey, time.Now().Add(time.Hour)))
291-
s.Require().NoError(tok.Set("iss", s.server.URL))
292-
s.Require().NoError(tok.Set("aud", "test"))
293-
s.Require().NoError(tok.Set("cid", "invalid"))
294-
signedTok, err := jwt.Sign(tok, jwt.WithKey(jwa.RS256, s.key))
295-
296-
s.NotNil(signedTok)
297-
s.Require().NoError(err)
298-
299-
_, _, err = s.auth.checkToken(context.Background(), []string{fmt.Sprintf("Bearer %s", string(signedTok))}, dpopInfo{})
300-
s.Require().Error(err)
301-
s.Equal("invalid client id", err.Error())
302-
}
303-
304-
func (s *AuthSuite) Test_CheckToken_When_CID_Invalid_INT_Expect_Error() {
305-
tok := jwt.New()
306-
s.Require().NoError(tok.Set(jwt.ExpirationKey, time.Now().Add(time.Hour)))
307-
s.Require().NoError(tok.Set("iss", s.server.URL))
308-
s.Require().NoError(tok.Set("aud", "test"))
309-
s.Require().NoError(tok.Set("cid", 1))
310-
signedTok, err := jwt.Sign(tok, jwt.WithKey(jwa.RS256, s.key))
311-
312-
s.NotNil(signedTok)
313-
s.Require().NoError(err)
314-
315-
_, _, err = s.auth.checkToken(context.Background(), []string{fmt.Sprintf("Bearer %s", string(signedTok))}, dpopInfo{})
316-
s.Require().Error(err)
317-
s.Equal("invalid client id", err.Error())
318-
}
319-
320256
func (s *AuthSuite) Test_CheckToken_When_Valid_No_DPoP_Expect_Error() {
321257
tok := jwt.New()
322258
s.Require().NoError(tok.Set(jwt.ExpirationKey, time.Now().Add(time.Hour)))

service/internal/auth/config.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ type Config struct {
1010

1111
// AuthNConfig is the configuration need for the platform to validate tokens
1212
type AuthNConfig struct {
13-
Issuer string `yaml:"issuer" json:"issuer"`
14-
Audience string `yaml:"audience" json:"audience"`
15-
Clients []string `yaml:"clients" json:"clients"`
13+
Issuer string `yaml:"issuer" json:"issuer"`
14+
Audience string `yaml:"audience" json:"audience"`
1615
OIDCConfiguration `yaml:"-" json:"-"`
1716
Policy PolicyConfig `yaml:"policy" json:"policy" mapstructure:"policy"`
1817
}
@@ -34,9 +33,5 @@ func (c AuthNConfig) validateAuthNConfig() error {
3433
return fmt.Errorf("config Auth.Audience is required")
3534
}
3635

37-
if len(c.Clients) == 0 {
38-
return fmt.Errorf("config Auth.Clients is required")
39-
}
40-
4136
return nil
4237
}

0 commit comments

Comments
 (0)