package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" "net/url" "strings" "github.com/dgrijalva/jwt-go" "github.com/labstack/echo" ) type handler struct{} type userInfo struct { Result struct { Result struct { Sshpubkeyfp []string `json:"sshpubkeyfp"` HasKeytab bool `json:"has_keytab"` Ipasshpubkey []string `json:"ipasshpubkey"` Cn []string `json:"cn"` Krbcanonicalname []string `json:"krbcanonicalname"` Krbticketflags []string `json:"krbticketflags"` MemberofGroup []string `json:"memberof_group"` HasPassword bool `json:"has_password"` Homedirectory []string `json:"homedirectory"` Nsaccountlock bool `json:"nsaccountlock"` UID []string `json:"uid"` Title []string `json:"title"` Loginshell []string `json:"loginshell"` Uidnumber []string `json:"uidnumber"` Preserved bool `json:"preserved"` Krbextradata []struct { Base64 string `json:"__base64__"` } `json:"krbextradata"` Mail []string `json:"mail"` MemberofindirectHbacrule []string `json:"memberofindirect_hbacrule"` Dn string `json:"dn"` Displayname []string `json:"displayname"` Mepmanagedentry []string `json:"mepmanagedentry"` Ipauniqueid []string `json:"ipauniqueid"` Krbloginfailedcount []string `json:"krbloginfailedcount"` Krbpwdpolicyreference []string `json:"krbpwdpolicyreference"` Krbprincipalname []string `json:"krbprincipalname"` Givenname []string `json:"givenname"` Krblastadminunlock []struct { Datetime string `json:"__datetime__"` } `json:"krblastadminunlock"` Krbpasswordexpiration []struct { Datetime string `json:"__datetime__"` } `json:"krbpasswordexpiration"` Krblastfailedauth []struct { Datetime string `json:"__datetime__"` } `json:"krblastfailedauth"` Objectclass []string `json:"objectclass"` Gidnumber []string `json:"gidnumber"` Gecos []string `json:"gecos"` Sn []string `json:"sn"` MemberofSudorule []string `json:"memberof_sudorule"` Krblastpwdchange []struct { Datetime string `json:"__datetime__"` } `json:"krblastpwdchange"` Initials []string `json:"initials"` } `json:"result"` Value string `json:"value"` Summary interface{} `json:"summary"` } `json:"result"` Version string `json:"version"` Error interface{} `json:"error"` ID int `json:"id"` Principal string `json:"principal"` } // Most of the code is taken from the echo guide // https://echo.labstack.com/cookbook/jwt func (h *handler) login(c echo.Context) error { username := c.FormValue("username") password := c.FormValue("password") _url := "https://ipa.sf.faraborddi.dc/ipa/session/login_password" method := "POST" params := url.Values{} params.Add("user", username) params.Add("password", password) payload := strings.NewReader(params.Encode()) client := &http.Client{} req, err := http.NewRequest(method, _url, payload) audit("Recieved Login request from:" + RealIP) if err != nil { fmt.Println(err) } req.Header.Add("Referer", "https://ipa.sf.faraborddi.dc/ipa") req.Header.Add("Content-Type", "application/x-www-form-urlencoded") req.Header.Add("Accept", "text/plain") res, err := client.Do(req) cockie := res.Cookies() defer res.Body.Close() fmt.Println(res.StatusCode) if res.StatusCode == 200 { user := getUserInfo(cockie, username) fmt.Println(user.Result.Value) tokens, err := generateTokenPair() if err != nil { return err } return c.JSON(http.StatusOK, tokens) } return echo.ErrUnauthorized } func getUserInfo(cockie []*http.Cookie, username string) userInfo { url := "https://ipa.sf.faraborddi.dc/ipa/session/json" method := "POST" _json := fmt.Sprintf(` { "method": "user_show", "params": [ [ "%s" ], { "all": true, "version": "2.215" } ], "id": 0 } `, username) payload := strings.NewReader(_json) client := &http.Client{} req, err := http.NewRequest(method, url, payload) if err != nil { fmt.Println(err) } req.Header.Add("Referer", "https://ipa.sf.faraborddi.dc/ipa") req.Header.Add("Content-Type", "application/json") req.Header.Add("Accept", "text/plain") req.Header.Add("Cookie", cockie[0].Raw) res, err := client.Do(req) defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) user := userInfo{} json.Unmarshal(body, &user) //fmt.Println(user.Result.Value) return user } // This is the api to refresh tokens // Most of the code is taken from the jwt-go package's sample codes // https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse--Hmac func (h *handler) token(c echo.Context) error { type tokenReqBody struct { RefreshToken string `json:"refresh_token"` } tokenReq := tokenReqBody{} c.Bind(&tokenReq) // Parse takes the token string and a function for looking up the key. // The latter is especially useful if you use multiple keys for your application. // The standard is to use 'kid' in the head of the token to identify // which key to use, but the parsed token (head and claims) is provided // to the callback, providing flexibility. token, err := jwt.Parse(tokenReq.RefreshToken, func(token *jwt.Token) (interface{}, error) { // Don't forget to validate the alg is what you expect: if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) } // hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key") return []byte("secret"), nil }) if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { // Get the user record from database or // run through your business logic to verify if the user can log in if int(claims["sub"].(float64)) == 1 { newTokenPair, err := generateTokenPair() if err != nil { return err } return c.JSON(http.StatusOK, newTokenPair) } return echo.ErrUnauthorized } return err } // Most of the code is taken from the echo guide // https://echo.labstack.com/cookbook/jwt func (h *handler) private(c echo.Context) error { user := c.Get("user").(*jwt.Token) claims := user.Claims.(jwt.MapClaims) name := claims["name"].(string) return c.String(http.StatusOK, "Welcome "+name+"!") }