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