feat(auth): add OAuth and token-based login for OpenAI and Anthropic
Add `picoclaw auth` CLI command supporting: - OpenAI OAuth2 (PKCE + browser callback or device code flow) - Anthropic paste-token flow - Token storage at ~/.picoclaw/auth.json with 0600 permissions - Auto-refresh for expired OAuth tokens in provider Closes #18 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
43
pkg/auth/token.go
Normal file
43
pkg/auth/token.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func LoginPasteToken(provider string, r io.Reader) (*AuthCredential, error) {
|
||||
fmt.Printf("Paste your API key or session token from %s:\n", providerDisplayName(provider))
|
||||
fmt.Print("> ")
|
||||
|
||||
scanner := bufio.NewScanner(r)
|
||||
if !scanner.Scan() {
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("reading token: %w", err)
|
||||
}
|
||||
return nil, fmt.Errorf("no input received")
|
||||
}
|
||||
|
||||
token := strings.TrimSpace(scanner.Text())
|
||||
if token == "" {
|
||||
return nil, fmt.Errorf("token cannot be empty")
|
||||
}
|
||||
|
||||
return &AuthCredential{
|
||||
AccessToken: token,
|
||||
Provider: provider,
|
||||
AuthMethod: "token",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func providerDisplayName(provider string) string {
|
||||
switch provider {
|
||||
case "anthropic":
|
||||
return "console.anthropic.com"
|
||||
case "openai":
|
||||
return "platform.openai.com"
|
||||
default:
|
||||
return provider
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user