feature:Save OIDC setting in DB (TODO: support multiple profile)

This commit is contained in:
KaySar12 2024-09-30 12:12:46 +07:00
parent 7c56d5865c
commit f89d096bc2
7 changed files with 102 additions and 16 deletions

2
.vscode/launch.json vendored
View File

@ -6,7 +6,7 @@
"type": "go",
"debugAdapter": "dlv-dap",
"request": "launch",
"port": 39337,
"port": 36633,
"host": "127.0.0.1",
"mode": "exec",
"program": "${workspaceFolder}/dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service"

2
dist/metadata.json vendored
View File

@ -1 +1 @@
{"project_name":"casaos-user-service","tag":"v1.0.0","previous_tag":"","version":"1.0.1","commit":"e360248157caa396765f4c7db5e5e5c65240059a","date":"2024-09-25T10:52:32.08272657+07:00","runtime":{"goos":"linux","goarch":"amd64"}}
{"project_name":"casaos-user-service","tag":"v1.0.0","previous_tag":"","version":"1.0.1","commit":"7c56d5865c9829a6af7fbd6c16a87b3266e9098a","date":"2024-09-30T12:02:33.51552871+07:00","runtime":{"goos":"linux","goarch":"amd64"}}

View File

@ -41,6 +41,8 @@ func InitRouter() *gin.Engine {
r.POST("/v1/users/oidc/validateToken", v1.OIDCValidateToken)
r.POST("/v1/users/oidc/logout", v1.OIDCLogout)
r.GET("/v1/users/oidc/health", v1.OIDCHealthCheck)
r.GET("/v1/users/oidc/settings", v1.GetOIDCSettings)
r.POST("/v1/users/oidc/saveSettings", v1.SaveOIDCSettings)
v1Group := r.Group("/v1")
v1Group.Use(jwt.JWT(

View File

@ -51,10 +51,20 @@ var (
clientSecret = "PE05fcDP4qESUmyZ1TNYpZNBxRPq70VpFI81vehsoJ6WhGz5yPXMljrFrOdMRdRhrYmF03fHWTZHgO9ZdNENrLN13BzL8CAgtEkTsyjXfgx9GvISheIjYfpSfvo219fL"
authURL = "http://accessmanager.local/application/o/nextzenos-oidc/"
//authURL = "http://10.0.0.26:9000/application/o/nextzenos-oidc/"
//callbackURL = "http://nextzenos.local/v1/users/oidc/callback"
callbackURL = "http://172.20.60.244:8080/v1/users/oidc/callback"
callbackURL = "http://nextzenos.local/v1/users/oidc/callback"
//callbackURL = "http://172.20.60.244:8080/v1/users/oidc/callback"
)
type OIDCSetting struct {
Settings struct {
ClientID string `json:"clientId"`
ClientSecret string `json:"clientSecret"`
Issuer string `json:"issuer"`
AuthURL string `json:"authUrl"`
CallbackURL string `json:"callbackUrl"`
} `json:"settings"`
}
// @Summary register user
// @Router /user/register/ [post]
func PostUserRegister(c *gin.Context) {
@ -246,7 +256,7 @@ func CheckOIDCInit() gin.HandlerFunc {
return func(c *gin.Context) {
if !oidcInit {
log.Println("Provider is Offline")
c.JSON(http.StatusServiceUnavailable, model.Result{Success: http.StatusProxyAuthRequired, Message: "Authentik Server is Offline"})
c.JSON(http.StatusServiceUnavailable, model.Result{Success: common_err.OIDC_OFFLINE, Message: "Authentik Server is Offline"})
return
}
c.Next()
@ -255,6 +265,14 @@ func CheckOIDCInit() gin.HandlerFunc {
// Use an init function to initialize the oauth2Config variable.
func OIDC() error {
authentik, err := service.MyService.Authentik().GetSettings()
if (authentik != model2.AuthentikCredentialsDBModel{} && err == nil) {
clientID = authentik.ClientID
clientSecret = authentik.ClientSecret
authServer = authentik.Issuer
authURL = authentik.AuthUrl
callbackURL = authentik.CallbackUrl
}
ctx := context.Background()
provider, err := oidc.NewProvider(ctx, authURL)
if err != nil {
@ -270,6 +288,24 @@ func OIDC() error {
}
return nil
}
func GetOIDCSettings(c *gin.Context) {
authentik, err := service.MyService.Authentik().GetSettings()
if err != nil {
c.JSON(common_err.SERVICE_ERROR,
model.Result{
Success: common_err.SERVICE_ERROR,
Message: common_err.GetMsg(common_err.SERVICE_ERROR),
})
return
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: authentik,
})
return
}
func OIDCLogin(c *gin.Context) {
json := make(map[string]string)
c.ShouldBind(&json)
@ -285,6 +321,30 @@ func OIDCLogin(c *gin.Context) {
Data: oauth2Config.AuthCodeURL(state),
})
}
func SaveOIDCSettings(c *gin.Context) {
var oidcSetting OIDCSetting
var authentik model2.AuthentikCredentialsDBModel
c.ShouldBind(&oidcSetting)
authentik.ClientID = oidcSetting.Settings.ClientID
authentik.ClientSecret = oidcSetting.Settings.ClientSecret
authentik.Issuer = oidcSetting.Settings.Issuer
authentik.AuthUrl = oidcSetting.Settings.AuthURL
authentik.CallbackUrl = oidcSetting.Settings.CallbackURL
var result, err = service.MyService.Authentik().UpdateSettings(authentik)
if err != nil {
c.JSON(common_err.SERVICE_ERROR,
model.Result{
Success: common_err.SERVICE_ERROR,
Message: common_err.GetMsg(common_err.SERVICE_ERROR),
})
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: result,
})
}
func OIDCCallback(c *gin.Context) {
w := c.Writer
r := c.Request

View File

@ -16,9 +16,9 @@ import (
type AuthentikService interface {
GetUserInfo(accessToken string, baseURL string) (model2.AuthentikUser, error)
GetUserApp(accessToken string, baseURL string) (model2.AuthentikApplication, error)
CreateCredential(m model2.AuthentikCredentialsDBModel) model2.AuthentikCredentialsDBModel
UpdateCredential(m model2.AuthentikCredentialsDBModel) model2.AuthentikCredentialsDBModel
GetCredential(id int) model2.AuthentikCredentialsDBModel
CreateSettings(m model2.AuthentikCredentialsDBModel) model2.AuthentikCredentialsDBModel
UpdateSettings(m model2.AuthentikCredentialsDBModel) (model2.AuthentikCredentialsDBModel, error)
GetSettings() (model2.AuthentikCredentialsDBModel, error)
ValidateToken(clientId string, clientSecret string, accessToken string, baseURL string) (model2.AuthentikToken, error)
HealthCheck(baseURL string) (string, error)
}
@ -31,18 +31,40 @@ var (
APICorePrefix = "/api/v3/core"
)
func (a *authentikService) CreateCredential(m model2.AuthentikCredentialsDBModel) model2.AuthentikCredentialsDBModel {
func (a *authentikService) CreateSettings(m model2.AuthentikCredentialsDBModel) model2.AuthentikCredentialsDBModel {
a.db.Create(&m)
return m
}
func (a *authentikService) UpdateCredential(m model2.AuthentikCredentialsDBModel) model2.AuthentikCredentialsDBModel {
a.db.Model(&m).Where("id = ?", m.Id).Updates(m)
return m
func (a *authentikService) UpdateSettings(m model2.AuthentikCredentialsDBModel) (model2.AuthentikCredentialsDBModel, error) {
// Find the first matching record
var existing model2.AuthentikCredentialsDBModel
result := a.db.First(&existing)
if result.Error != nil {
return existing, result.Error
}
// Update the existing record
existing.ClientID = m.ClientID
existing.ClientSecret = m.ClientSecret
existing.Issuer = m.Issuer
existing.AuthUrl = m.AuthUrl
existing.CallbackUrl = m.CallbackUrl
// Save the updated record
result = a.db.Save(&existing)
if result.Error != nil {
return existing, result.Error
}
return existing, nil
}
func (a *authentikService) GetCredential(id int) model2.AuthentikCredentialsDBModel {
func (a *authentikService) GetSettings() (model2.AuthentikCredentialsDBModel, error) {
var m model2.AuthentikCredentialsDBModel
a.db.Limit(1).Where("id = ?", id).First(&m)
return m
result := a.db.First(&m)
if result.Error != nil {
return model2.AuthentikCredentialsDBModel{}, result.Error
}
return m, nil
}
func (a *authentikService) HealthCheck(baseURL string) (string, error) {
// Check health/live first

View File

@ -7,7 +7,9 @@ type AuthentikCredentialsDBModel struct {
Id int `gorm:"column:id;primary_key" json:"id"`
ClientID string `json:"clientId"`
ClientSecret string `json:"clientSecret"`
Server string `json:"server"`
Issuer string `json:"issuer"`
AuthUrl string `json:"authUrl"`
CallbackUrl string `json:"callbackUrl"`
CreatedAt time.Time `gorm:"<-:create;autoCreateTime" json:"created_at,omitempty"`
UpdatedAt time.Time `gorm:"<-:create;<-:update;autoUpdateTime" json:"updated_at,omitempty"`
}