package main
import (
"bytes"
"context"
"crypto/rand"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
"time"
)
// TokenResponse represents the OAuth token response
type TokenResponse struct {
Data struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
Scope string `json:"scope"`
TokenType string `json:"token_type"`
} `json:"data"`
}
const BASE_URL = "https://whitebit.com"
const CLIENT_ID = "YOUR_CLIENT_ID"
const CLIENT_SECRET = "YOUR_CLIENT_SECRET"
// Initiate OAuth flow
func initiateOAuthFlowHandler(w http.ResponseWriter, r *http.Request) {
b := make([]byte, 32)
rand.Read(b)
state := base64.RawURLEncoding.EncodeToString(b)
// In production, store state in session
authURL, _ := url.Parse(BASE_URL + "/auth/login")
q := authURL.Query()
q.Set("clientId", CLIENT_ID)
q.Set("state", state)
authURL.RawQuery = q.Encode()
http.Redirect(w, r, authURL.String(), http.StatusFound)
}
// Handle OAuth callback
func oauthCallbackHandler(w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")
state := r.URL.Query().Get("state")
// Verify state here...
token, err := exchangeCodeForToken(r.Context(), code)
if err != nil {
http.Error(w, "Authentication failed", http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "Token received: %s", token.Data.AccessToken)
}
func exchangeCodeForToken(ctx context.Context, code string) (*TokenResponse, error) {
data := url.Values{}
data.Set("client_id", CLIENT_ID)
data.Set("client_secret", CLIENT_SECRET)
data.Set("code", code)
resp, err := http.PostForm(BASE_URL+"/oauth2/token", data)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var tokenResponse TokenResponse
json.NewDecoder(resp.Body).Decode(&tokenResponse)
return &tokenResponse, nil
}