/
config_sasl_oauthbearer.go
73 lines (59 loc) · 2 KB
/
config_sasl_oauthbearer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package kafka
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
)
type OAuthBearerConfig struct {
TokenEndpoint string `koanf:"tokenEndpoint"`
ClientID string `koanf:"clientId"`
ClientSecret string `koanf:"clientSecret"`
Scope string `koanf:"scope"`
}
func (c *OAuthBearerConfig) Validate() error {
if c.TokenEndpoint == "" {
return fmt.Errorf("OAuthBearer token endpoint is not specified")
}
if c.ClientID == "" || c.ClientSecret == "" {
return fmt.Errorf("OAuthBearer client credentials are not specified")
}
return nil
}
// same as AcquireToken in Console https://github.com/redpanda-data/console/blob/master/backend/pkg/config/kafka_sasl_oauth.go#L56
func (c *OAuthBearerConfig) getToken(ctx context.Context) (string, error) {
authHeaderValue := base64.StdEncoding.EncodeToString([]byte(c.ClientID + ":" + c.ClientSecret))
queryParams := url.Values{
"grant_type": []string{"client_credentials"},
"scope": []string{c.Scope},
}
req, err := http.NewRequestWithContext(ctx, "POST", c.TokenEndpoint, strings.NewReader(queryParams.Encode()))
if err != nil {
return "", fmt.Errorf("failed to create HTTP request: %w", err)
}
req.URL.RawQuery = queryParams.Encode()
req.Header.Set("Authorization", "Basic "+authHeaderValue)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("HTTP request failed: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("token request failed with status code %d", resp.StatusCode)
}
var tokenResponse map[string]interface{}
decoder := json.NewDecoder(resp.Body)
if err := decoder.Decode(&tokenResponse); err != nil {
return "", fmt.Errorf("failed to parse token response: %w", err)
}
accessToken, ok := tokenResponse["access_token"].(string)
if !ok {
return "", fmt.Errorf("access_token not found in token response")
}
return accessToken, nil
}