statping/handlers/oauth_keycloak.go

76 lines
2.0 KiB
Go

package handlers
import (
"context"
"encoding/json"
"net/http"
"strings"
"github.com/statping-ng/statping-ng/types/core"
"github.com/statping-ng/statping-ng/types/errors"
"golang.org/x/oauth2"
)
type keycloakUserInfo struct {
Username string `json:"preferred_username"`
Email string `json:"email"`
Groups []string `json:"groups"`
}
func keycloakOAuth(r *http.Request) (*oAuth, error) {
auth := core.App.OAuth
code := r.URL.Query().Get("code")
log.Infof("Keycloak code: %s", code)
if code == "" {
return nil, errors.New("code not found")
}
scopes := strings.Split(auth.KeycloakScopes, ",")
conf := &oauth2.Config{
ClientID: core.App.OAuth.KeycloakClientID,
ClientSecret: core.App.OAuth.KeycloakClientSecret,
Endpoint: oauth2.Endpoint{
AuthURL: auth.KeycloakEndpointAuth,
TokenURL: auth.KeycloakEndpointToken,
},
RedirectURL: core.App.Domain + basePath + "oauth/keycloak",
Scopes: scopes,
}
log.Infof("Keycloak config: %+v", conf)
token, err := conf.Exchange(context.Background(), code)
log.Infof("Keycloak token: %+v", token)
if err != nil {
log.Error("Failed to exchange token: ", err)
return nil, err
}
client := conf.Client(context.Background(), token)
log.Infof("Keycloak client: %+v", client)
resp, err := client.Get(core.App.OAuth.KeycloakEndpointUserinfo)
log.Infof("Keycloak user info URL: %s", core.App.OAuth.KeycloakEndpointUserinfo)
if err != nil {
log.Error("Failed to get user info: ", err)
return nil, err
}
defer resp.Body.Close()
var userInfo struct {
Email string `json:"email"`
Username string `json:"preferred_username"`
Groups []string `json:"groups"`
}
if err := json.NewDecoder(resp.Body).Decode(&userInfo); err != nil {
log.Error("Failed to decode user info: ", err)
return nil, err
}
log.Infof("Keycloak user info: %+v", userInfo)
log.Infof("Keycloak user groups: %+v", userInfo.Groups)
return &oAuth{
Email: userInfo.Email,
Username: userInfo.Username,
Token: token,
Groups: userInfo.Groups,
}, nil
}