feat: Improved bypass
parent
217c90d0cf
commit
a33b79712f
|
@ -9,6 +9,7 @@ RUN CGO_ENABLED=0 go build -ldflags "-s -w"
|
|||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||
COPY --from=build /src/login /login
|
||||
COPY --from=build /src/.env /.env
|
||||
|
||||
|
|
89
main.go
89
main.go
|
@ -2,7 +2,6 @@ package main
|
|||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"crypto/rsa"
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
|
@ -18,12 +17,12 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/go-redis/redis"
|
||||
"github.com/ttacon/libphonenumber"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/ttacon/libphonenumber"
|
||||
)
|
||||
|
||||
var listen string
|
||||
|
@ -94,8 +93,8 @@ func main() {
|
|||
// Routes
|
||||
router := httprouter.New()
|
||||
|
||||
router.POST("/login", Login);
|
||||
router.POST("/init", InitRequest)
|
||||
router.POST("/init/bypass", InitRequestBypass)
|
||||
router.POST("/verify", VerifyCode)
|
||||
router.POST("/register/:code/:nonce", CreateUser)
|
||||
|
||||
|
@ -121,6 +120,7 @@ func RandomHex() (string, error) {
|
|||
type InitRequestBody struct {
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
}
|
||||
|
||||
func InitRequest(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
// Get request body
|
||||
req := InitRequestBody{}
|
||||
|
@ -152,12 +152,12 @@ func InitRequest(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
|||
bytes := hex.EncodeToString(b)
|
||||
|
||||
// Set code-nonce pair in redis first
|
||||
redisClient.Set(code + "nonce", bytes, ttl)
|
||||
redisClient.Set(code+"nonce", bytes, ttl)
|
||||
// Set code-phone_number pair
|
||||
redisClient.Set(code + "phone", phone, ttl)
|
||||
redisClient.Set(code+"phone", phone, ttl)
|
||||
|
||||
// Send SMS via Twilio
|
||||
data := url.Values {}
|
||||
data := url.Values{}
|
||||
data.Set("MessagingServiceSid", messagingSID)
|
||||
data.Set("To", phone)
|
||||
data.Set("Body", fmt.Sprintf("Your OTP for Beep is %s", code))
|
||||
|
@ -171,11 +171,7 @@ func InitRequest(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
|||
twilioReq.SetBasicAuth(twilioSID, twilioToken)
|
||||
twilioReq.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
// Twilio uses self-signed certs
|
||||
transport := &http.Transport {
|
||||
TLSClientConfig: &tls.Config{ InsecureSkipVerify: true },
|
||||
}
|
||||
client := &http.Client{ Transport: transport }
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(twilioReq)
|
||||
|
||||
if err != nil {
|
||||
|
@ -191,11 +187,48 @@ func InitRequest(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
|||
w.Write([]byte(bytes))
|
||||
}
|
||||
|
||||
func InitRequestBypass(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
// Get request body
|
||||
req := InitRequestBody{}
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
err := decoder.Decode(&req)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure phone number is legitimate
|
||||
phone, err := ParsePhone(req.PhoneNumber)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Generate nonce
|
||||
b := make([]byte, 16)
|
||||
_, err = rand.Read(b)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
bytes := hex.EncodeToString(b)
|
||||
|
||||
code := "000000"
|
||||
// Set code-nonce pair in redis first
|
||||
redisClient.Set(code+"nonce", bytes, ttl)
|
||||
// Set code-phone_number pair
|
||||
redisClient.Set(code+"phone", phone, ttl)
|
||||
|
||||
// Return nonce
|
||||
w.Write([]byte(bytes))
|
||||
}
|
||||
|
||||
type VerifyRequestBody struct {
|
||||
Code string `json:"code"`
|
||||
Nonce string `json:"nonce"`
|
||||
ClientId string `json:"clientid"`
|
||||
}
|
||||
|
||||
func VerifyCode(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
// Get request body
|
||||
req := VerifyRequestBody{}
|
||||
|
@ -264,7 +297,7 @@ func VerifyCode(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
|||
}
|
||||
|
||||
// Generate JWT
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
|
||||
"userid": userID,
|
||||
"clientid": req.ClientId,
|
||||
})
|
||||
|
@ -278,34 +311,6 @@ func VerifyCode(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
|||
w.Write([]byte(tokenString))
|
||||
}
|
||||
|
||||
type LoginData struct {
|
||||
ID string `json:"userid"`
|
||||
Client string `json:"clientid"`
|
||||
}
|
||||
|
||||
func Login(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
login := LoginData {}
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
err := decoder.Decode(&login)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims {
|
||||
"userid": login.ID,
|
||||
"clientid": login.Client,
|
||||
})
|
||||
|
||||
tokenString, err := token.SignedString(privateKey)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write([]byte(tokenString))
|
||||
}
|
||||
|
||||
func CreateUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||
code := p.ByName("code")
|
||||
nonce := p.ByName("nonce")
|
||||
|
|
Loading…
Reference in New Issue