package controllers import ( "encoding/json" "fmt" "net/http" "oc-auth/infrastructure" auth_connectors "oc-auth/infrastructure/auth_connector" "regexp" "strings" oclib "cloud.o-forge.io/core/oc-lib" model "cloud.o-forge.io/core/oc-lib/models/peer" beego "github.com/beego/beego/v2/server/web" ) // Operations about auth type OAuthController struct { beego.Controller } // @Title Logout // @Description unauthenticate user // @Param Authorization header string false "auth token" // @Success 200 {string} // @router /ldap/logout [delete] func (o *OAuthController) LogOutLDAP() { // authorize user reqToken := o.Ctx.Request.Header.Get("Authorization") splitToken := strings.Split(reqToken, "Bearer ") if len(splitToken) < 2 { reqToken = "" } else { reqToken = splitToken[1] } var res auth_connectors.Token json.Unmarshal(o.Ctx.Input.CopyBody(10000000), &res) token, err := infrastructure.GetAuthConnector().Logout(reqToken) if err != nil || token == nil { o.Data["json"] = err } else { o.Data["json"] = token } o.ServeJSON() } // @Title Login // @Description authenticate user // @Param body body models.workflow true "The workflow content" // @Success 200 {string} // @router /ldap/login [post] func (o *OAuthController) LoginLDAP() { // authorize user var res auth_connectors.Token json.Unmarshal(o.Ctx.Input.CopyBody(10000000), &res) ldap := auth_connectors.New() found, err := ldap.Authenticate(o.Ctx.Request.Context(), res.Username, res.Password) if err != nil || !found { o.Data["json"] = err o.Ctx.ResponseWriter.WriteHeader(401) o.ServeJSON() return } token, err := infrastructure.GetAuthConnector().Login(res.Username, &http.Cookie{ // open a session Name: "csrf_token", Value: o.XSRFToken(), }) if err != nil || token == nil { o.Data["json"] = err o.Ctx.ResponseWriter.WriteHeader(401) } else { o.Data["json"] = token } o.ServeJSON() } // @Title Introspection // @Description introspect token // @Param body body models.Token true "The token info" // @Success 200 {string} // @router /refresh [post] func (o *OAuthController) Refresh() { var token auth_connectors.Token json.Unmarshal(o.Ctx.Input.CopyBody(100000), &token) // refresh token newToken, err := infrastructure.GetAuthConnector().Refresh(&token) if err != nil || newToken == nil { o.Data["json"] = err o.Ctx.ResponseWriter.WriteHeader(401) } else { o.Data["json"] = newToken } o.ServeJSON() } // @Title Introspection // @Description introspect token // @Param Authorization header string false "auth token" // @Success 200 {string} // @router /introspect [get] func (o *OAuthController) Introspect() { reqToken := o.Ctx.Request.Header.Get("Authorization") splitToken := strings.Split(reqToken, "Bearer ") if len(splitToken) < 2 { reqToken = "" } else { reqToken = splitToken[1] } token, err := infrastructure.GetAuthConnector().Introspect(reqToken) if err != nil || !token { o.Data["json"] = err o.Ctx.ResponseWriter.WriteHeader(401) } o.ServeJSON() } var whitelist = []string{ "/login", "/refresh", "/introspect", } // @Title AuthForward // @Description auth forward // @Param Authorization header string false "auth token" // @Success 200 {string} // @router /forward [get] func (o *OAuthController) InternalAuthForward() { fmt.Println("InternalAuthForward") reqToken := o.Ctx.Request.Header.Get("Authorization") if reqToken == "" { for _, w := range whitelist { if strings.Contains(o.Ctx.Request.Header.Get("X-Forwarded-Uri"), w) { o.Ctx.ResponseWriter.WriteHeader(200) o.ServeJSON() return } } o.Ctx.ResponseWriter.WriteHeader(401) o.ServeJSON() return } splitToken := strings.Split(reqToken, "Bearer ") if len(splitToken) < 2 { reqToken = "" } else { reqToken = splitToken[1] } origin, publicKey, external := o.extractOrigin() if !infrastructure.GetAuthConnector().CheckAuthForward( //reqToken != "" && reqToken, publicKey, origin, o.Ctx.Request.Header.Get("X-Forwarded-Method"), o.Ctx.Request.Header.Get("X-Forwarded-Uri"), external) && origin != "" && publicKey != "" { o.Ctx.ResponseWriter.WriteHeader(401) o.ServeJSON() return } isToken, err := infrastructure.GetAuthConnector().Introspect(reqToken, &http.Cookie{ Name: "csrf_token", Value: o.XSRFToken(), }) // may be a problem... we should check if token is valid on our side // prefers a refresh token call fmt.Println("InternalAuthForward", isToken, err) if err != nil || !isToken { o.Ctx.ResponseWriter.WriteHeader(401) } o.ServeJSON() } func (o *OAuthController) extractOrigin() (string, string, bool) { external := true publicKey := "" origin := o.Ctx.Request.Header.Get("X-Forwarded-Host") if origin == "" { origin = o.Ctx.Request.Header.Get("Origin") } searchStr := origin r := regexp.MustCompile("(:[0-9]+)") t := r.FindString(searchStr) if t != "" { searchStr = strings.Replace(searchStr, t, "", -1) } peer := oclib.Search(nil, searchStr, oclib.LibDataEnum(oclib.PEER)) if peer.Code != 200 || len(peer.Data) == 0 { // TODO: add state of partnership return "", "", external } p := peer.Data[0].(*model.Peer) publicKey = p.PublicKey origin = p.Url if origin != "" { // is external if strings.Contains(origin, "localhost") || strings.Contains(origin, "127.0.0.1") || p.State == model.SELF { external = false } } else { external = false } return origin, publicKey, external }