package mock import ( "context" "encoding/json" "io" "net/http" "strings" "golang.org/x/oauth2" "base/internal/pkg/oauth/types" ) type client struct { oauthConfig *oauth2.Config userinfoURL string } // New creates a mock OAuth client that uses a local mock OAuth server. // Use for local development when real Google/GitHub credentials are not available. func New(config oauth2.Config, baseURL string) types.Oauth { baseURL = strings.TrimSuffix(baseURL, "/") oauthConfig := &oauth2.Config{ ClientID: config.ClientID, ClientSecret: config.ClientSecret, RedirectURL: config.RedirectURL, Scopes: config.Scopes, Endpoint: oauth2.Endpoint{ AuthURL: baseURL + "/authorize", TokenURL: baseURL + "/token", }, } return &client{ oauthConfig: oauthConfig, userinfoURL: baseURL + "/userinfo", } } func (c *client) GetConsentAuthUrl(ctx context.Context, state string) string { return c.oauthConfig.AuthCodeURL(state, oauth2.AccessTypeOffline) } func (c *client) ExchangeCodeWithToken(ctx context.Context, code string) (*types.Token, error) { exchange, err := c.oauthConfig.Exchange(ctx, code, oauth2.AccessTypeOffline) if err != nil { return nil, err } token, err := c.oauthConfig.TokenSource(ctx, exchange).Token() if err != nil { return nil, err } return &types.Token{ AccessToken: token.AccessToken, TokenType: token.TokenType, RefreshToken: token.RefreshToken, ExpiresIn: token.ExpiresIn, }, nil } func (c *client) GetUserInfo(ctx context.Context, accessToken, _ string) (types.UserInfo, error) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.userinfoURL, nil) if err != nil { return nil, err } req.Header.Set("Authorization", "Bearer "+accessToken) resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { return nil, err } var user UserInfo if err := json.Unmarshal(data, &user); err != nil { return nil, err } return &user, nil }