MCPcopy Create free account
hub / github.com/erpc/erpc / Authenticate

Method Authenticate

auth/strategy_database.go:122–270  ·  view source on GitHub ↗
(ctx context.Context, req *common.NormalizedRequest, ap *AuthPayload)

Source from the content-addressed store, hash-verified

120}
121
122func (s *DatabaseStrategy) Authenticate(ctx context.Context, req *common.NormalizedRequest, ap *AuthPayload) (*common.User, error) {
123 if ap.Secret == nil {
124 s.recordAuthFailureMetric(req, "missing_secret")
125 return nil, common.NewErrAuthUnauthorized("database", "no secret provided")
126 }
127
128 apiKey := ap.Secret.Value
129 if apiKey == "" {
130 s.recordAuthFailureMetric(req, "empty_secret")
131 return nil, common.NewErrAuthUnauthorized("database", "empty API key")
132 }
133
134 // Check positive cache first if available
135 if s.cache != nil {
136 if cachedUser, found := s.cache.Get(apiKey); found {
137 s.logger.Debug().Str("apiKey", apiKey).Msg("API key found in cache")
138 return cachedUser, nil
139 }
140 s.logger.Debug().Str("apiKey", apiKey).Msg("API key not found in cache")
141 }
142
143 // Negative cache: short-circuit known invalid/disabled keys
144 if s.negCache != nil {
145 if _, found := s.negCache.Get(apiKey); found {
146 s.logger.Debug().Str("apiKey", apiKey).Msg("API key found in negative cache")
147 s.recordAuthFailureMetric(req, "cached_unknown_api_key")
148 return nil, common.NewErrAuthUnauthorized("database", "invalid API key")
149 }
150 }
151
152 // Fail-open fast path. When the connector is in a known-down state and
153 // fail-open is configured, serve the emergency user immediately without
154 // going through singleflight + connector.Get + Error log + metric. This
155 // is what eliminates per-request pressure during a sustained outage
156 // (see DatabaseStrategy struct comment for the incident reference).
157 // One caller per connectorDownProbeInterval still goes through the real
158 // DB path so we eventually notice recovery; everyone else fast-paths.
159 if u := s.tryFastFailOpen(); u != nil {
160 s.recordAuthFailureMetric(req, "db_fail_open_fast_path")
161 return u, nil
162 }
163
164 // Use singleflight to deduplicate concurrent misses per key
165 type authFetchResult struct {
166 user *common.User
167 err error
168 neg bool
169 skipCache bool
170 }
171 v, sfErr, _ := s.sf.Do(apiKey, func() (interface{}, error) {
172 rangeKey := "*"
173 lookupCtx := ctx
174 if s.cfg != nil && s.cfg.MaxWait.Duration() > 0 {
175 var cancel context.CancelFunc
176 lookupCtx, cancel = context.WithTimeout(ctx, s.cfg.MaxWait.Duration())
177 defer cancel()
178 }
179 valueBytes, err := s.getWithRetries(lookupCtx, data.ConnectorMainIndex, apiKey, rangeKey)

Callers

nothing calls this directly

Calls 12

tryFastFailOpenMethod · 0.95
getWithRetriesMethod · 0.95
markConnectorUpMethod · 0.95
isDownSignalMethod · 0.95
markConnectorDownMethod · 0.95
classifyDbErrorMethod · 0.95
buildFailOpenUserMethod · 0.95
HasErrorCodeFunction · 0.92
GetMethod · 0.65
ErrorMethod · 0.65
DurationMethod · 0.45

Tested by

no test coverage detected