diff --git a/.gitignore b/.gitignore index 0687891..c245427 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,4 @@ dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user- linux-amd64-nextzenos-user-service-v1.2.4.tar.gz dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service +dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service diff --git a/dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service b/dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service index 1ae447e..9e79ffe 100755 Binary files a/dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service and b/dist/casaos-user-service-amd64_linux_amd64_v1/build/sysroot/usr/bin/casaos-user-service differ diff --git a/dist/metadata.json b/dist/metadata.json index e7f8b18..28510f8 100644 --- a/dist/metadata.json +++ b/dist/metadata.json @@ -1 +1 @@ -{"project_name":"casaos-user-service","tag":"v1.0.0","previous_tag":"","version":"1.0.1","commit":"bb2cbabc598c04de66f2652e8cd829c837ab0798","date":"2024-08-15T13:47:15.2430523+07:00","runtime":{"goos":"linux","goarch":"amd64"}} \ No newline at end of file +{"project_name":"casaos-user-service","tag":"v1.0.0","previous_tag":"","version":"1.0.1","commit":"0af7c28227cfc12fd45ef08404aa1298bc4554f2","date":"2024-08-29T11:42:27.804094773+07:00","runtime":{"goos":"linux","goarch":"amd64"}} \ No newline at end of file diff --git a/middleware/authentik.go b/middleware/authentik.go new file mode 100644 index 0000000..f1658f3 --- /dev/null +++ b/middleware/authentik.go @@ -0,0 +1,14 @@ +package middleware + +import ( + "log" + + "github.com/gin-gonic/gin" +) + +func CheckConnection() gin.HandlerFunc { + return func(c *gin.Context) { + log.Println("OK") + c.Next() + } +} diff --git a/route/v1.go b/route/v1.go index c11dc86..5c2b56a 100644 --- a/route/v1.go +++ b/route/v1.go @@ -15,7 +15,7 @@ import ( func InitRouter() *gin.Engine { r := gin.Default() r.Use(middleware.Cors()) - // r.Use(middleware.WriteLog()) + r.Use(v1.CheckOIDCInit()) r.Use(gzip.Gzip(gzip.DefaultCompression)) // check if environment variable is set @@ -24,7 +24,7 @@ func InitRouter() *gin.Engine { } else { gin.SetMode(gin.ReleaseMode) } - v1.OIDC() + go v1.InitOIDC() r.POST("/v1/users/register", v1.PostUserRegister) r.POST("/v1/users/login", v1.PostUserLogin) r.POST("/v1/users/omvlogin", v1.PostOMVLogin) diff --git a/route/v1/user.go b/route/v1/user.go index 8dff435..322ebf8 100644 --- a/route/v1/user.go +++ b/route/v1/user.go @@ -52,7 +52,7 @@ var ( 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.26.157.79:8080/v1/users/oidc/callback" + //callbackURL = "http://172.20.60.244:8080/v1/users/oidc/callback" ) // @Summary register user @@ -189,13 +189,76 @@ func randString(nByte int) (string, error) { } var oauth2Config oauth2.Config +var oidcInit bool + +func InitOIDC() { + const ( + maxSleep = 60 * time.Second + minSleep = 10 * time.Second + maxRetryBackoff = 5 // Cap retry backoff to 5 attempts + ) + + var ( + successCount int + failCount int + sleepTime = minSleep + ) + + ticker := time.NewTicker(sleepTime) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + if err := OIDC(); err == nil { + if !oidcInit { + log.Println("OIDC provider initialized successfully") + } else { + log.Println("OIDC provider renewed successfully") + } + oidcInit = true + failCount = 0 + successCount++ + // Exponential backoff with a cap + sleepTime = minSleep * time.Duration(successCount) + if sleepTime > maxSleep { + sleepTime = maxSleep + } + + } else { + oidcInit = false + successCount = 0 + failCount++ + // Exponential backoff with a cap + sleepTime = minSleep * time.Duration(failCount) + if failCount > maxRetryBackoff { + sleepTime = minSleep * time.Duration(maxRetryBackoff) + } + log.Printf("OIDC initialization failed: %v. Retrying in %v", err, sleepTime) + } + + log.Printf("Waiting for %v before next check", sleepTime) + ticker.Reset(sleepTime) + } + } +} +func CheckOIDCInit() gin.HandlerFunc { + return func(c *gin.Context) { + if !oidcInit { + log.Println("Provider is Offline") + c.JSON(http.StatusServiceUnavailable, model.Result{Success: http.StatusServiceUnavailable, Message: "Authentik Server is Offline"}) + return + } + c.Next() + } +} // Use an init function to initialize the oauth2Config variable. -func OIDC() { +func OIDC() error { ctx := context.Background() provider, err := oidc.NewProvider(ctx, authURL) if err != nil { - log.Fatalf("Error creating OIDC provider: %v", err) // This will print the error and stop execution + return err } oauth2Config = oauth2.Config{ ClientID: clientID, @@ -205,6 +268,7 @@ func OIDC() { Scopes: []string{oidc.ScopeOpenID, "profile", "email", "goauthentik.io/api"}, //add offline access for refresh token } + return nil } func OIDCLogin(c *gin.Context) { json := make(map[string]string) @@ -264,6 +328,7 @@ func OIDCUserInfo(c *gin.Context) { }) } func OIDCValidateToken(c *gin.Context) { + json := make(map[string]string) c.ShouldBind(&json) accessToken := json["authentikToken"] @@ -280,6 +345,7 @@ func OIDCValidateToken(c *gin.Context) { c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR_AUTH_TOKEN, Message: common_err.GetMsg(common_err.ERROR_AUTH_TOKEN)}) } func OIDCLogout(c *gin.Context) { + json := make(map[string]string) c.ShouldBind(&json) accessToken := json["authentikToken"] @@ -297,6 +363,9 @@ func OIDCLogout(c *gin.Context) { c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR_AUTH_TOKEN, Message: common_err.GetMsg(common_err.ERROR_AUTH_TOKEN), Data: fullURL}) } func OIDCProfile(c *gin.Context) { + if !oidcInit { + + } json := make(map[string]string) c.ShouldBind(&json) accessToken, err := c.Cookie("accessToken")