5
0
Fork 0

feat: Improved bypass

feat/improved-bypass
Ambrose Chua 2019-07-27 18:13:25 +08:00
parent 217c90d0cf
commit a33b79712f
Signed by: ambrose
GPG Key ID: B34FBE029276BA5D
2 changed files with 247 additions and 241 deletions

View File

@ -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
View File

@ -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")