From a03cf171d07ffd93d85a938f335001e2e2de9844 Mon Sep 17 00:00:00 2001 From: Akshay Gaikwad Date: Tue, 25 Jan 2022 13:24:56 +0530 Subject: [PATCH] Valdiate URLs in create/update OIDC provider service --- .../_kratos/sync_providers_from_db.go | 24 ++++---- .../usermgmt/pkg/service/oidc_provider.go | 59 ++++++++++++++++--- 2 files changed, 63 insertions(+), 20 deletions(-) diff --git a/components/usermgmt/_kratos/sync_providers_from_db.go b/components/usermgmt/_kratos/sync_providers_from_db.go index db46676..e060c80 100644 --- a/components/usermgmt/_kratos/sync_providers_from_db.go +++ b/components/usermgmt/_kratos/sync_providers_from_db.go @@ -17,14 +17,14 @@ import ( type Provider struct { Id uuid.UUID `bun:"id,type:uuid"` Provider string `bun:"provider_name,notnull"` - MapperURL string `bun:"mapper_url"yaml:"mapper_url"` - ClientId string `bun:"client_id,notnull"yaml:"client_id"` - ClientSecret string `bun:"client_secret,notnull"yaml:"client_secret"` + MapperURL string `bun:"mapper_url" yaml:"mapper_url"` + ClientId string `bun:"client_id,notnull" yaml:"client_id"` + ClientSecret string `bun:"client_secret,notnull" yaml:"client_secret"` Scope []string `bun:"scopes,notnull"` - IssuerURL string `bun:"issuer_url,notnull"yaml:"issuer_url"` - AuthURL string `bun:"auth_url"yaml:"auth_url,omitempty"` - TokenURL string `bun:"token_url"yaml:"token_url,omitempty"` - RequestedClaims map[string]interface{} `bun:"type:jsonb"yaml:"requested_claims,omitempty"` + IssuerURL string `bun:"issuer_url,notnull" yaml:"issuer_url"` + AuthURL string `bun:"auth_url" yaml:"auth_url,omitempty"` + TokenURL string `bun:"token_url" yaml:"token_url,omitempty"` + RequestedClaims map[string]interface{} `bun:"type:jsonb" yaml:"requested_claims,omitempty"` } type Config struct { @@ -44,18 +44,18 @@ var ProvidersDB []Provider func sync(ctx context.Context, db *bun.DB) error { err := db.NewSelect().Model(&ProvidersDB).ModelTableExpr("authsrv_oidc_provider AS provider").Scan(ctx) if err != nil { - return fmt.Errorf("failed to fetch providers from DB: ", err) + return fmt.Errorf("failed to fetch providers from DB: %s", err) } var c Config c.Selfservice.Methods.Oidc.Config.Providers = ProvidersDB d, err := yaml.Marshal(&c) if err != nil { - return fmt.Errorf("failed to marshal: ", err) + return fmt.Errorf("failed to marshal: %s", err) } err = os.WriteFile("oidc_providers.yml", d, 0644) if err != nil { - return fmt.Errorf("failed to write data: ", err) + return fmt.Errorf("failed to write data: %s", err) } return nil } @@ -71,8 +71,8 @@ func main() { panic(err) } - for _ = range ln.Channel() { - fmt.Printf("%s: Received notification", time.Now()) + for range ln.Channel() { + fmt.Printf("%s: Received notification\n", time.Now()) if err := sync(ctx, db); err != nil { fmt.Println(err) } else { diff --git a/components/usermgmt/pkg/service/oidc_provider.go b/components/usermgmt/pkg/service/oidc_provider.go index 07e9fc9..7e10098 100644 --- a/components/usermgmt/pkg/service/oidc_provider.go +++ b/components/usermgmt/pkg/service/oidc_provider.go @@ -3,6 +3,7 @@ package service import ( "context" "fmt" + "net/url" "os" "time" @@ -38,6 +39,11 @@ func generateCallbackUrl(id string) string { return fmt.Sprintf("%s/self-service/methods/oidc/callback/%s", base, id) } +func validateURL(rawURL string) error { + _, err := url.ParseRequestURI(rawURL) + return err +} + func (s *oidcProvider) Create(ctx context.Context, provider *userv3.OIDCProvider) (*userv3.OIDCProvider, error) { // validate name name := provider.Metadata.GetName() @@ -50,19 +56,37 @@ func (s *oidcProvider) Create(ctx context.Context, provider *userv3.OIDCProvider return &userv3.OIDCProvider{}, fmt.Errorf("DUPLICATE NAME") } + mapUrl := provider.Spec.GetMapperUrl() + issUrl := provider.Spec.GetIssuerUrl() + authUrl := provider.Spec.GetAuthUrl() + tknUrl := provider.Spec.GetTokenUrl() + + if len(mapUrl) != 0 && validateURL(mapUrl) != nil { + return &userv3.OIDCProvider{}, fmt.Errorf("INVALID MAPPER URL") + } + if len(issUrl) != 0 && validateURL(issUrl) != nil { + return &userv3.OIDCProvider{}, fmt.Errorf("INVALID ISSUER URL") + } + if len(authUrl) != 0 && validateURL(authUrl) != nil { + return &userv3.OIDCProvider{}, fmt.Errorf("INVALID AUTH URL") + } + if len(tknUrl) != 0 && validateURL(tknUrl) != nil { + return &userv3.OIDCProvider{}, fmt.Errorf("INVALID TOKEN URL") + } + entity := &models.OIDCProvider{ Name: name, CreatedAt: time.Time{}, ModifiedAt: time.Time{}, ProviderName: provider.Spec.GetProviderName(), - MapperURL: provider.Spec.GetMapperUrl(), + MapperURL: mapUrl, MapperFilename: provider.Spec.GetMapperFilename(), ClientId: provider.Spec.GetClientId(), ClientSecret: provider.Spec.GetClientSecret(), Scopes: provider.Spec.GetScopes(), - IssuerURL: provider.Spec.GetIssuerUrl(), - AuthURL: provider.Spec.GetAuthUrl(), - TokenURL: provider.Spec.GetTokenUrl(), + IssuerURL: issUrl, + AuthURL: authUrl, + TokenURL: tknUrl, RequestedClaims: provider.Spec.GetRequestedClaims().AsMap(), Predefined: provider.Spec.GetPredefined(), } @@ -207,6 +231,25 @@ func (s *oidcProvider) Update(ctx context.Context, provider *userv3.OIDCProvider if err != nil { return &userv3.OIDCProvider{}, err } + + mapUrl := provider.Spec.GetMapperUrl() + issUrl := provider.Spec.GetIssuerUrl() + authUrl := provider.Spec.GetAuthUrl() + tknUrl := provider.Spec.GetTokenUrl() + + if len(mapUrl) != 0 && validateURL(mapUrl) != nil { + return &userv3.OIDCProvider{}, fmt.Errorf("INVALID MAPPER URL") + } + if len(issUrl) != 0 && validateURL(issUrl) != nil { + return &userv3.OIDCProvider{}, fmt.Errorf("INVALID ISSUER URL") + } + if len(authUrl) != 0 && validateURL(authUrl) != nil { + return &userv3.OIDCProvider{}, fmt.Errorf("INVALID AUTH URL") + } + if len(tknUrl) != 0 && validateURL(tknUrl) != nil { + return &userv3.OIDCProvider{}, fmt.Errorf("INVALID TOKEN URL") + } + entity := &models.OIDCProvider{ Id: id, Name: provider.Metadata.GetName(), @@ -215,14 +258,14 @@ func (s *oidcProvider) Update(ctx context.Context, provider *userv3.OIDCProvider PartnerId: partId, ModifiedAt: time.Now(), ProviderName: provider.Spec.GetProviderName(), - MapperURL: provider.Spec.GetMapperUrl(), + MapperURL: mapUrl, MapperFilename: provider.Spec.GetMapperFilename(), ClientId: provider.Spec.GetClientId(), ClientSecret: provider.Spec.GetClientSecret(), Scopes: provider.Spec.GetScopes(), - IssuerURL: provider.Spec.GetIssuerUrl(), - AuthURL: provider.Spec.GetAuthUrl(), - TokenURL: provider.Spec.GetTokenUrl(), + IssuerURL: issUrl, + AuthURL: authUrl, + TokenURL: tknUrl, RequestedClaims: provider.Spec.GetRequestedClaims().AsMap(), Predefined: provider.Spec.GetPredefined(), }