mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 13:00:52 +08:00
fix(iflow): streamline authentication callback handling and improve error reporting
This commit is contained in:
@@ -1150,126 +1150,50 @@ func (h *Handler) RequestIFlowToken(c *gin.Context) {
|
|||||||
c.JSON(http.StatusInternalServerError, gin.H{"status": "error", "error": "failed to start callback server"})
|
c.JSON(http.StatusInternalServerError, gin.H{"status": "error", "error": "failed to start callback server"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer stopCallbackForwarder(iflowauth.CallbackPort)
|
|
||||||
fmt.Println("Waiting for authentication...")
|
|
||||||
|
|
||||||
waitFile := filepath.Join(h.cfg.AuthDir, fmt.Sprintf(".oauth-iflow-%s.oauth", state))
|
|
||||||
deadline := time.Now().Add(5 * time.Minute)
|
|
||||||
var resultMap map[string]string
|
|
||||||
for {
|
|
||||||
if time.Now().After(deadline) {
|
|
||||||
oauthStatus[state] = "Authentication failed"
|
|
||||||
fmt.Println("Authentication failed: timeout waiting for callback")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if data, errR := os.ReadFile(waitFile); errR == nil {
|
|
||||||
_ = os.Remove(waitFile)
|
|
||||||
_ = json.Unmarshal(data, &resultMap)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
time.Sleep(500 * time.Millisecond)
|
|
||||||
}
|
|
||||||
|
|
||||||
if errStr := strings.TrimSpace(resultMap["error"]); errStr != "" {
|
|
||||||
oauthStatus[state] = "Authentication failed"
|
|
||||||
fmt.Printf("Authentication failed: %s\n", errStr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if resultState := strings.TrimSpace(resultMap["state"]); resultState != state {
|
|
||||||
oauthStatus[state] = "Authentication failed"
|
|
||||||
fmt.Println("Authentication failed: state mismatch")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
code := strings.TrimSpace(resultMap["code"])
|
|
||||||
if code == "" {
|
|
||||||
oauthStatus[state] = "Authentication failed"
|
|
||||||
fmt.Println("Authentication failed: code missing")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tokenData, errExchange := authSvc.ExchangeCodeForTokens(ctx, code, redirectURI)
|
|
||||||
if errExchange != nil {
|
|
||||||
oauthStatus[state] = "Authentication failed"
|
|
||||||
fmt.Printf("Authentication failed: %v\n", errExchange)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tokenStorage := authSvc.CreateTokenStorage(tokenData)
|
|
||||||
identifier := strings.TrimSpace(tokenStorage.Email)
|
|
||||||
if identifier == "" {
|
|
||||||
identifier = fmt.Sprintf("iflow-%d", time.Now().UnixMilli())
|
|
||||||
tokenStorage.Email = identifier
|
|
||||||
}
|
|
||||||
record := &coreauth.Auth{
|
|
||||||
ID: fmt.Sprintf("iflow-%s.json", identifier),
|
|
||||||
Provider: "iflow",
|
|
||||||
FileName: fmt.Sprintf("iflow-%s.json", identifier),
|
|
||||||
Storage: tokenStorage,
|
|
||||||
Metadata: map[string]any{"email": identifier, "api_key": tokenStorage.APIKey},
|
|
||||||
Attributes: map[string]string{"api_key": tokenStorage.APIKey},
|
|
||||||
}
|
|
||||||
|
|
||||||
savedPath, errSave := h.saveTokenRecord(ctx, record)
|
|
||||||
if errSave != nil {
|
|
||||||
oauthStatus[state] = "Failed to save authentication tokens"
|
|
||||||
log.Fatalf("Failed to save authentication tokens: %v", errSave)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Authentication successful! Token saved to %s\n", savedPath)
|
|
||||||
if tokenStorage.APIKey != "" {
|
|
||||||
fmt.Println("API key obtained and saved")
|
|
||||||
}
|
|
||||||
fmt.Println("You can now use iFlow services through this CLI")
|
|
||||||
delete(oauthStatus, state)
|
|
||||||
}()
|
|
||||||
|
|
||||||
oauthStatus[state] = ""
|
|
||||||
c.JSON(http.StatusOK, gin.H{"status": "ok", "url": authURL, "state": state})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
oauthServer := iflowauth.NewOAuthServer(iflowauth.CallbackPort)
|
|
||||||
if err := oauthServer.Start(); err != nil {
|
|
||||||
oauthStatus[state] = "Failed to start authentication server"
|
|
||||||
log.Errorf("Failed to start iFlow OAuth server: %v", err)
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"status": "error", "error": "failed to start local oauth server"})
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
if isWebUI {
|
||||||
|
defer stopCallbackForwarder(iflowauth.CallbackPort)
|
||||||
|
}
|
||||||
fmt.Println("Waiting for authentication...")
|
fmt.Println("Waiting for authentication...")
|
||||||
defer func() {
|
|
||||||
stopCtx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
waitFile := filepath.Join(h.cfg.AuthDir, fmt.Sprintf(".oauth-iflow-%s.oauth", state))
|
||||||
defer cancel()
|
deadline := time.Now().Add(5 * time.Minute)
|
||||||
if err := oauthServer.Stop(stopCtx); err != nil {
|
var resultMap map[string]string
|
||||||
log.Warnf("Failed to stop iFlow OAuth server: %v", err)
|
for {
|
||||||
|
if time.Now().After(deadline) {
|
||||||
|
oauthStatus[state] = "Authentication failed"
|
||||||
|
fmt.Println("Authentication failed: timeout waiting for callback")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}()
|
if data, errR := os.ReadFile(waitFile); errR == nil {
|
||||||
|
_ = os.Remove(waitFile)
|
||||||
result, err := oauthServer.WaitForCallback(5 * time.Minute)
|
_ = json.Unmarshal(data, &resultMap)
|
||||||
if err != nil {
|
break
|
||||||
oauthStatus[state] = "Authentication failed"
|
}
|
||||||
fmt.Printf("Authentication failed: %v\n", err)
|
time.Sleep(500 * time.Millisecond)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.Error != "" {
|
if errStr := strings.TrimSpace(resultMap["error"]); errStr != "" {
|
||||||
oauthStatus[state] = "Authentication failed"
|
oauthStatus[state] = "Authentication failed"
|
||||||
fmt.Printf("Authentication failed: %s\n", result.Error)
|
fmt.Printf("Authentication failed: %s\n", errStr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if resultState := strings.TrimSpace(resultMap["state"]); resultState != state {
|
||||||
if result.State != state {
|
|
||||||
oauthStatus[state] = "Authentication failed"
|
oauthStatus[state] = "Authentication failed"
|
||||||
fmt.Println("Authentication failed: state mismatch")
|
fmt.Println("Authentication failed: state mismatch")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenData, errExchange := authSvc.ExchangeCodeForTokens(ctx, result.Code, redirectURI)
|
code := strings.TrimSpace(resultMap["code"])
|
||||||
|
if code == "" {
|
||||||
|
oauthStatus[state] = "Authentication failed"
|
||||||
|
fmt.Println("Authentication failed: code missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenData, errExchange := authSvc.ExchangeCodeForTokens(ctx, code, redirectURI)
|
||||||
if errExchange != nil {
|
if errExchange != nil {
|
||||||
oauthStatus[state] = "Authentication failed"
|
oauthStatus[state] = "Authentication failed"
|
||||||
fmt.Printf("Authentication failed: %v\n", errExchange)
|
fmt.Printf("Authentication failed: %v\n", errExchange)
|
||||||
|
|||||||
Reference in New Issue
Block a user