package main import ( "encoding/base64" "encoding/json" "fmt" "os" "strings" bkosmi "github.com/42wim/matterbridge/bridge/kosmi" "github.com/sirupsen/logrus" ) func main() { if len(os.Args) < 3 { fmt.Println("Usage: compare-auth ") fmt.Println("") fmt.Println("This script will:") fmt.Println("1. Get an anonymous token") fmt.Println("2. Get an authenticated token via browser") fmt.Println("3. Decode and compare both JWT tokens") fmt.Println("4. Show what's different") os.Exit(1) } email := os.Args[1] password := os.Args[2] // Set up logging log := logrus.New() log.SetLevel(logrus.InfoLevel) entry := logrus.NewEntry(log) fmt.Println(strings.Repeat("=", 80)) fmt.Println("COMPARING ANONYMOUS vs AUTHENTICATED TOKENS") fmt.Println(strings.Repeat("=", 80)) fmt.Println() // Get anonymous token fmt.Println("📝 Step 1: Getting anonymous token...") client := bkosmi.NewGraphQLWSClient("https://app.kosmi.io/room/@test", "@test", entry) anonToken, err := client.GetAnonymousTokenForTest() if err != nil { fmt.Printf("❌ Failed to get anonymous token: %v\n", err) os.Exit(1) } fmt.Printf("✅ Anonymous token obtained (length: %d)\n", len(anonToken)) fmt.Println() // Get authenticated token fmt.Println("📝 Step 2: Getting authenticated token via browser...") browserAuth := bkosmi.NewBrowserAuthManager(email, password, entry) authToken, err := browserAuth.GetToken() if err != nil { fmt.Printf("❌ Failed to get authenticated token: %v\n", err) os.Exit(1) } fmt.Printf("✅ Authenticated token obtained (length: %d)\n", len(authToken)) fmt.Println() // Decode both tokens fmt.Println("📝 Step 3: Decoding JWT tokens...") fmt.Println() anonClaims := decodeJWT(anonToken) authClaims := decodeJWT(authToken) fmt.Println("ANONYMOUS TOKEN:") fmt.Println(strings.Repeat("=", 80)) printClaims(anonClaims) fmt.Println() fmt.Println("AUTHENTICATED TOKEN:") fmt.Println(strings.Repeat("=", 80)) printClaims(authClaims) fmt.Println() // Compare fmt.Println("DIFFERENCES:") fmt.Println(strings.Repeat("=", 80)) compareClaims(anonClaims, authClaims) fmt.Println() fmt.Println("📝 Step 4: Testing connection with both tokens...") fmt.Println() // We can't easily test the actual connection here, but we've shown the token differences fmt.Println("✅ Analysis complete!") fmt.Println() fmt.Println("RECOMMENDATION:") fmt.Println("If the authenticated token has a different 'sub' (user ID), that user") fmt.Println("might not have the same permissions or profile as the anonymous user.") } func decodeJWT(token string) map[string]interface{} { parts := strings.Split(token, ".") if len(parts) != 3 { return map[string]interface{}{"error": "invalid JWT format"} } // Decode payload payload := parts[1] // Add padding if needed switch len(payload) % 4 { case 2: payload += "==" case 3: payload += "=" } // Replace URL-safe characters payload = strings.ReplaceAll(payload, "-", "+") payload = strings.ReplaceAll(payload, "_", "/") decoded, err := base64.StdEncoding.DecodeString(payload) if err != nil { return map[string]interface{}{"error": fmt.Sprintf("decode error: %v", err)} } var claims map[string]interface{} if err := json.Unmarshal(decoded, &claims); err != nil { return map[string]interface{}{"error": fmt.Sprintf("parse error: %v", err)} } return claims } func printClaims(claims map[string]interface{}) { keys := []string{"sub", "aud", "iss", "typ", "iat", "exp", "nbf", "jti"} for _, key := range keys { if val, ok := claims[key]; ok { fmt.Printf(" %-10s: %v\n", key, val) } } } func compareClaims(anon, auth map[string]interface{}) { allKeys := make(map[string]bool) for k := range anon { allKeys[k] = true } for k := range auth { allKeys[k] = true } different := false for key := range allKeys { anonVal := anon[key] authVal := auth[key] if fmt.Sprintf("%v", anonVal) != fmt.Sprintf("%v", authVal) { different = true fmt.Printf(" %-10s: ANON=%v AUTH=%v\n", key, anonVal, authVal) } } if !different { fmt.Println(" (No differences found - tokens are essentially the same)") } }