auth/auth.go
2024-09-13 23:41:29 +02:00

148 lines
3.5 KiB
Go

package kekskurseauth
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
)
type Auth struct {
authConfig AuthConfig
clientConfig ClientConfig
}
type Token struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiredIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
CreatedAt time.Time
}
func NewAuthWithConfig(config ClientConfig, authConfig AuthConfig) (Auth, error) {
a := Auth{}
a.authConfig = authConfig
a.clientConfig = config
return a, nil
}
func NewAuthWithConfigurationURL(config ClientConfig, url string) (Auth, error) {
a := Auth{}
a.clientConfig = config
authConfig := AuthConfig{}
res, err := http.Get(url)
if err != nil {
return Auth{}, fmt.Errorf("%w: %q", ErrCantGetConfiguratorData, err)
}
defer res.Body.Close()
bodyContent, err := io.ReadAll(res.Body)
if err != nil {
return Auth{}, fmt.Errorf("%w: %q", ErrCantGetConfiguratorData, err)
}
err = json.Unmarshal(bodyContent, &authConfig)
if err != nil {
return Auth{}, fmt.Errorf("%w: %q", ErrCantGetConfiguratorData, err)
}
a.authConfig = authConfig
return a, nil
}
func (a Auth) GetAuthorizationURL(state string) (string, error) {
if a.authConfig.AuthorizationEndpoint == "" {
return "", fmt.Errorf("%w: %s", ErrCantGetAuthorizationURL, "AuthorizationEndpoint in config is empty")
}
if a.clientConfig.ClientID == "" {
return "", fmt.Errorf("%w: %s", ErrCantGetAuthorizationURL, "clientid in config is empty")
}
url, err := url.Parse(a.authConfig.AuthorizationEndpoint)
if err != nil {
return "", fmt.Errorf("%w: %q", ErrCantGetAuthorizationURL, err)
}
values := url.Query()
values.Set("client_id", a.clientConfig.ClientID)
if a.clientConfig.RedirectURL != "" {
values.Set("redirect_uri", a.clientConfig.RedirectURL)
}
if len(a.clientConfig.Scope) > 0 {
values.Set("scope", strings.Join(a.clientConfig.Scope, "+"))
}
if state != "" {
values.Set("state", state)
}
values.Set("response_type", "code")
url.RawQuery = values.Encode()
return url.String(), nil
}
func (a Auth) GetTokenFromCode(code string) (Token, error) {
form := url.Values{}
form.Add("grant_type", "authorization_code")
form.Add("code", code)
req, err := http.NewRequest("POST", a.authConfig.TokenEndpoint, strings.NewReader(form.Encode()))
if err != nil {
return Token{}, fmt.Errorf("%w: %q", ErrCantCreateTokenRequests, err)
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.SetBasicAuth(a.clientConfig.ClientID, a.clientConfig.ClientSecret)
hc := http.Client{}
resp, err := hc.Do(req)
if err != nil {
return Token{}, fmt.Errorf("%w: %q", ErrCantSendRequestsForToken, err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return Token{}, fmt.Errorf("%w: %q", ErrCantSendRequestsForToken, err)
}
fmt.Println(string(body))
fmt.Println(resp.StatusCode)
if resp.StatusCode != 200 {
var er struct {
Error string `json:"error"`
ErrorDescription string `json:"error_description"`
}
err = json.Unmarshal(body, &er)
if err != nil {
return Token{}, fmt.Errorf("%w: %s", ErrWrongResponseFromServer, string(body))
}
if er.ErrorDescription != "" {
return Token{}, fmt.Errorf("%w: %s", ErrWrongResponseFromServer, er.ErrorDescription)
}
return Token{}, fmt.Errorf("%w: %s", ErrWrongResponseFromServer, string(body))
}
t := Token{}
t.CreatedAt = time.Now()
err = json.Unmarshal(body, &t)
if err != nil {
return Token{}, fmt.Errorf("%w: %q", ErrCantGetTokenForCode, err)
}
return t, nil
}