From 7e4dc852bbaedde494efd1726949b158baa71bb1 Mon Sep 17 00:00:00 2001 From: Arvid Mildner Date: Tue, 23 Mar 2021 17:49:30 +0100 Subject: [PATCH 1/4] Added denylist options for the connections as described in https://auth0.com/docs/security/denylist-user-attributes --- management/connection.go | 231 ++++++++++++++++++---------------- management/connection_test.go | 5 +- management/management.gen.go | 136 ++++++++++++++++++++ 3 files changed, 262 insertions(+), 110 deletions(-) diff --git a/management/connection.go b/management/connection.go index 30800d5..3a7efde 100644 --- a/management/connection.go +++ b/management/connection.go @@ -209,7 +209,8 @@ type ConnectionOptions struct { StrategyVersion *int `json:"strategy_version,omitempty"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } type ConnectionOptionsGoogleOAuth2 struct { @@ -218,39 +219,39 @@ type ConnectionOptionsGoogleOAuth2 struct { AllowedAudiences []interface{} `json:"allowed_audiences,omitempty"` - Email *bool `json:"email,omitempty" scope:"email"` - Profile *bool `json:"profile,omitempty" scope:"profile"` - Contacts *bool `json:"contacts,omitempty" scope:"contacts"` - Blogger *bool `json:"blogger,omitempty" scope:"blogger"` - Calendar *bool `json:"calendar,omitempty" scope:"calendar"` - Gmail *bool `json:"gmail,omitempty" scope:"gmail"` - GooglePlus *bool `json:"google_plus,omitempty" scope:"google_plus"` - Orkut *bool `json:"orkut,omitempty" scope:"orkut"` - PicasaWeb *bool `json:"picasa_web,omitempty" scope:"picasa_web"` - Tasks *bool `json:"tasks,omitempty" scope:"tasks"` - Youtube *bool `json:"youtube,omitempty" scope:"youtube"` - AdsenseManagement *bool `json:"adsense_management,omitempty" scope:"adsense_management"` - GoogleAffiliateNetwork *bool `json:"google_affiliate_network,omitempty" scope:"google_affiliate_network"` - Analytics *bool `json:"analytics,omitempty" scope:"analytics"` - GoogleBooks *bool `json:"google_books,omitempty" scope:"google_books"` - GoogleCloudStorage *bool `json:"google_cloud_storage,omitempty" scope:"google_cloud_storage"` - ContentAPIForShopping *bool `json:"content_api_for_shopping,omitempty" scope:"content_api_for_shopping"` - ChromeWebStore *bool `json:"chrome_web_store,omitempty" scope:"chrome_web_store"` - DocumentList *bool `json:"document_list,omitempty" scope:"document_list"` - GoogleDrive *bool `json:"google_drive,omitempty" scope:"google_drive"` - GoogleDriveFiles *bool `json:"google_drive_files,omitempty" scope:"google_drive_files"` - LatitudeBest *bool `json:"latitude_best,omitempty" scope:"latitude_best"` - LatitudeCity *bool `json:"latitude_city,omitempty" scope:"latitude_city"` - Moderator *bool `json:"moderator,omitempty" scope:"moderator"` - Sites *bool `json:"sites,omitempty" scope:"sites"` - Spreadsheets *bool `json:"spreadsheets,omitempty" scope:"spreadsheets"` - URLShortener *bool `json:"url_shortener,omitempty" scope:"url_shortener"` - WebmasterTools *bool `json:"webmaster_tools,omitempty" scope:"webmaster_tools"` - Coordinate *bool `json:"coordinate,omitempty" scope:"coordinate"` - CoordinateReadonly *bool `json:"coordinate_readonly,omitempty" scope:"coordinate_readonly"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` - - Scope []interface{} `json:"scope,omitempty"` + Email *bool `json:"email,omitempty" scope:"email"` + Profile *bool `json:"profile,omitempty" scope:"profile"` + Contacts *bool `json:"contacts,omitempty" scope:"contacts"` + Blogger *bool `json:"blogger,omitempty" scope:"blogger"` + Calendar *bool `json:"calendar,omitempty" scope:"calendar"` + Gmail *bool `json:"gmail,omitempty" scope:"gmail"` + GooglePlus *bool `json:"google_plus,omitempty" scope:"google_plus"` + Orkut *bool `json:"orkut,omitempty" scope:"orkut"` + PicasaWeb *bool `json:"picasa_web,omitempty" scope:"picasa_web"` + Tasks *bool `json:"tasks,omitempty" scope:"tasks"` + Youtube *bool `json:"youtube,omitempty" scope:"youtube"` + AdsenseManagement *bool `json:"adsense_management,omitempty" scope:"adsense_management"` + GoogleAffiliateNetwork *bool `json:"google_affiliate_network,omitempty" scope:"google_affiliate_network"` + Analytics *bool `json:"analytics,omitempty" scope:"analytics"` + GoogleBooks *bool `json:"google_books,omitempty" scope:"google_books"` + GoogleCloudStorage *bool `json:"google_cloud_storage,omitempty" scope:"google_cloud_storage"` + ContentAPIForShopping *bool `json:"content_api_for_shopping,omitempty" scope:"content_api_for_shopping"` + ChromeWebStore *bool `json:"chrome_web_store,omitempty" scope:"chrome_web_store"` + DocumentList *bool `json:"document_list,omitempty" scope:"document_list"` + GoogleDrive *bool `json:"google_drive,omitempty" scope:"google_drive"` + GoogleDriveFiles *bool `json:"google_drive_files,omitempty" scope:"google_drive_files"` + LatitudeBest *bool `json:"latitude_best,omitempty" scope:"latitude_best"` + LatitudeCity *bool `json:"latitude_city,omitempty" scope:"latitude_city"` + Moderator *bool `json:"moderator,omitempty" scope:"moderator"` + Sites *bool `json:"sites,omitempty" scope:"sites"` + Spreadsheets *bool `json:"spreadsheets,omitempty" scope:"spreadsheets"` + URLShortener *bool `json:"url_shortener,omitempty" scope:"url_shortener"` + WebmasterTools *bool `json:"webmaster_tools,omitempty" scope:"webmaster_tools"` + Coordinate *bool `json:"coordinate,omitempty" scope:"coordinate"` + CoordinateReadonly *bool `json:"coordinate_readonly,omitempty" scope:"coordinate_readonly"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` + Scope []interface{} `json:"scope,omitempty"` } func (c *ConnectionOptionsGoogleOAuth2) Scopes() []string { @@ -265,49 +266,49 @@ type ConnectionOptionsFacebook struct { ClientID *string `json:"client_id,omitempty"` ClientSecret *string `json:"client_secret,omitempty"` - AllowContextProfileField *bool `json:"allow_context_profile_field,omitempty"` - - Email *bool `json:"email,omitempty" scope:"email"` - GroupsAccessMemberInfo *bool `json:"groups_access_member_info,omitempty" scope:"groups_access_member_info"` - PublishToGroups *bool `json:"publish_to_groups,omitempty" scope:"publish_to_groups"` - UserAgeRange *bool `json:"user_age_range,omitempty" scope:"user_age_range"` - UserBirthday *bool `json:"user_birthday,omitempty" scope:"user_birthday"` - AdsManagement *bool `json:"ads_management,omitempty" scope:"ads_management"` - AdsRead *bool `json:"ads_read,omitempty" scope:"ads_read"` - ReadAudienceNetworkInsights *bool `json:"read_audience_network_insights,omitempty" scope:"read_audience_network_insights"` - ReadInsights *bool `json:"read_insights,omitempty" scope:"read_insights"` - ManageNotifications *bool `json:"manage_notifications,omitempty" scope:"manage_notifications"` - PublishActions *bool `json:"publish_actions,omitempty" scope:"publish_actions"` - ReadMailbox *bool `json:"read_mailbox,omitempty" scope:"read_mailbox"` - PublicProfile *bool `json:"public_profile,omitempty" scope:"public_profile"` - UserEvents *bool `json:"user_events,omitempty" scope:"user_events"` - UserFriends *bool `json:"user_friends,omitempty" scope:"user_friends"` - UserGender *bool `json:"user_gender,omitempty" scope:"user_gender"` - UserHometown *bool `json:"user_hometown,omitempty" scope:"user_hometown"` - UserLikes *bool `json:"user_likes,omitempty" scope:"user_likes"` - UserLink *bool `json:"user_link,omitempty" scope:"user_link"` - UserLocation *bool `json:"user_location,omitempty" scope:"user_location"` - UserPhotos *bool `json:"user_photos,omitempty" scope:"user_photos"` - UserPosts *bool `json:"user_posts,omitempty" scope:"user_posts"` - UserTaggedPlaces *bool `json:"user_tagged_places,omitempty" scope:"user_tagged_places"` - UserVideos *bool `json:"user_videos,omitempty" scope:"user_videos"` - BusinessManagement *bool `json:"business_management,omitempty" scope:"business_management"` - LeadsRetrieval *bool `json:"leads_retrieval,omitempty" scope:"leads_retrieval"` - ManagePages *bool `json:"manage_pages,omitempty" scope:"manage_pages"` - PagesManageCTA *bool `json:"pages_manage_cta,omitempty" scope:"pages_manage_cta"` - PagesManageInstantArticles *bool `json:"pages_manage_instant_articles,omitempty" scope:"pages_manage_instant_articles"` - PagesShowList *bool `json:"pages_show_list,omitempty" scope:"pages_show_list"` - PagesMessaging *bool `json:"pages_messaging,omitempty" scope:"pages_messaging"` - PagesMessagingPhoneNumber *bool `json:"pages_messaging_phone_number,omitempty" scope:"pages_messaging_phone_number"` - PagesMessagingSubscriptions *bool `json:"pages_messaging_subscriptions,omitempty" scope:"pages_messaging_subscriptions"` - PublishPages *bool `json:"publish_pages,omitempty" scope:"publish_pages"` - PublishVideo *bool `json:"publish_video,omitempty" scope:"publish_video"` - ReadPageMailboxes *bool `json:"read_page_mailboxes,omitempty" scope:"read_page_mailboxes"` - ReadStream *bool `json:"read_stream,omitempty" scope:"read_stream"` - UserGroups *bool `json:"user_groups,omitempty" scope:"user_groups"` - UserManagedGroups *bool `json:"user_managed_groups,omitempty" scope:"user_managed_groups"` - UserStatus *bool `json:"user_status,omitempty" scope:"user_status"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + AllowContextProfileField *bool `json:"allow_context_profile_field,omitempty"` + Email *bool `json:"email,omitempty" scope:"email"` + GroupsAccessMemberInfo *bool `json:"groups_access_member_info,omitempty" scope:"groups_access_member_info"` + PublishToGroups *bool `json:"publish_to_groups,omitempty" scope:"publish_to_groups"` + UserAgeRange *bool `json:"user_age_range,omitempty" scope:"user_age_range"` + UserBirthday *bool `json:"user_birthday,omitempty" scope:"user_birthday"` + AdsManagement *bool `json:"ads_management,omitempty" scope:"ads_management"` + AdsRead *bool `json:"ads_read,omitempty" scope:"ads_read"` + ReadAudienceNetworkInsights *bool `json:"read_audience_network_insights,omitempty" scope:"read_audience_network_insights"` + ReadInsights *bool `json:"read_insights,omitempty" scope:"read_insights"` + ManageNotifications *bool `json:"manage_notifications,omitempty" scope:"manage_notifications"` + PublishActions *bool `json:"publish_actions,omitempty" scope:"publish_actions"` + ReadMailbox *bool `json:"read_mailbox,omitempty" scope:"read_mailbox"` + PublicProfile *bool `json:"public_profile,omitempty" scope:"public_profile"` + UserEvents *bool `json:"user_events,omitempty" scope:"user_events"` + UserFriends *bool `json:"user_friends,omitempty" scope:"user_friends"` + UserGender *bool `json:"user_gender,omitempty" scope:"user_gender"` + UserHometown *bool `json:"user_hometown,omitempty" scope:"user_hometown"` + UserLikes *bool `json:"user_likes,omitempty" scope:"user_likes"` + UserLink *bool `json:"user_link,omitempty" scope:"user_link"` + UserLocation *bool `json:"user_location,omitempty" scope:"user_location"` + UserPhotos *bool `json:"user_photos,omitempty" scope:"user_photos"` + UserPosts *bool `json:"user_posts,omitempty" scope:"user_posts"` + UserTaggedPlaces *bool `json:"user_tagged_places,omitempty" scope:"user_tagged_places"` + UserVideos *bool `json:"user_videos,omitempty" scope:"user_videos"` + BusinessManagement *bool `json:"business_management,omitempty" scope:"business_management"` + LeadsRetrieval *bool `json:"leads_retrieval,omitempty" scope:"leads_retrieval"` + ManagePages *bool `json:"manage_pages,omitempty" scope:"manage_pages"` + PagesManageCTA *bool `json:"pages_manage_cta,omitempty" scope:"pages_manage_cta"` + PagesManageInstantArticles *bool `json:"pages_manage_instant_articles,omitempty" scope:"pages_manage_instant_articles"` + PagesShowList *bool `json:"pages_show_list,omitempty" scope:"pages_show_list"` + PagesMessaging *bool `json:"pages_messaging,omitempty" scope:"pages_messaging"` + PagesMessagingPhoneNumber *bool `json:"pages_messaging_phone_number,omitempty" scope:"pages_messaging_phone_number"` + PagesMessagingSubscriptions *bool `json:"pages_messaging_subscriptions,omitempty" scope:"pages_messaging_subscriptions"` + PublishPages *bool `json:"publish_pages,omitempty" scope:"publish_pages"` + PublishVideo *bool `json:"publish_video,omitempty" scope:"publish_video"` + ReadPageMailboxes *bool `json:"read_page_mailboxes,omitempty" scope:"read_page_mailboxes"` + ReadStream *bool `json:"read_stream,omitempty" scope:"read_stream"` + UserGroups *bool `json:"user_groups,omitempty" scope:"user_groups"` + UserManagedGroups *bool `json:"user_managed_groups,omitempty" scope:"user_managed_groups"` + UserStatus *bool `json:"user_status,omitempty" scope:"user_status"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` // Scope is a comma separated list of scopes. Scope *string `json:"scope,omitempty"` @@ -331,8 +332,9 @@ type ConnectionOptionsApple struct { Name *bool `json:"name,omitempty" scope:"name"` Email *bool `json:"email,omitempty" scope:"email"` - Scope *string `json:"scope,omitempty"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + Scope *string `json:"scope,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } func (c *ConnectionOptionsApple) Scopes() []string { @@ -355,7 +357,8 @@ type ConnectionOptionsLinkedin struct { Scope []interface{} `json:"scope,omitempty"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } func (c *ConnectionOptionsLinkedin) Scopes() []string { @@ -393,7 +396,8 @@ type ConnectionOptionsGitHub struct { Scope []interface{} `json:"scope,omitempty"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } func (c *ConnectionOptionsGitHub) Scopes() []string { @@ -412,9 +416,10 @@ type ConnectionOptionsEmail struct { AuthParams map[string]string `json:"authParams,omitempty"` - DisableSignup *bool `json:"disable_signup,omitempty"` - BruteForceProtection *bool `json:"brute_force_protection,omitempty"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + DisableSignup *bool `json:"disable_signup,omitempty"` + BruteForceProtection *bool `json:"brute_force_protection,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } type ConnectionOptionsEmailSettings struct { @@ -478,7 +483,8 @@ type ConnectionOptionsWindowsLive struct { Scope []interface{} `json:"scope,omitempty"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } func (c *ConnectionOptionsWindowsLive) Scopes() []string { @@ -497,8 +503,9 @@ type ConnectionOptionsSalesforce struct { Scope []interface{} `json:"scope,omitempty"` - CommunityBaseURL *string `json:"community_base_url,omitempty"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + CommunityBaseURL *string `json:"community_base_url,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } func (c *ConnectionOptionsSalesforce) Scopes() []string { @@ -517,16 +524,17 @@ type ConnectionOptionsOIDC struct { DomainAliases []interface{} `json:"domain_aliases,omitempty"` LogoURL *string `json:"icon_url,omitempty"` - DiscoveryURL *string `json:"discovery_url"` - AuthorizationEndpoint *string `json:"authorization_endpoint"` - Issuer *string `json:"issuer"` - JWKSURI *string `json:"jwks_uri"` - Type *string `json:"type"` - UserInfoEndpoint *string `json:"userinfo_endpoint"` - TokenEndpoint *string `json:"token_endpoint"` + DiscoveryURL *string `json:"discovery_url"` + AuthorizationEndpoint *string `json:"authorization_endpoint"` + Issuer *string `json:"issuer"` + JWKSURI *string `json:"jwks_uri"` + Type *string `json:"type"` + UserInfoEndpoint *string `json:"userinfo_endpoint"` + TokenEndpoint *string `json:"token_endpoint"` + Scope *string `json:"scope,omitempty"` - Scope *string `json:"scope,omitempty"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } func (c *ConnectionOptionsOIDC) Scopes() []string { @@ -553,13 +561,13 @@ func (c *ConnectionOptionsOIDC) SetScopes(enable bool, scopes ...string) { } type ConnectionOptionsOAuth2 struct { - ClientID *string `json:"client_id,omitempty"` - ClientSecret *string `json:"client_secret,omitempty"` - AuthorizationURL *string `json:"authorizationURL"` - TokenURL *string `json:"tokenURL"` - Scope *string `json:"scope,omitempty"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` - + ClientID *string `json:"client_id,omitempty"` + ClientSecret *string `json:"client_secret,omitempty"` + AuthorizationURL *string `json:"authorizationURL"` + TokenURL *string `json:"tokenURL"` + Scope *string `json:"scope,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` // Scripts for the connection // Allowed keys are: "fetchUserProfile" Scripts map[string]interface{} `json:"scripts,omitempty"` @@ -599,7 +607,8 @@ type ConnectionOptionsAD struct { DisableCache *bool `json:"disable_cache,omitempty"` BruteForceProtection *bool `json:"brute_force_protection,omitempty"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } type ConnectionOptionsAzureAD struct { @@ -631,8 +640,9 @@ type ConnectionOptionsAzureAD struct { AgreedTerms *bool `json:"ext_agreed_terms,omitempty" scope:"ext_agreed_terms"` AssignedPlans *bool `json:"ext_assigned_plans,omitempty" scope:"ext_assigned_plans"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` - TrustEmailVerified *string `json:"should_trust_email_verified_connection,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + TrustEmailVerified *string `json:"should_trust_email_verified_connection,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } func (c *ConnectionOptionsAzureAD) Scopes() []string { @@ -652,7 +662,8 @@ type ConnectionOptionsADFS struct { EnableUsersAPI *bool `json:"api_enable_users,omitempty"` // Set to on_first_login to avoid setting user attributes at each login. - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } type ConnectionOptionsSAML struct { @@ -678,7 +689,8 @@ type ConnectionOptionsSAML struct { UserIDAttribute *string `json:"user_id_attribute,omitempty"` LogoURL *string `json:"icon_url,omitempty"` - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } type ConnectionOptionsSAMLIdpInitiated struct { @@ -686,6 +698,9 @@ type ConnectionOptionsSAMLIdpInitiated struct { ClientID *string `json:"client_id,omitempty"` ClientProtocol *string `json:"client_protocol,omitempty"` ClientAuthorizeQuery *string `json:"client_authorizequery,omitempty"` + + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } type ConnectionManager struct { diff --git a/management/connection_test.go b/management/connection_test.go index 661a2b4..006b6c8 100644 --- a/management/connection_test.go +++ b/management/connection_test.go @@ -102,8 +102,9 @@ func TestConnection(t *testing.T) { DisableSignup: auth0.Bool(true), RequiresUsername: auth0.Bool(false), - CustomScripts: map[string]interface{}{"get_user": "function( { return callback(null) }"}, - Configuration: map[string]interface{}{"foo": "bar"}, + CustomScripts: map[string]interface{}{"get_user": "function( { return callback(null) }"}, + Configuration: map[string]interface{}{"foo": "bar"}, + NonPersistentAttrs: &[]string{"ethnicity", "gender"}, } err = m.Connection.Update(id, c) diff --git a/management/management.gen.go b/management/management.gen.go index 495a01f..cd0b4dc 100644 --- a/management/management.gen.go +++ b/management/management.gen.go @@ -553,6 +553,14 @@ func (c *ConnectionOptions) GetImportMode() bool { return *c.ImportMode } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptions) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetPasswordPolicy returns the PasswordPolicy field if it's non-nil, zero value otherwise. func (c *ConnectionOptions) GetPasswordPolicy() string { if c == nil || c.PasswordPolicy == nil { @@ -630,6 +638,14 @@ func (c *ConnectionOptionsAD) GetLogoURL() string { return *c.LogoURL } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsAD) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetSetUserAttributes returns the SetUserAttributes field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsAD) GetSetUserAttributes() string { if c == nil || c.SetUserAttributes == nil { @@ -675,6 +691,14 @@ func (c *ConnectionOptionsADFS) GetLogoURL() string { return *c.LogoURL } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsADFS) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetSetUserAttributes returns the SetUserAttributes field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsADFS) GetSetUserAttributes() string { if c == nil || c.SetUserAttributes == nil { @@ -736,6 +760,14 @@ func (c *ConnectionOptionsApple) GetName() bool { return *c.Name } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsApple) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetScope returns the Scope field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsApple) GetScope() string { if c == nil || c.Scope == nil { @@ -893,6 +925,14 @@ func (c *ConnectionOptionsAzureAD) GetNestedGroups() bool { return *c.NestedGroups } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsAzureAD) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetSetUserAttributes returns the SetUserAttributes field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsAzureAD) GetSetUserAttributes() string { if c == nil || c.SetUserAttributes == nil { @@ -986,6 +1026,14 @@ func (c *ConnectionOptionsEmail) GetName() string { return *c.Name } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsEmail) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetOTP returns the OTP field. func (c *ConnectionOptionsEmail) GetOTP() *ConnectionOptionsOTP { if c == nil { @@ -1132,6 +1180,14 @@ func (c *ConnectionOptionsFacebook) GetManagePages() bool { return *c.ManagePages } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsFacebook) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetPagesManageCTA returns the PagesManageCTA field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsFacebook) GetPagesManageCTA() bool { if c == nil || c.PagesManageCTA == nil { @@ -1481,6 +1537,14 @@ func (c *ConnectionOptionsGitHub) GetGist() bool { return *c.Gist } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsGitHub) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetNotifications returns the Notifications field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsGitHub) GetNotifications() bool { if c == nil || c.Notifications == nil { @@ -1782,6 +1846,14 @@ func (c *ConnectionOptionsGoogleOAuth2) GetModerator() bool { return *c.Moderator } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsGoogleOAuth2) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetOrkut returns the Orkut field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsGoogleOAuth2) GetOrkut() bool { if c == nil || c.Orkut == nil { @@ -1899,6 +1971,14 @@ func (c *ConnectionOptionsLinkedin) GetEmail() bool { return *c.Email } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsLinkedin) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetProfile returns the Profile field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsLinkedin) GetProfile() bool { if c == nil || c.Profile == nil { @@ -1952,6 +2032,14 @@ func (c *ConnectionOptionsOAuth2) GetClientSecret() string { return *c.ClientSecret } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsOAuth2) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetScope returns the Scope field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsOAuth2) GetScope() string { if c == nil || c.Scope == nil { @@ -2037,6 +2125,14 @@ func (c *ConnectionOptionsOIDC) GetLogoURL() string { return *c.LogoURL } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsOIDC) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetScope returns the Scope field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsOIDC) GetScope() string { if c == nil || c.Scope == nil { @@ -2135,6 +2231,14 @@ func (c *ConnectionOptionsSalesforce) GetCommunityBaseURL() string { return *c.CommunityBaseURL } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsSalesforce) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetProfile returns the Profile field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsSalesforce) GetProfile() bool { if c == nil || c.Profile == nil { @@ -2220,6 +2324,14 @@ func (c *ConnectionOptionsSAML) GetMetadataXML() string { return *c.MetadataXML } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsSAML) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetProtocolBinding returns the ProtocolBinding field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsSAML) GetProtocolBinding() string { if c == nil || c.ProtocolBinding == nil { @@ -2337,6 +2449,22 @@ func (c *ConnectionOptionsSAMLIdpInitiated) GetEnabled() bool { return *c.Enabled } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsSAMLIdpInitiated) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + +// GetSetUserAttributes returns the SetUserAttributes field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsSAMLIdpInitiated) GetSetUserAttributes() string { + if c == nil || c.SetUserAttributes == nil { + return "" + } + return *c.SetUserAttributes +} + // String returns a string representation of ConnectionOptionsSAMLIdpInitiated. func (c *ConnectionOptionsSAMLIdpInitiated) String() string { return Stringify(c) @@ -2539,6 +2667,14 @@ func (c *ConnectionOptionsWindowsLive) GetFilesUpdate() bool { return *c.FilesUpdate } +// GetNonPersistentAttrs returns the NonPersistentAttrs field if it's non-nil, zero value otherwise. +func (c *ConnectionOptionsWindowsLive) GetNonPersistentAttrs() []string { + if c == nil || c.NonPersistentAttrs == nil { + return nil + } + return *c.NonPersistentAttrs +} + // GetNotes returns the Notes field if it's non-nil, zero value otherwise. func (c *ConnectionOptionsWindowsLive) GetNotes() bool { if c == nil || c.Notes == nil { From 3502f08e67cce965f328ded68b99125e6304a657 Mon Sep 17 00:00:00 2001 From: Arvid Mildner Date: Wed, 24 Mar 2021 11:52:34 +0100 Subject: [PATCH 2/4] Added some tests to verify that the NonPersistentAttrs field works as expected for the various connections. --- management/connection_test.go | 50 ++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/management/connection_test.go b/management/connection_test.go index 006b6c8..cde6af3 100644 --- a/management/connection_test.go +++ b/management/connection_test.go @@ -1,6 +1,7 @@ package management import ( + "log" "testing" "time" @@ -159,9 +160,10 @@ func TestConnectionOptions(t *testing.T) { "example.com", "api.example.com", }, - Profile: auth0.Bool(true), - Calendar: auth0.Bool(true), - Youtube: auth0.Bool(false), + Profile: auth0.Bool(true), + Calendar: auth0.Bool(true), + Youtube: auth0.Bool(false), + NonPersistentAttrs: &[]string{"gender", "ethnicity", "favorite_color"}, }, } @@ -171,16 +173,33 @@ func TestConnectionOptions(t *testing.T) { if err != nil { t.Fatal(err) } - - o, ok := g.Options.(*ConnectionOptionsGoogleOAuth2) + c, err := m.Connection.Read(g.GetID()) + if err != nil { + t.Fatal(err) + } + o, ok := c.Options.(*ConnectionOptionsGoogleOAuth2) if !ok { t.Fatalf("unexpected type %T", o) } - expect.Expect(t, o.GetProfile(), true) expect.Expect(t, o.GetCalendar(), true) expect.Expect(t, o.GetYoutube(), false) expect.Expect(t, o.Scopes(), []string{"email", "profile", "calendar"}) + expect.Expect(t, o.GetNonPersistentAttrs(), []string{"gender", "ethnicity", "favorite_color"}) + + o.NonPersistentAttrs = &[]string{""} + g.Options = o + err = m.Connection.Update(g.GetID(), g) + if err != nil { + log.Fatal(err) + } + + c, err = m.Connection.Read(g.GetID()) + if err != nil { + log.Fatal(err) + } + o, ok = c.Options.(*ConnectionOptionsGoogleOAuth2) + expect.Expect(t, o.GetNonPersistentAttrs(), []string{""}) t.Logf("%s\n", g) }) @@ -196,15 +215,20 @@ func TestConnectionOptions(t *testing.T) { o.SetScopes(false, "baz") expect.Expect(t, len(o.Scopes()), 2) expect.Expect(t, o.Scopes(), []string{"bar", "foo"}) + + o.NonPersistentAttrs = &[]string{"gender", "ethnicity", "favorite_color"} + expect.Expect(t, o.GetNonPersistentAttrs(), []string{"gender", "ethnicity", "favorite_color"}) + }) t.Run("OAuth2", func(t *testing.T) { o := &ConnectionOptionsOAuth2{ - Scripts: map[string]interface{}{"fetchUserProfile": "function( { return callback(null) }"}, - TokenURL: auth0.String("https://example.com/oauth2/token"), - AuthorizationURL: auth0.String("https://example.com/oauth2/authorize"), - ClientID: auth0.String("test-client"), - ClientSecret: auth0.String("superSecretKey"), + Scripts: map[string]interface{}{"fetchUserProfile": "function( { return callback(null) }"}, + TokenURL: auth0.String("https://example.com/oauth2/token"), + AuthorizationURL: auth0.String("https://example.com/oauth2/authorize"), + ClientID: auth0.String("test-client"), + ClientSecret: auth0.String("superSecretKey"), + NonPersistentAttrs: &[]string{"gender", "ethnicity", "favorite_color"}, } expect.Expect(t, len(o.Scopes()), 0) @@ -215,7 +239,10 @@ func TestConnectionOptions(t *testing.T) { o.SetScopes(false, "baz") expect.Expect(t, len(o.Scopes()), 2) expect.Expect(t, o.Scopes(), []string{"bar", "foo"}) + expect.Expect(t, o.GetNonPersistentAttrs(), []string{"gender", "ethnicity", "favorite_color"}) + o.NonPersistentAttrs = &[]string{"foo", "bar"} + expect.Expect(t, o.GetNonPersistentAttrs(), []string{"foo", "bar"}) }) t.Run("Email", func(t *testing.T) { @@ -249,7 +276,6 @@ func TestConnectionOptions(t *testing.T) { if err != nil { t.Fatal(err) } - o, ok := e.Options.(*ConnectionOptionsEmail) if !ok { t.Fatalf("unexpected type %T", o) From a6d1b16bcee523f7b2e40e9f8c74ee5b6a350243 Mon Sep 17 00:00:00 2001 From: Arvid Mildner Date: Mon, 5 Apr 2021 20:15:37 +0200 Subject: [PATCH 3/4] Added testify and modified defers in tests so they also verify that the connection was deleted. --- go.mod | 1 + management/connection_test.go | 33 ++++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 66e0f47..b8b5f9d 100644 --- a/go.mod +++ b/go.mod @@ -7,5 +7,6 @@ require ( github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0 // indirect github.com/benbjohnson/clock v1.0.3 // indirect github.com/dustin/go-humanize v1.0.0 // indirect + github.com/stretchr/testify v1.4.0 golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 ) diff --git a/management/connection_test.go b/management/connection_test.go index cde6af3..13fbc04 100644 --- a/management/connection_test.go +++ b/management/connection_test.go @@ -1,6 +1,7 @@ package management import ( + "github.com/stretchr/testify/assert" "log" "testing" "time" @@ -167,7 +168,11 @@ func TestConnectionOptions(t *testing.T) { }, } - defer func() { m.Connection.Delete(g.GetID()) }() + defer func() { + m.Connection.Delete(g.GetID()) + assertDeleted(t, g) + + }() err := m.Connection.Create(g) if err != nil { @@ -270,7 +275,10 @@ func TestConnectionOptions(t *testing.T) { }, } - defer func() { m.Connection.Delete(e.GetID()) }() + defer func() { + m.Connection.Delete(e.GetID()) + assertDeleted(t, e) + }() err := m.Connection.Create(e) if err != nil { @@ -320,7 +328,10 @@ func TestConnectionOptions(t *testing.T) { }, } - defer func() { m.Connection.Delete(s.GetID()) }() + defer func() { + m.Connection.Delete(s.GetID()) + assertDeleted(t, s) + }() err := m.Connection.Create(s) if err != nil { @@ -386,7 +397,10 @@ ZsUkLw2I7zI/dNlWdB8Xp7v+3w9sX5N3J/WuJ1KOO5m26kRlHQo7EzT3974g }, }, } - defer func() { m.Connection.Delete(g.GetID()) }() + defer func() { + m.Connection.Delete(g.GetID()) + assertDeleted(t, g) + }() err := m.Connection.Create(g) if err != nil { @@ -408,7 +422,10 @@ ZsUkLw2I7zI/dNlWdB8Xp7v+3w9sX5N3J/WuJ1KOO5m26kRlHQo7EzT3974g Strategy: auth0.String("ad"), } - defer func() { m.Connection.Delete(a.GetID()) }() + defer func() { + m.Connection.Delete(a.GetID()) + assertDeleted(t, a) + }() if err := m.Connection.Create(a); err != nil { t.Fatal(err) @@ -453,3 +470,9 @@ ZsUkLw2I7zI/dNlWdB8Xp7v+3w9sX5N3J/WuJ1KOO5m26kRlHQo7EzT3974g } }) } + +func assertDeleted(t *testing.T, c *Connection) { + c, err := m.Connection.Read(c.GetID()) + assert.Nil(t, c) + assert.EqualError(t, err, "404 Not Found: The connection does not exist") +} From 711ff1af5eec8663eee1864a5bf744bdab9f22ff Mon Sep 17 00:00:00 2001 From: Arvid Mildner Date: Mon, 5 Apr 2021 20:19:50 +0200 Subject: [PATCH 4/4] Added tests that updates connection options with denylist options (NonPersistentAttrs) for GoogleOauth2 and Email --- management/connection.go | 22 +++++++++++----------- management/connection_test.go | 33 +++++++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/management/connection.go b/management/connection.go index 3a7efde..ae607bd 100644 --- a/management/connection.go +++ b/management/connection.go @@ -524,17 +524,17 @@ type ConnectionOptionsOIDC struct { DomainAliases []interface{} `json:"domain_aliases,omitempty"` LogoURL *string `json:"icon_url,omitempty"` - DiscoveryURL *string `json:"discovery_url"` - AuthorizationEndpoint *string `json:"authorization_endpoint"` - Issuer *string `json:"issuer"` - JWKSURI *string `json:"jwks_uri"` - Type *string `json:"type"` - UserInfoEndpoint *string `json:"userinfo_endpoint"` - TokenEndpoint *string `json:"token_endpoint"` - Scope *string `json:"scope,omitempty"` - - SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` - NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` + DiscoveryURL *string `json:"discovery_url"` + AuthorizationEndpoint *string `json:"authorization_endpoint"` + Issuer *string `json:"issuer"` + JWKSURI *string `json:"jwks_uri"` + Type *string `json:"type"` + UserInfoEndpoint *string `json:"userinfo_endpoint"` + TokenEndpoint *string `json:"token_endpoint"` + Scope *string `json:"scope,omitempty"` + + SetUserAttributes *string `json:"set_user_root_attributes,omitempty"` + NonPersistentAttrs *[]string `json:"non_persistent_attrs,omitempty"` } func (c *ConnectionOptionsOIDC) Scopes() []string { diff --git a/management/connection_test.go b/management/connection_test.go index 13fbc04..b171ade 100644 --- a/management/connection_test.go +++ b/management/connection_test.go @@ -161,10 +161,9 @@ func TestConnectionOptions(t *testing.T) { "example.com", "api.example.com", }, - Profile: auth0.Bool(true), - Calendar: auth0.Bool(true), - Youtube: auth0.Bool(false), - NonPersistentAttrs: &[]string{"gender", "ethnicity", "favorite_color"}, + Profile: auth0.Bool(true), + Calendar: auth0.Bool(true), + Youtube: auth0.Bool(false), }, } @@ -190,11 +189,22 @@ func TestConnectionOptions(t *testing.T) { expect.Expect(t, o.GetCalendar(), true) expect.Expect(t, o.GetYoutube(), false) expect.Expect(t, o.Scopes(), []string{"email", "profile", "calendar"}) + + o.NonPersistentAttrs = &[]string{"gender", "ethnicity", "favorite_color"} + err = m.Connection.Update(g.GetID(), &Connection{ + Options: o, + }) + if err != nil { + t.Fatal(err) + } + c, _ = m.Connection.Read(g.GetID()) + o, ok = c.Options.(*ConnectionOptionsGoogleOAuth2) expect.Expect(t, o.GetNonPersistentAttrs(), []string{"gender", "ethnicity", "favorite_color"}) o.NonPersistentAttrs = &[]string{""} - g.Options = o - err = m.Connection.Update(g.GetID(), g) + err = m.Connection.Update(g.GetID(), &Connection{ + Options: o, + }) if err != nil { log.Fatal(err) } @@ -300,6 +310,17 @@ func TestConnectionOptions(t *testing.T) { expect.Expect(t, o.GetDisableSignup(), true) expect.Expect(t, o.GetName(), "Test-Connection-Email") + o.NonPersistentAttrs = &[]string{"gender", "ethnicity", "favorite_color"} + err = m.Connection.Update(e.GetID(), &Connection{ + Options: o, + }) + if err != nil { + t.Fatal(err) + } + e, _ = m.Connection.Read(e.GetID()) + o, ok = e.Options.(*ConnectionOptionsEmail) + + expect.Expect(t, o.GetNonPersistentAttrs(), []string{"gender", "ethnicity", "favorite_color"}) t.Logf("%s\n", e) })