package auth import ( "context" "fmt" "os" "time" "golang.org/x/oauth2" "golang.org/x/oauth2/google" "google.golang.org/api/healthcare/v1" "google.golang.org/api/option" ) // GoogleClient handles authentication with Google APIs type GoogleClient struct { credentialsPath string tokenSource oauth2.TokenSource } // NewGoogleClient creates a new Google authentication client func NewGoogleClient(credentialsPath string) (*GoogleClient, error) { client := &GoogleClient{ credentialsPath: credentialsPath, } // Initialize on creation to validate credentials ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() // Try reading the credentials file credBytes, err := os.ReadFile(credentialsPath) if err != nil { return nil, fmt.Errorf("failed to read credentials file: %w", err) } // Create credentials from the JSON key file creds, err := google.CredentialsFromJSON(ctx, credBytes, healthcare.CloudPlatformScope) if err != nil { return nil, fmt.Errorf("failed to initialize Google client: %w", err) } client.tokenSource = creds.TokenSource return client, nil } // GetAccessToken returns a valid access token for Google APIs func (c *GoogleClient) GetAccessToken() (string, error) { _, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() token, err := c.tokenSource.Token() if err != nil { return "", fmt.Errorf("failed to get access token: %w", err) } return token.AccessToken, nil } // GetHealthcareClient returns a configured Healthcare API client func (c *GoogleClient) GetHealthcareClient(ctx context.Context) (*healthcare.Service, error) { opts := []option.ClientOption{ option.WithCredentialsFile(c.credentialsPath), option.WithScopes(healthcare.CloudPlatformScope), } return healthcare.NewService(ctx, opts...) }