Skip to content

Commit

Permalink
OIDC: validate the client_secret field
Browse files Browse the repository at this point in the history
- Make the client_secret required, as OIDC auth won't work without it
- Raise a clear error if unsupported file:// URLs are used

Closes #39107
  • Loading branch information
zmb3 committed Oct 16, 2024
1 parent d602f89 commit 712051d
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 2 deletions.
10 changes: 9 additions & 1 deletion api/types/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"net/netip"
"net/url"
"slices"
"strings"
"time"

"github.com/gravitational/trace"
Expand Down Expand Up @@ -403,7 +404,14 @@ func (o *OIDCConnectorV3) CheckAndSetDefaults() error {
}

if o.Spec.ClientID == "" {
return trace.BadParameter("ClientID: missing client id")
return trace.BadParameter("OIDC connector is missing required client_id")
}

if o.Spec.ClientSecret == "" {
return trace.BadParameter("OIDC connector is missing required client_secret")
}
if strings.HasPrefix(o.Spec.ClientSecret, "file://") {
return trace.BadParameter("the client_secret must be a literal value, file:// URLs are not supported")
}

if len(o.GetClaimsToRoles()) == 0 {
Expand Down
18 changes: 18 additions & 0 deletions api/types/oidc_external_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package types
import (
"testing"

"github.com/gravitational/trace"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -55,3 +56,20 @@ func TestOIDCClaimsRoundTrip(t *testing.T) {
})
}
}

func TestClientSecretFileURI(t *testing.T) {
_, err := NewOIDCConnector("test-connector", OIDCConnectorSpecV3{
ClientID: "some-client-id",
ClientSecret: "file://is-not-allowed",
ClaimsToRoles: []ClaimMapping{
{
Claim: "team",
Value: "dev",
Roles: []string{"dev-team-access"},
},
},
})
require.Error(t, err)
require.True(t, trace.IsBadParameter(err))
require.ErrorContains(t, err, "file:// URLs are not supported")
}
3 changes: 2 additions & 1 deletion lib/auth/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1343,7 +1343,8 @@ func TestOIDCConnectorCRUDEventsEmitted(t *testing.T) {

ctx := context.Background()
oidc, err := types.NewOIDCConnector("test", types.OIDCConnectorSpecV3{
ClientID: "a",
ClientID: "a",
ClientSecret: "b",
ClaimsToRoles: []types.ClaimMapping{
{
Claim: "dummy",
Expand Down
6 changes: 6 additions & 0 deletions lib/services/oidc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ func TestOIDCUnmarshal(t *testing.T) {
},
"spec": {
"client_id": "id-from-google.apps.googleusercontent.com",
"client_secret": "secret-key-from-google",
"claims_to_roles": [
{
"claim": "roles",
Expand All @@ -125,6 +126,7 @@ func TestOIDCUnmarshal(t *testing.T) {
}`,
expectSpec: types.OIDCConnectorSpecV3{
ClientID: "id-from-google.apps.googleusercontent.com",
ClientSecret: "secret-key-from-google",
ClaimsToRoles: []types.ClaimMapping{{Claim: "roles", Value: "teleport-user", Roles: []string{"dictator"}}},
RedirectURLs: []string{
"https://localhost:3080/v1/webapi/oidc/callback",
Expand Down Expand Up @@ -159,6 +161,7 @@ func TestOIDCCheckAndSetDefaults(t *testing.T) {
desc: "basic spec and defaults",
spec: types.OIDCConnectorSpecV3{
ClientID: "id-from-google.apps.googleusercontent.com",
ClientSecret: "some-client-secret",
ClaimsToRoles: []types.ClaimMapping{{Claim: "roles", Value: "teleport-user", Roles: []string{"dictator"}}},
RedirectURLs: []string{"https://localhost:3080/v1/webapi/oidc/callback"},
},
Expand All @@ -175,6 +178,7 @@ func TestOIDCCheckAndSetDefaults(t *testing.T) {
desc: "omit prompt",
spec: types.OIDCConnectorSpecV3{
ClientID: "id-from-google.apps.googleusercontent.com",
ClientSecret: "some-client-secret",
ClaimsToRoles: []types.ClaimMapping{{Claim: "roles", Value: "teleport-user", Roles: []string{"dictator"}}},
RedirectURLs: []string{
"https://localhost:3080/v1/webapi/oidc/callback",
Expand All @@ -191,6 +195,7 @@ func TestOIDCCheckAndSetDefaults(t *testing.T) {
desc: "invalid claims to roles",
spec: types.OIDCConnectorSpecV3{
ClientID: "id-from-google.apps.googleusercontent.com",
ClientSecret: "some-client-secret",
ClaimsToRoles: []types.ClaimMapping{{Claim: "roles", Value: "teleport-user"}},
RedirectURLs: []string{
"https://localhost:3080/v1/webapi/oidc/callback",
Expand All @@ -215,6 +220,7 @@ func TestOIDCCheckAndSetDefaults(t *testing.T) {
func TestOIDCGetRedirectURL(t *testing.T) {
conn, err := types.NewOIDCConnector("oidc", types.OIDCConnectorSpecV3{
ClientID: "id-from-google.apps.googleusercontent.com",
ClientSecret: "some-client-secret",
ClaimsToRoles: []types.ClaimMapping{{Claim: "roles", Value: "teleport-user", Roles: []string{"dictator"}}},
RedirectURLs: []string{
"https://proxy.example.com/v1/webapi/oidc/callback",
Expand Down
1 change: 1 addition & 0 deletions tool/tsh/common/tsh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3879,6 +3879,7 @@ func mockConnector(t *testing.T) types.OIDCConnector {
IssuerURL: "https://auth.example.com",
RedirectURLs: []string{"https://cluster.example.com"},
ClientID: "fake-client",
ClientSecret: "fake-secret",
ClaimsToRoles: []types.ClaimMapping{
{
Claim: "groups",
Expand Down

0 comments on commit 712051d

Please sign in to comment.