feat: oidc (#605)

* chore: add oidc base config

* wip: authorize page

* feat: implement basic oidc functionality

* refactor: implement oidc following tinyauth patterns

* feat: adapt frontend to oidc flow

* fix: review comments

* fix: oidc review comments

* feat: refresh token grant type support

* feat: cleanup expired oidc sessions

* feat: frontend i18n

* fix: fix typo in error screen

* tests: add basic testing

* fix: more review comments

* refactor: rework oidc error messages

* feat: openid discovery endpoint

* feat: jwk endpoint

* i18n: fix typo

* fix: more rabbit nitpicks

* fix: final review comments

* i18n: authorize page error messages
This commit is contained in:
Stavros
2026-02-01 19:00:59 +02:00
committed by GitHub
parent 252ba10f48
commit 671343f677
38 changed files with 2573 additions and 64 deletions

View File

@@ -30,6 +30,7 @@ type BootstrapApp struct {
users []config.User
oauthProviders map[string]config.OAuthServiceConfig
configuredProviders []controller.Provider
oidcClients []config.OIDCClientConfig
}
services Services
}
@@ -84,6 +85,12 @@ func (app *BootstrapApp) Setup() error {
app.context.oauthProviders[id] = provider
}
// Setup OIDC clients
for id, client := range app.config.OIDC.Clients {
client.ID = id
app.context.oidcClients = append(app.context.oidcClients, client)
}
// Get cookie domain
cookieDomain, err := utils.GetCookieDomain(app.config.AppURL)
@@ -240,7 +247,7 @@ func (app *BootstrapApp) heartbeat() {
heartbeatURL := config.ApiServer + "/v1/instances/heartbeat"
for ; true; <-ticker.C {
for range ticker.C {
tlog.App.Debug().Msg("Sending heartbeat")
req, err := http.NewRequest(http.MethodPost, heartbeatURL, bytes.NewReader(bodyJson))
@@ -272,7 +279,7 @@ func (app *BootstrapApp) dbCleanup(queries *repository.Queries) {
defer ticker.Stop()
ctx := context.Background()
for ; true; <-ticker.C {
for range ticker.C {
tlog.App.Debug().Msg("Cleaning up old database sessions")
err := queries.DeleteExpiredSessions(ctx, time.Now().Unix())
if err != nil {

View File

@@ -86,6 +86,10 @@ func (app *BootstrapApp) setupRouter() (*gin.Engine, error) {
oauthController.SetupRoutes()
oidcController := controller.NewOIDCController(controller.OIDCControllerConfig{}, app.services.oidcService, apiRouter)
oidcController.SetupRoutes()
proxyController := controller.NewProxyController(controller.ProxyControllerConfig{
AppURL: app.config.AppURL,
}, apiRouter, app.services.accessControlService, app.services.authService)
@@ -109,5 +113,9 @@ func (app *BootstrapApp) setupRouter() (*gin.Engine, error) {
healthController.SetupRoutes()
wellknownController := controller.NewWellKnownController(controller.WellKnownControllerConfig{}, app.services.oidcService, engine)
wellknownController.SetupRoutes()
return engine, nil
}

View File

@@ -12,6 +12,7 @@ type Services struct {
dockerService *service.DockerService
ldapService *service.LdapService
oauthBrokerService *service.OAuthBrokerService
oidcService *service.OIDCService
}
func (app *BootstrapApp) initServices(queries *repository.Queries) (Services, error) {
@@ -88,5 +89,21 @@ func (app *BootstrapApp) initServices(queries *repository.Queries) (Services, er
services.oauthBrokerService = oauthBrokerService
oidcService := service.NewOIDCService(service.OIDCServiceConfig{
Clients: app.config.OIDC.Clients,
PrivateKeyPath: app.config.OIDC.PrivateKeyPath,
PublicKeyPath: app.config.OIDC.PublicKeyPath,
Issuer: app.config.AppURL,
SessionExpiry: app.config.Auth.SessionExpiry,
}, queries)
err = oidcService.Init()
if err != nil {
return Services{}, err
}
services.oidcService = oidcService
return services, nil
}