package controllers import ( "encoding/base64" "encoding/json" "fmt" "net/http" "oc-auth/conf" "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" // @Param client_id query string true "the client_id you want to get" // @Success 200 {string} // @router /logout [delete] func (o *OAuthController) LogOut() { // authorize user clientID := o.Ctx.Input.Query("client_id") 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(clientID, 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" // @Param client_id query string true "the client_id you want to get" // @Success 200 {string} // @router /login [post] func (o *OAuthController) Login() { // authorize user fmt.Println("Login", o.Ctx.Input.Query("client_id"), o.Ctx.Input.Param(":client_id")) clientID := o.Ctx.Input.Query("client_id") var res auth_connectors.Token json.Unmarshal(o.Ctx.Input.CopyBody(10000000), &res) if conf.GetConfig().SourceMode == "ldap" { ldap := auth_connectors.New() found, err := ldap.Authenticate(o.Ctx.Request.Context(), res.Username, res.Password) fmt.Println("found", found, "err", err) if err != nil || !found { o.Data["json"] = err o.Ctx.ResponseWriter.WriteHeader(401) o.ServeJSON() return } } token, err := infrastructure.GetAuthConnector().Login( clientID, res.Username, &http.Cookie{ // open a session Name: "csrf_token", Value: o.XSRFToken(), }) fmt.Println("token", token, "err", err) 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" // @Param client_id query string true "the client_id you want to get" // @Success 200 {string} // @router /refresh [post] func (o *OAuthController) Refresh() { clientID := o.Ctx.Input.Query("client_id") var token auth_connectors.Token json.Unmarshal(o.Ctx.Input.CopyBody(100000), &token) // refresh token newToken, err := infrastructure.GetAuthConnector().Refresh(clientID, &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) InternaisDraftlAuthForward() { 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(o.Ctx.Request) 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 } o.ServeJSON() } func (o *OAuthController) extractOrigin(request *http.Request) (string, string, bool) { user, peerID, groups := oclib.ExtractTokenInfo(*request) 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.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).Search(nil, searchStr, false) 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 } func ExtractClient(request http.Request) string { reqToken := request.Header.Get("Authorization") splitToken := strings.Split(reqToken, "Bearer ") if len(splitToken) < 2 { reqToken = "" } else { reqToken = splitToken[1] } if reqToken != "" { token := strings.Split(reqToken, ".") if len(token) > 2 { bytes, err := base64.StdEncoding.DecodeString(token[2]) if err != nil { return "" } m := map[string]interface{}{} err = json.Unmarshal(bytes, &m) if err != nil { return "" } return m["session"].(map[string]interface{})["id_token"].(map[string]interface{})["client_id"].(string) } } return "" }