mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-10-07 08:09:48 +08:00
fix(meta): require OAuth storage for DCA tokens and reject them in config meta-api-key
This commit is contained in:
@@ -384,22 +384,20 @@ func (h *Handler) resolveMetaToken(ctx context.Context, auth *coreauth.Auth, req
|
||||
}
|
||||
|
||||
var dcaToken string
|
||||
if auth.Metadata != nil {
|
||||
if d, ok := auth.Metadata["dca_token"].(string); ok && strings.TrimSpace(d) != "" {
|
||||
dcaToken = strings.TrimSpace(d)
|
||||
} else if t, ok := auth.Metadata["access_token"].(string); ok && strings.HasPrefix(strings.TrimSpace(t), "dca:") {
|
||||
dcaToken = strings.TrimSpace(t)
|
||||
} else if k, ok := auth.Metadata["api_key"].(string); ok && strings.HasPrefix(strings.TrimSpace(k), "dca:") {
|
||||
dcaToken = strings.TrimSpace(k)
|
||||
if !coreauth.IsConfigAPIKeyAuth(auth) {
|
||||
if auth.Metadata != nil {
|
||||
if d, ok := auth.Metadata["dca_token"].(string); ok && strings.TrimSpace(d) != "" {
|
||||
dcaToken = strings.TrimSpace(d)
|
||||
} else if t, ok := auth.Metadata["access_token"].(string); ok && strings.HasPrefix(strings.TrimSpace(t), "dca:") {
|
||||
dcaToken = strings.TrimSpace(t)
|
||||
}
|
||||
}
|
||||
}
|
||||
if dcaToken == "" && auth.Attributes != nil {
|
||||
if d := strings.TrimSpace(auth.Attributes["dca_token"]); d != "" {
|
||||
dcaToken = d
|
||||
} else if t := strings.TrimSpace(auth.Attributes["access_token"]); strings.HasPrefix(t, "dca:") {
|
||||
dcaToken = t
|
||||
} else if k := strings.TrimSpace(auth.Attributes["api_key"]); strings.HasPrefix(k, "dca:") {
|
||||
dcaToken = k
|
||||
if dcaToken == "" && auth.Attributes != nil {
|
||||
if d := strings.TrimSpace(auth.Attributes["dca_token"]); d != "" {
|
||||
dcaToken = d
|
||||
} else if t := strings.TrimSpace(auth.Attributes["access_token"]); strings.HasPrefix(t, "dca:") {
|
||||
dcaToken = t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ func TestMetaConfigDropsUnusableKeys(t *testing.T) {
|
||||
- base-url: "https://api.meta.ai/v1"
|
||||
- headers: {X-Trace: placeholder}
|
||||
- api-key: " LLM|valid "
|
||||
- api-key: "dca:recoverable"
|
||||
- api-key: "dca:requires-oauth-storage"
|
||||
`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(cfg.MetaKey) != 2 {
|
||||
t.Fatalf("got %d keys, want only the two usable credentials", len(cfg.MetaKey))
|
||||
if len(cfg.MetaKey) != 1 {
|
||||
t.Fatalf("got %d keys, want only the 1 valid API key (DCA tokens require OAuth storage)", len(cfg.MetaKey))
|
||||
}
|
||||
if cfg.MetaKey[0].APIKey != "LLM|valid" || cfg.MetaKey[0].BaseURL != "https://api.meta.ai/v1" {
|
||||
t.Fatalf("valid key not normalized: %#v", cfg.MetaKey[0])
|
||||
|
||||
@@ -210,8 +210,8 @@ func sanitizeMetaKeyEntries(entries []MetaKey) []MetaKey {
|
||||
for i := range entries {
|
||||
e := entries[i]
|
||||
e.APIKey = strings.TrimSpace(e.APIKey)
|
||||
// The native Meta executor requires an API key or a DCA token in this field.
|
||||
if e.APIKey == "" {
|
||||
// meta-api-key requires a valid API key. DCA tokens require OAuth storage (auths/*.json).
|
||||
if e.APIKey == "" || strings.HasPrefix(e.APIKey, "dca:") {
|
||||
continue
|
||||
}
|
||||
e.Prefix = normalizeModelPrefix(e.Prefix)
|
||||
|
||||
@@ -254,7 +254,7 @@ func (e *MetaExecutor) Refresh(ctx context.Context, auth *cliproxyauth.Auth) (*c
|
||||
|
||||
// ShouldPrepareRequestAuth reports true when a Meta auth has a DCA token but no usable API key.
|
||||
func (e *MetaExecutor) ShouldPrepareRequestAuth(auth *cliproxyauth.Auth) bool {
|
||||
if auth == nil {
|
||||
if auth == nil || cliproxyauth.IsConfigAPIKeyAuth(auth) {
|
||||
return false
|
||||
}
|
||||
_, token := metaCreds(auth)
|
||||
@@ -291,6 +291,12 @@ func (e *MetaExecutor) ensureAuth(ctx context.Context, auth *cliproxyauth.Auth)
|
||||
}
|
||||
|
||||
if token == "" {
|
||||
if cliproxyauth.IsConfigAPIKeyAuth(auth) {
|
||||
return nil, statusErr{
|
||||
code: http.StatusUnauthorized,
|
||||
msg: "meta executor: meta-api-key requires a valid API key (DCA tokens require OAuth storage)",
|
||||
}
|
||||
}
|
||||
return nil, statusErr{
|
||||
code: http.StatusUnauthorized,
|
||||
msg: "meta executor: missing API key or access token",
|
||||
@@ -326,7 +332,7 @@ func (e *MetaExecutor) enrichAuth(auth *cliproxyauth.Auth) *cliproxyauth.Auth {
|
||||
}
|
||||
|
||||
func extractDCAToken(a *cliproxyauth.Auth) string {
|
||||
if a == nil {
|
||||
if a == nil || cliproxyauth.IsConfigAPIKeyAuth(a) {
|
||||
return ""
|
||||
}
|
||||
if a.Attributes != nil {
|
||||
@@ -336,9 +342,6 @@ func extractDCAToken(a *cliproxyauth.Auth) string {
|
||||
if t := strings.TrimSpace(a.Attributes["access_token"]); strings.HasPrefix(t, "dca:") {
|
||||
return t
|
||||
}
|
||||
if k := strings.TrimSpace(a.Attributes["api_key"]); strings.HasPrefix(k, "dca:") {
|
||||
return k
|
||||
}
|
||||
}
|
||||
if a.Metadata != nil {
|
||||
if d, ok := a.Metadata["dca_token"].(string); ok && strings.TrimSpace(d) != "" {
|
||||
@@ -347,9 +350,6 @@ func extractDCAToken(a *cliproxyauth.Auth) string {
|
||||
if t, ok := a.Metadata["access_token"].(string); ok && strings.HasPrefix(strings.TrimSpace(t), "dca:") {
|
||||
return strings.TrimSpace(t)
|
||||
}
|
||||
if k, ok := a.Metadata["api_key"].(string); ok && strings.HasPrefix(strings.TrimSpace(k), "dca:") {
|
||||
return strings.TrimSpace(k)
|
||||
}
|
||||
}
|
||||
if a.Storage != nil {
|
||||
if ms, ok := a.Storage.(*metaauth.MetaTokenStorage); ok && ms != nil {
|
||||
|
||||
@@ -572,6 +572,17 @@ func TestMetaExecutor_RequestAuthPreparer(t *testing.T) {
|
||||
t.Errorf("ShouldPrepareRequestAuth should be false when dca_token is missing")
|
||||
}
|
||||
|
||||
authConfigDCA := &cliproxyauth.Auth{
|
||||
Provider: "meta",
|
||||
Attributes: map[string]string{
|
||||
"api_key": "dca:invalid-for-config",
|
||||
cliproxyauth.AttributeSource: "config:meta[0]",
|
||||
},
|
||||
}
|
||||
if exec.ShouldPrepareRequestAuth(authConfigDCA) {
|
||||
t.Errorf("ShouldPrepareRequestAuth should be false for config API key auths")
|
||||
}
|
||||
|
||||
authDCAOnly := &cliproxyauth.Auth{
|
||||
ID: "meta-prep-test",
|
||||
Provider: "meta",
|
||||
|
||||
Reference in New Issue
Block a user