From c6e393596f7705f39753051b13b8dd4cfe72512c Mon Sep 17 00:00:00 2001 From: abhishek Date: Fri, 12 Sep 2025 00:19:22 +0530 Subject: [PATCH 1/3] Ratelimit Threshold --- .generator/templates/client.mustache | 5 +++-- .generator/templates/configuration.mustache | 7 +++++++ okta/client.go | 5 +++-- okta/configuration.go | 7 +++++++ 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/.generator/templates/client.mustache b/.generator/templates/client.mustache index 0fb012fa1..ffdc410f2 100644 --- a/.generator/templates/client.mustache +++ b/.generator/templates/client.mustache @@ -1140,8 +1140,9 @@ func (c *APIClient) do(ctx context.Context, req *http.Request) (*http.Response, c.rateLimitLock.Lock() limit := c.rateLimit c.rateLimitLock.Unlock() - if limit != nil && limit.Remaining <= 0 { - timer := time.NewTimer(time.Second * time.Duration(limit.Reset)) + // If the remaining requests are less than the threshold percentage of the limit, wait for the max backoff + if limit != nil && limit.Remaining <= int(c.cfg.Okta.Client.RateLimit.Threshold)*limit.Limit/100 { + timer := time.NewTimer(time.Second * time.Duration(c.cfg.Okta.Client.RateLimit.MaxBackoff)) select { case <-ctx.Done(): if !timer.Stop() { diff --git a/.generator/templates/configuration.mustache b/.generator/templates/configuration.mustache index 960dbf01a..4539df110 100644 --- a/.generator/templates/configuration.mustache +++ b/.generator/templates/configuration.mustache @@ -145,6 +145,7 @@ type Configuration struct { MaxRetries int32 `yaml:"maxRetries" envconfig:"OKTA_CLIENT_RATE_LIMIT_MAX_RETRIES"` MaxBackoff int64 `yaml:"maxBackoff" envconfig:"OKTA_CLIENT_RATE_LIMIT_MAX_BACKOFF"` Enable bool `yaml:"enable" envconfig:"OKTA_CLIENT_RATE_LIMIT_ENABLE"` + Threshold int32 `yaml:"threshold" envconfig:"OKTA_CLIENT_RATE_LIMIT_THRESHOLD"` } `yaml:"rateLimit"` OrgUrl string `yaml:"orgUrl" envconfig:"OKTA_CLIENT_ORGURL"` Token string `yaml:"token" envconfig:"OKTA_CLIENT_TOKEN"` @@ -551,6 +552,12 @@ func WithRateLimitMaxBackOff(maxBackoff int64) ConfigSetter { } } +func WithRateLimitThreshold(threshold int32) ConfigSetter { + return func(c *Configuration) { + c.Okta.Client.RateLimit.Threshold = threshold + } +} + func WithAuthorizationMode(authzMode string) ConfigSetter { return func(c *Configuration) { c.Okta.Client.AuthorizationMode = authzMode diff --git a/okta/client.go b/okta/client.go index f9b1ebc02..2e5880dbc 100644 --- a/okta/client.go +++ b/okta/client.go @@ -1328,8 +1328,9 @@ func (c *APIClient) do(ctx context.Context, req *http.Request) (*http.Response, c.rateLimitLock.Lock() limit := c.rateLimit c.rateLimitLock.Unlock() - if limit != nil && limit.Remaining <= 0 { - timer := time.NewTimer(time.Second * time.Duration(limit.Reset)) + // If the remaining requests are less than the threshold percentage of the limit, wait for the MaxBackoff + if limit != nil && limit.Remaining <= int(c.cfg.Okta.Client.RateLimit.Threshold)*limit.Limit/100 { + timer := time.NewTimer(time.Second * time.Duration(c.cfg.Okta.Client.RateLimit.MaxBackoff)) select { case <-ctx.Done(): if !timer.Stop() { diff --git a/okta/configuration.go b/okta/configuration.go index 0bf88e47f..1ad997194 100644 --- a/okta/configuration.go +++ b/okta/configuration.go @@ -142,6 +142,7 @@ type Configuration struct { MaxRetries int32 `yaml:"maxRetries" envconfig:"OKTA_CLIENT_RATE_LIMIT_MAX_RETRIES"` MaxBackoff int64 `yaml:"maxBackoff" envconfig:"OKTA_CLIENT_RATE_LIMIT_MAX_BACKOFF"` Enable bool `yaml:"enable" envconfig:"OKTA_CLIENT_RATE_LIMIT_ENABLE"` + Threshold int32 `yaml:"threshold" envconfig:"OKTA_CLIENT_RATE_LIMIT_THRESHOLD"` } `yaml:"rateLimit"` OrgUrl string `yaml:"orgUrl" envconfig:"OKTA_CLIENT_ORGURL"` Token string `yaml:"token" envconfig:"OKTA_CLIENT_TOKEN"` @@ -485,6 +486,12 @@ func WithRateLimitMaxBackOff(maxBackoff int64) ConfigSetter { } } +func WithRateLimitThreshold(threshold int32) ConfigSetter { + return func(c *Configuration) { + c.Okta.Client.RateLimit.Threshold = threshold + } +} + func WithAuthorizationMode(authzMode string) ConfigSetter { return func(c *Configuration) { c.Okta.Client.AuthorizationMode = authzMode From 6483eec60eddebd6f66d7fd47586e60bdc79fd00 Mon Sep 17 00:00:00 2001 From: abhishek Date: Fri, 12 Sep 2025 11:59:00 +0530 Subject: [PATCH 2/3] Ratelimit on reaching the threshold Signed-off-by: abhishek --- .generator/templates/client.mustache | 2 +- okta/client.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.generator/templates/client.mustache b/.generator/templates/client.mustache index ffdc410f2..4e7e8d9f7 100644 --- a/.generator/templates/client.mustache +++ b/.generator/templates/client.mustache @@ -1141,7 +1141,7 @@ func (c *APIClient) do(ctx context.Context, req *http.Request) (*http.Response, limit := c.rateLimit c.rateLimitLock.Unlock() // If the remaining requests are less than the threshold percentage of the limit, wait for the max backoff - if limit != nil && limit.Remaining <= int(c.cfg.Okta.Client.RateLimit.Threshold)*limit.Limit/100 { + if limit != nil && limit.Remaining <= limit.Limit-int(c.cfg.Okta.Client.RateLimit.Threshold)*limit.Limit/100 { // less than threshold timer := time.NewTimer(time.Second * time.Duration(c.cfg.Okta.Client.RateLimit.MaxBackoff)) select { case <-ctx.Done(): diff --git a/okta/client.go b/okta/client.go index 2e5880dbc..c0b55e273 100644 --- a/okta/client.go +++ b/okta/client.go @@ -1329,7 +1329,7 @@ func (c *APIClient) do(ctx context.Context, req *http.Request) (*http.Response, limit := c.rateLimit c.rateLimitLock.Unlock() // If the remaining requests are less than the threshold percentage of the limit, wait for the MaxBackoff - if limit != nil && limit.Remaining <= int(c.cfg.Okta.Client.RateLimit.Threshold)*limit.Limit/100 { + if limit != nil && limit.Remaining <= limit.Limit-int(c.cfg.Okta.Client.RateLimit.Threshold)*limit.Limit/100 { // less than threshold timer := time.NewTimer(time.Second * time.Duration(c.cfg.Okta.Client.RateLimit.MaxBackoff)) select { case <-ctx.Done(): From 93aae8ec7d04cb37a160d0a3798293c99f8650cf Mon Sep 17 00:00:00 2001 From: manjunathsc <150641428+manjunathsc@users.noreply.github.com> Date: Fri, 12 Sep 2025 19:08:55 +0530 Subject: [PATCH 3/3] =?UTF-8?q?fix=20=5Fembedded=C2=A0field=20type=20misma?= =?UTF-8?q?tch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- okta/model_policy.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/okta/model_policy.go b/okta/model_policy.go index 08a8781d8..993c803c5 100644 --- a/okta/model_policy.go +++ b/okta/model_policy.go @@ -21,6 +21,7 @@ API version: 2024.06.1 Contact: devex-public@okta.com */ +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. package okta import ( @@ -45,9 +46,9 @@ type Policy struct { Status *string `json:"status,omitempty"` // Specifies whether Okta created the Policy System *bool `json:"system,omitempty"` - // All Okta orgs contain only one IdP Discovery Policy with an immutable default Rule routing to your org's sign-in page. Creating or replacing a policy with `IDP_DISCOVERY` type isn't supported. The following policy types are available with the Okta Identity Engine: `ACCESS_POLICY`, `PROFILE_ENROLLMENT`, `CONTINUOUS_ACCESS`, and `ENTITY_RISK`. The `CONTINUOUS_ACCESS`, and `ENTITY_RISK` policy types are in Early Access (EA). Contact your Okta account team to enable these features. + // All Okta orgs contain only one IdP Discovery Policy with an immutable default Rule routing to your org's sign-in page. Creating or replacing a policy with `IDP_DISCOVERY` type isn't supported. The following policy types are available with the Okta Identity Engine: `ACCESS_POLICY`, `PROFILE_ENROLLMENT`, `CONTINUOUS_ACCESS`, and `ENTITY_RISK`. The `CONTINUOUS_ACCESS`, and `ENTITY_RISK` policy types are in Early Access (EA). Contact your Okta account team to enable these features. Type *string `json:"type,omitempty"` - Embedded map[string]interface{} `json:"_embedded,omitempty"` + Embedded interface{} `json:"_embedded,omitempty"` Links *PolicyLinks `json:"_links,omitempty"` AdditionalProperties map[string]interface{} } @@ -360,21 +361,28 @@ func (o *Policy) SetType(v string) { } // GetEmbedded returns the Embedded field value if set, zero value otherwise. -func (o *Policy) GetEmbedded() map[string]interface{} { +func (o *Policy) GetEmbedded() map[string]map[string]interface{} { if o == nil || o.Embedded == nil { - var ret map[string]interface{} + var ret map[string]map[string]interface{} return ret } - return o.Embedded + if embedded, ok := o.Embedded.(map[string]map[string]interface{}); ok { + return embedded + } + var ret map[string]map[string]interface{} + return ret } // GetEmbeddedOk returns a tuple with the Embedded field value if set, nil otherwise // and a boolean to check if the value has been set. -func (o *Policy) GetEmbeddedOk() (map[string]interface{}, bool) { +func (o *Policy) GetEmbeddedOk() (map[string]map[string]interface{}, bool) { if o == nil || o.Embedded == nil { return nil, false } - return o.Embedded, true + if embedded, ok := o.Embedded.(map[string]map[string]interface{}); ok { + return embedded, true + } + return nil, false } // HasEmbedded returns a boolean if a field has been set. @@ -386,8 +394,8 @@ func (o *Policy) HasEmbedded() bool { return false } -// SetEmbedded gets a reference to the given map[string]interface{} and assigns it to the Embedded field. -func (o *Policy) SetEmbedded(v map[string]interface{}) { +// SetEmbedded gets a reference to the given map[string]map[string]interface{} and assigns it to the Embedded field. +func (o *Policy) SetEmbedded(v map[string]map[string]interface{}) { o.Embedded = v }