mirror of
https://github.com/go-vikunja/vikunja.git
synced 2026-03-12 01:59:34 -05:00
feat(auth): add oauth require availability configuration on startup (#1358)
This commit is contained in:
@@ -717,6 +717,11 @@
|
||||
"key": "forceuserinfo",
|
||||
"default_value": "false",
|
||||
"comment": "This option forces the use of the OpenID Connect UserInfo endpoint to retrieve user information instead of relying on claims from the ID token. When set to `true`, user data (email, name, username) will always be obtained from the UserInfo endpoint even if the information is available in the token claims. This is useful for providers that don't include complete user information in their tokens or when you need the most up-to-date user data. Allowed value is either `true` or `false`."
|
||||
},
|
||||
{
|
||||
"key": "requireavailability",
|
||||
"default_value": "false",
|
||||
"comment": "This option requires the OpenID Connect provider to be available during Vikunja startup. When set to `true`, Vikunja will crash if it cannot connect to the provider during initialization, allowing container orchestrators like Kubernetes to handle the failure by restarting the application. This is useful in environments where you want to ensure all authentication providers are available before the application starts serving requests. Allowed value is either `true` or `false`."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -97,6 +97,12 @@ func FullInitWithoutAsync() {
|
||||
// Connect to ldap if enabled
|
||||
ldap.InitializeLDAPConnection()
|
||||
|
||||
// Check all OpenID Connect providers at startup
|
||||
_, err := openid.GetAllProviders()
|
||||
if err != nil {
|
||||
log.Errorf("Error initializing OpenID Connect providers: %s", err)
|
||||
}
|
||||
|
||||
// Load translations
|
||||
i18n.Init()
|
||||
|
||||
|
||||
@@ -52,19 +52,20 @@ type Callback struct {
|
||||
|
||||
// Provider is the structure of an OpenID Connect provider
|
||||
type Provider struct {
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
OriginalAuthURL string `json:"-"`
|
||||
AuthURL string `json:"auth_url"`
|
||||
LogoutURL string `json:"logout_url"`
|
||||
ClientID string `json:"client_id"`
|
||||
Scope string `json:"scope"`
|
||||
EmailFallback bool `json:"email_fallback"`
|
||||
UsernameFallback bool `json:"username_fallback"`
|
||||
ForceUserInfo bool `json:"force_user_info"`
|
||||
ClientSecret string `json:"-"`
|
||||
openIDProvider *oidc.Provider
|
||||
Oauth2Config *oauth2.Config `json:"-"`
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
OriginalAuthURL string `json:"-"`
|
||||
AuthURL string `json:"auth_url"`
|
||||
LogoutURL string `json:"logout_url"`
|
||||
ClientID string `json:"client_id"`
|
||||
Scope string `json:"scope"`
|
||||
EmailFallback bool `json:"email_fallback"`
|
||||
UsernameFallback bool `json:"username_fallback"`
|
||||
ForceUserInfo bool `json:"force_user_info"`
|
||||
RequireAvailability bool `json:"-"`
|
||||
ClientSecret string `json:"-"`
|
||||
openIDProvider *oidc.Provider
|
||||
Oauth2Config *oauth2.Config `json:"-"`
|
||||
}
|
||||
|
||||
type claims struct {
|
||||
@@ -83,6 +84,9 @@ func init() {
|
||||
|
||||
func (p *Provider) setOicdProvider() (err error) {
|
||||
p.openIDProvider, err = oidc.NewProvider(context.Background(), p.OriginalAuthURL)
|
||||
if err != nil && p.RequireAvailability {
|
||||
log.Fatalf("OpenID Connect provider '%s' is not available and require_availability is enabled: %s", p.Name, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ func getProviderFromMap(pi map[string]interface{}, key string) (provider *Provid
|
||||
"emailfallback",
|
||||
"usernamefallback",
|
||||
"forceuserinfo",
|
||||
"requireavailability",
|
||||
},
|
||||
requiredKeys...,
|
||||
)
|
||||
@@ -193,17 +194,29 @@ func getProviderFromMap(pi map[string]interface{}, key string) (provider *Provid
|
||||
}
|
||||
}
|
||||
|
||||
var requireAvailability = false
|
||||
requireAvailabilityValue, exists := pi["requireavailability"]
|
||||
if exists {
|
||||
requireAvailabilityTypedValue, ok := requireAvailabilityValue.(bool)
|
||||
if ok {
|
||||
requireAvailability = requireAvailabilityTypedValue
|
||||
} else {
|
||||
log.Errorf("requireavailability is not a boolean for provider %s, value: %v", key, requireAvailabilityValue)
|
||||
}
|
||||
}
|
||||
|
||||
provider = &Provider{
|
||||
Name: name,
|
||||
Key: key,
|
||||
AuthURL: pi["authurl"].(string),
|
||||
OriginalAuthURL: pi["authurl"].(string),
|
||||
ClientSecret: pi["clientsecret"].(string),
|
||||
LogoutURL: logoutURL,
|
||||
Scope: scope,
|
||||
EmailFallback: emailFallback,
|
||||
UsernameFallback: usernameFallback,
|
||||
ForceUserInfo: forceUserInfo,
|
||||
Name: name,
|
||||
Key: key,
|
||||
AuthURL: pi["authurl"].(string),
|
||||
OriginalAuthURL: pi["authurl"].(string),
|
||||
ClientSecret: pi["clientsecret"].(string),
|
||||
LogoutURL: logoutURL,
|
||||
Scope: scope,
|
||||
EmailFallback: emailFallback,
|
||||
UsernameFallback: usernameFallback,
|
||||
ForceUserInfo: forceUserInfo,
|
||||
RequireAvailability: requireAvailability,
|
||||
}
|
||||
|
||||
cl, is := pi["clientid"].(int)
|
||||
|
||||
Reference in New Issue
Block a user