Files
api-antrian-operasi/internal/domain/keycloak/service.go
2026-02-19 14:13:25 +07:00

62 lines
1.6 KiB
Go

package keycloak
import (
"antrian-operasi/internal/config"
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"strings"
)
type IKeycloakService interface {
FetchTokenUsingRefreshToken(c context.Context, refreshToken string) (*TokenResponse, error)
}
type KeycloakService struct {
config config.KeycloakConfig
}
func NewKeycloakService(cfg config.KeycloakConfig) IKeycloakService {
return KeycloakService{cfg}
}
func (s KeycloakService) FetchTokenUsingRefreshToken(c context.Context, refreshToken string) (*TokenResponse, error) {
refreshTokenUrl := s.config.BaseUrl + "/realms/" + s.config.Realm + "/protocol/openid-connect/token"
bodyRequest := url.Values{}
bodyRequest.Set("grant_type", "refresh_token")
bodyRequest.Set("client_id", s.config.Audience)
bodyRequest.Set("client_secret", s.config.SecretKey)
bodyRequest.Set("refresh_token", refreshToken)
client := &http.Client{}
req, err := http.NewRequestWithContext(c, http.MethodPost, refreshTokenUrl, strings.NewReader(bodyRequest.Encode()))
if err != nil {
log.Printf("error request token %s", err)
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
log.Printf("error response %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
var errResp TokenErrorResponse
json.NewDecoder(resp.Body).Decode(&errResp)
return nil, fmt.Errorf("Keycloak error : %s - %s", errResp.Error, errResp.ErrorDescription)
}
var tokenResp TokenResponse
err = json.NewDecoder(resp.Body).Decode(&tokenResp)
if err != nil {
return nil, err
}
return &tokenResp, nil
}