Skip to content

Commit d2f8aa9

Browse files
committed
fix(config): Validate OIDC configuration for login and callback path
1 parent 52c39b4 commit d2f8aa9

File tree

2 files changed

+157
-2
lines changed

2 files changed

+157
-2
lines changed

pkg/config/validation.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"errors"
55
"fmt"
66
"net/http"
7+
"net/url"
8+
"path"
79
"strings"
810

911
"github.com/thoas/go-funk"
@@ -83,6 +85,37 @@ func validateBusinessConfig(out *Config) error {
8385
}
8486
}
8587

88+
// Validate authentication providers
89+
if out.AuthProviders != nil && out.AuthProviders.OIDC != nil {
90+
for prov, authProviderCfg := range out.AuthProviders.OIDC {
91+
// Build redirect url
92+
u, err := url.Parse(authProviderCfg.RedirectURL)
93+
// Check if error exists
94+
if err != nil {
95+
return err
96+
}
97+
// Continue to build redirect url
98+
u.Path = path.Join(u.Path, authProviderCfg.CallbackPath)
99+
100+
// Now, full callback path is generated
101+
102+
// Check if new path is "/"
103+
if u.Path == "/" {
104+
return fmt.Errorf("provider %s can't have a callback path equal to / (to avoid redirect loop)", prov)
105+
}
106+
107+
// Check login path
108+
if authProviderCfg.LoginPath == "/" {
109+
return fmt.Errorf("provider %s can't have a login path equal to / (to avoid redirect loop)", prov)
110+
}
111+
112+
// Check that they are different
113+
if authProviderCfg.LoginPath == u.Path {
114+
return fmt.Errorf("provider %s can't have same login and callback path (to avoid redirect loop)", prov)
115+
}
116+
}
117+
}
118+
86119
return nil
87120
}
88121

pkg/config/validation_test.go

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// +build unit
2-
31
package config
42

53
import (
@@ -522,6 +520,130 @@ func Test_validateBusinessConfig(t *testing.T) {
522520
wantErr: true,
523521
errorString: "path 0 in list targets must ends with /",
524522
},
523+
{
524+
name: "OIDC provider with wrong callback path",
525+
args: args{
526+
out: &Config{
527+
AuthProviders: &AuthProviderConfig{
528+
OIDC: map[string]*OIDCAuthConfig{
529+
"provider1": {
530+
CallbackPath: "/",
531+
},
532+
},
533+
},
534+
Targets: []*TargetConfig{
535+
{
536+
Name: "test1",
537+
Bucket: &BucketConfig{
538+
Name: "bucket1",
539+
Region: "region1",
540+
},
541+
Mount: &MountConfig{
542+
Path: []string{"/mount1/"},
543+
},
544+
Resources: nil,
545+
Actions: &ActionsConfig{
546+
GET: &GetActionConfig{Enabled: true},
547+
PUT: &PutActionConfig{Enabled: false},
548+
DELETE: &DeleteActionConfig{Enabled: false},
549+
},
550+
},
551+
},
552+
ListTargets: &ListTargetsConfig{
553+
Enabled: true,
554+
Mount: &MountConfig{
555+
Path: []string{"/"},
556+
},
557+
Resource: nil,
558+
},
559+
},
560+
},
561+
wantErr: true,
562+
errorString: "provider provider1 can't have a callback path equal to / (to avoid redirect loop)",
563+
},
564+
{
565+
name: "OIDC provider with wrong login path",
566+
args: args{
567+
out: &Config{
568+
AuthProviders: &AuthProviderConfig{
569+
OIDC: map[string]*OIDCAuthConfig{
570+
"provider1": {
571+
LoginPath: "/",
572+
},
573+
},
574+
},
575+
Targets: []*TargetConfig{
576+
{
577+
Name: "test1",
578+
Bucket: &BucketConfig{
579+
Name: "bucket1",
580+
Region: "region1",
581+
},
582+
Mount: &MountConfig{
583+
Path: []string{"/mount1/"},
584+
},
585+
Resources: nil,
586+
Actions: &ActionsConfig{
587+
GET: &GetActionConfig{Enabled: true},
588+
PUT: &PutActionConfig{Enabled: false},
589+
DELETE: &DeleteActionConfig{Enabled: false},
590+
},
591+
},
592+
},
593+
ListTargets: &ListTargetsConfig{
594+
Enabled: true,
595+
Mount: &MountConfig{
596+
Path: []string{"/"},
597+
},
598+
Resource: nil,
599+
},
600+
},
601+
},
602+
wantErr: true,
603+
errorString: "provider provider1 can't have a login path equal to / (to avoid redirect loop)",
604+
},
605+
{
606+
name: "OIDC provider with same login and callback path",
607+
args: args{
608+
out: &Config{
609+
AuthProviders: &AuthProviderConfig{
610+
OIDC: map[string]*OIDCAuthConfig{
611+
"provider1": {
612+
LoginPath: "/fake",
613+
CallbackPath: "/fake",
614+
},
615+
},
616+
},
617+
Targets: []*TargetConfig{
618+
{
619+
Name: "test1",
620+
Bucket: &BucketConfig{
621+
Name: "bucket1",
622+
Region: "region1",
623+
},
624+
Mount: &MountConfig{
625+
Path: []string{"/mount1/"},
626+
},
627+
Resources: nil,
628+
Actions: &ActionsConfig{
629+
GET: &GetActionConfig{Enabled: true},
630+
PUT: &PutActionConfig{Enabled: false},
631+
DELETE: &DeleteActionConfig{Enabled: false},
632+
},
633+
},
634+
},
635+
ListTargets: &ListTargetsConfig{
636+
Enabled: true,
637+
Mount: &MountConfig{
638+
Path: []string{"/"},
639+
},
640+
Resource: nil,
641+
},
642+
},
643+
},
644+
wantErr: true,
645+
errorString: "provider provider1 can't have same login and callback path (to avoid redirect loop)",
646+
},
525647
{
526648
name: "Configuration with list target and target is valid",
527649
args: args{

0 commit comments

Comments
 (0)