Files
new-api/examples/oauth2_test_client.go
2025-09-08 12:09:26 +08:00

126 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"context"
"fmt"
"io"
"log"
"net/http"
"golang.org/x/oauth2"
"golang.org/x/oauth2/clientcredentials"
)
func main() {
// 测试 Client Credentials 流程
testClientCredentials()
// 测试 Authorization Code + PKCE 流程(需要浏览器交互)
// testAuthorizationCode()
}
// testClientCredentials 测试服务对服务认证
func testClientCredentials() {
fmt.Println("=== Testing Client Credentials Flow ===")
cfg := clientcredentials.Config{
ClientID: "client_demo123456789", // 需要先创建客户端
ClientSecret: "demo_secret_32_chars_long_123456",
TokenURL: "http://127.0.0.1:8080/api/oauth/token",
Scopes: []string{"api:read", "api:write"},
EndpointParams: map[string][]string{
"audience": {"api://new-api"},
},
}
// 创建HTTP客户端
httpClient := cfg.Client(context.Background())
// 调用受保护的API
resp, err := httpClient.Get("http://127.0.0.1:8080/api/status")
if err != nil {
log.Printf("Request failed: %v", err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Printf("Failed to read response: %v", err)
return
}
fmt.Printf("Status: %s\n", resp.Status)
fmt.Printf("Response: %s\n", string(body))
}
// testAuthorizationCode 测试授权码流程
func testAuthorizationCode() {
fmt.Println("=== Testing Authorization Code + PKCE Flow ===")
conf := oauth2.Config{
ClientID: "client_web123456789", // Web客户端
ClientSecret: "web_secret_32_chars_long_123456",
RedirectURL: "http://localhost:9999/callback",
Scopes: []string{"api:read", "api:write"},
Endpoint: oauth2.Endpoint{
AuthURL: "http://127.0.0.1:8080/api/oauth/authorize",
TokenURL: "http://127.0.0.1:8080/api/oauth/token",
},
}
// 生成PKCE参数
codeVerifier := oauth2.GenerateVerifier()
// 构建授权URL
url := conf.AuthCodeURL(
"random-state-string",
oauth2.S256ChallengeOption(codeVerifier),
oauth2.SetAuthURLParam("audience", "api://new-api"),
)
fmt.Printf("Visit this URL to authorize:\n%s\n\n", url)
fmt.Printf("After authorization, you'll get a code. Use it to exchange for tokens.\n")
// 在实际应用中这里需要启动一个HTTP服务器来接收回调
// 或者手动输入从回调URL中获取的授权码
fmt.Print("Enter the authorization code: ")
var code string
fmt.Scanln(&code)
if code != "" {
// 交换令牌
token, err := conf.Exchange(
context.Background(),
code,
oauth2.VerifierOption(codeVerifier),
)
if err != nil {
log.Printf("Token exchange failed: %v", err)
return
}
fmt.Printf("Access Token: %s\n", token.AccessToken)
fmt.Printf("Token Type: %s\n", token.TokenType)
fmt.Printf("Expires In: %v\n", token.Expiry)
// 使用令牌调用API
client := conf.Client(context.Background(), token)
resp, err := client.Get("http://127.0.0.1:8080/api/status")
if err != nil {
log.Printf("API request failed: %v", err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Printf("Failed to read response: %v", err)
return
}
fmt.Printf("API Response: %s\n", string(body))
}
}