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
|
||||||
|
|
||||||
|
|
487
main.go
487
main.go
|
@ -1,29 +1,28 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/tls"
|
"crypto/rsa"
|
||||||
"crypto/rsa"
|
"database/sql"
|
||||||
"database/sql"
|
"encoding/hex"
|
||||||
"encoding/hex"
|
"encoding/json"
|
||||||
"encoding/json"
|
"fmt"
|
||||||
"fmt"
|
"io"
|
||||||
"io"
|
"io/ioutil"
|
||||||
"io/ioutil"
|
"log"
|
||||||
"log"
|
"math/big"
|
||||||
"math/big"
|
"net/http"
|
||||||
"net/http"
|
"net/url"
|
||||||
"net/url"
|
"os"
|
||||||
"os"
|
"strings"
|
||||||
"strings"
|
"time"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/dgrijalva/jwt-go"
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/go-redis/redis"
|
||||||
"github.com/dgrijalva/jwt-go"
|
"github.com/joho/godotenv"
|
||||||
"github.com/go-redis/redis"
|
"github.com/julienschmidt/httprouter"
|
||||||
"github.com/ttacon/libphonenumber"
|
_ "github.com/lib/pq"
|
||||||
_ "github.com/lib/pq"
|
"github.com/ttacon/libphonenumber"
|
||||||
)
|
)
|
||||||
|
|
||||||
var listen string
|
var listen string
|
||||||
|
@ -44,63 +43,63 @@ var db *sql.DB
|
||||||
var redisClient *redis.Client
|
var redisClient *redis.Client
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Load .env
|
// Load .env
|
||||||
err := godotenv.Load()
|
err := godotenv.Load()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error loading .env file")
|
log.Fatal("Error loading .env file")
|
||||||
}
|
}
|
||||||
listen = os.Getenv("LISTEN")
|
listen = os.Getenv("LISTEN")
|
||||||
postgres = os.Getenv("POSTGRES")
|
postgres = os.Getenv("POSTGRES")
|
||||||
redisHost = os.Getenv("REDIS")
|
redisHost = os.Getenv("REDIS")
|
||||||
|
|
||||||
ttl, err = time.ParseDuration(os.Getenv("TTL"))
|
ttl, err = time.ParseDuration(os.Getenv("TTL"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error parsing ttl")
|
log.Fatal("Error parsing ttl")
|
||||||
}
|
}
|
||||||
|
|
||||||
messagingSID = os.Getenv("MESSAGING_SID")
|
messagingSID = os.Getenv("MESSAGING_SID")
|
||||||
twilioSID = os.Getenv("TWILIO_SID")
|
twilioSID = os.Getenv("TWILIO_SID")
|
||||||
twilioToken = os.Getenv("TWILIO_TOKEN")
|
twilioToken = os.Getenv("TWILIO_TOKEN")
|
||||||
|
|
||||||
dummyToken = "{\"userid\":\"dummy\",\"clientid\":\"dummy\"}"
|
dummyToken = "{\"userid\":\"dummy\",\"clientid\":\"dummy\"}"
|
||||||
coreURL = os.Getenv("CORE_URL")
|
coreURL = os.Getenv("CORE_URL")
|
||||||
|
|
||||||
// Load RSA private key
|
// Load RSA private key
|
||||||
privateKeyBytes, err := ioutil.ReadFile("key")
|
privateKeyBytes, err := ioutil.ReadFile("key")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
privateKey, err = jwt.ParseRSAPrivateKeyFromPEM(privateKeyBytes)
|
privateKey, err = jwt.ParseRSAPrivateKeyFromPEM(privateKeyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Postgres
|
// Postgres
|
||||||
log.Printf("connecting to postgres %s", postgres)
|
log.Printf("connecting to postgres %s", postgres)
|
||||||
db, err = sql.Open("postgres", postgres)
|
db, err = sql.Open("postgres", postgres)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
// Redis
|
// Redis
|
||||||
redisClient = redis.NewClient(&redis.Options{
|
redisClient = redis.NewClient(&redis.Options{
|
||||||
Addr: redisHost,
|
Addr: redisHost,
|
||||||
Password: "",
|
Password: "",
|
||||||
DB: 1,
|
DB: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
// 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)
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
log.Printf("starting server on %s", listen)
|
log.Printf("starting server on %s", listen)
|
||||||
log.Fatal(http.ListenAndServe(listen, router))
|
log.Fatal(http.ListenAndServe(listen, router))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,249 +118,255 @@ 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{}
|
||||||
decoder := json.NewDecoder(r.Body)
|
decoder := json.NewDecoder(r.Body)
|
||||||
err := decoder.Decode(&req)
|
err := decoder.Decode(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure phone number is legitimate
|
// Make sure phone number is legitimate
|
||||||
phone, err := ParsePhone(req.PhoneNumber)
|
phone, err := ParsePhone(req.PhoneNumber)
|
||||||
if err != nil {
|
|
||||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate OTP code
|
|
||||||
c, err := rand.Int(rand.Reader, big.NewInt(1000000))
|
|
||||||
code := fmt.Sprintf("%06d", c)
|
|
||||||
|
|
||||||
// Generate nonce
|
|
||||||
b := make([]byte, 16)
|
|
||||||
_, err = rand.Read(b)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bytes := hex.EncodeToString(b)
|
|
||||||
|
|
||||||
// Set code-nonce pair in redis first
|
// Generate OTP code
|
||||||
redisClient.Set(code + "nonce", bytes, ttl)
|
c, err := rand.Int(rand.Reader, big.NewInt(1000000))
|
||||||
// Set code-phone_number pair
|
code := fmt.Sprintf("%06d", c)
|
||||||
redisClient.Set(code + "phone", phone, ttl)
|
|
||||||
|
|
||||||
// Send SMS via Twilio
|
// Generate nonce
|
||||||
data := url.Values {}
|
b := make([]byte, 16)
|
||||||
data.Set("MessagingServiceSid", messagingSID)
|
_, err = rand.Read(b)
|
||||||
data.Set("To", phone)
|
if err != nil {
|
||||||
data.Set("Body", fmt.Sprintf("Your OTP for Beep is %s", code))
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
|
|
||||||
url := fmt.Sprintf("https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json", twilioSID)
|
|
||||||
twilioReq, err := http.NewRequest("POST", url, strings.NewReader(data.Encode()))
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
twilioReq.SetBasicAuth(twilioSID, twilioToken)
|
bytes := hex.EncodeToString(b)
|
||||||
twilioReq.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
|
|
||||||
// Twilio uses self-signed certs
|
// Set code-nonce pair in redis first
|
||||||
transport := &http.Transport {
|
redisClient.Set(code+"nonce", bytes, ttl)
|
||||||
TLSClientConfig: &tls.Config{ InsecureSkipVerify: true },
|
// Set code-phone_number pair
|
||||||
}
|
redisClient.Set(code+"phone", phone, ttl)
|
||||||
client := &http.Client{ Transport: transport }
|
|
||||||
resp, err := client.Do(twilioReq)
|
|
||||||
|
|
||||||
if err != nil {
|
// Send SMS via Twilio
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
data := url.Values{}
|
||||||
|
data.Set("MessagingServiceSid", messagingSID)
|
||||||
|
data.Set("To", phone)
|
||||||
|
data.Set("Body", fmt.Sprintf("Your OTP for Beep is %s", code))
|
||||||
|
|
||||||
|
url := fmt.Sprintf("https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json", twilioSID)
|
||||||
|
twilioReq, err := http.NewRequest("POST", url, strings.NewReader(data.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
twilioReq.SetBasicAuth(twilioSID, twilioToken)
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
twilioReq.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return nonce
|
client := &http.Client{}
|
||||||
w.Write([]byte(bytes))
|
resp, err := client.Do(twilioReq)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||||
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return nonce
|
||||||
|
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{}
|
||||||
decoder := json.NewDecoder(r.Body)
|
decoder := json.NewDecoder(r.Body)
|
||||||
err := decoder.Decode(&req)
|
err := decoder.Decode(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get nonce
|
// Get nonce
|
||||||
storedNonce, err := redisClient.Get(req.Code + "nonce").Result()
|
storedNonce, err := redisClient.Get(req.Code + "nonce").Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete nonce
|
// Delete nonce
|
||||||
_, err = redisClient.Del(req.Code + "nonce").Result()
|
_, err = redisClient.Del(req.Code + "nonce").Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check nonce
|
// Check nonce
|
||||||
if req.Nonce != storedNonce {
|
if req.Nonce != storedNonce {
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get stored phone number
|
// Get stored phone number
|
||||||
phoneNumber, err := redisClient.Get(req.Code + "phone").Result()
|
phoneNumber, err := redisClient.Get(req.Code + "phone").Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete stored phone number
|
// Delete stored phone number
|
||||||
_, err = redisClient.Del(req.Code + "phone").Result()
|
_, err = redisClient.Del(req.Code + "phone").Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate (potential) User ID
|
// Generate (potential) User ID
|
||||||
userHex, err := RandomHex()
|
userHex, err := RandomHex()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userIDPotential := "u-" + userHex
|
userIDPotential := "u-" + userHex
|
||||||
|
|
||||||
// Check for existing user
|
// Check for existing user
|
||||||
var userID string
|
var userID string
|
||||||
err = db.QueryRow(`
|
err = db.QueryRow(`
|
||||||
INSERT INTO "user" (id, first_name, last_name, phone_number)
|
INSERT INTO "user" (id, first_name, last_name, phone_number)
|
||||||
VALUES ($1, '', '', $2)
|
VALUES ($1, '', '', $2)
|
||||||
ON CONFLICT(phone_number)
|
ON CONFLICT(phone_number)
|
||||||
DO UPDATE SET phone_number=EXCLUDED.phone_number
|
DO UPDATE SET phone_number=EXCLUDED.phone_number
|
||||||
RETURNING id
|
RETURNING id
|
||||||
`, userIDPotential, phoneNumber).Scan(&userID)
|
`, userIDPotential, phoneNumber).Scan(&userID)
|
||||||
if err != nil {
|
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate JWT
|
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims {
|
|
||||||
"userid": userID,
|
|
||||||
"clientid": req.ClientId,
|
|
||||||
})
|
|
||||||
|
|
||||||
tokenString, err := token.SignedString(privateKey)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims {
|
// Generate JWT
|
||||||
"userid": login.ID,
|
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
|
||||||
"clientid": login.Client,
|
"userid": userID,
|
||||||
})
|
"clientid": req.ClientId,
|
||||||
|
})
|
||||||
|
|
||||||
tokenString, err := token.SignedString(privateKey)
|
tokenString, err := token.SignedString(privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Write([]byte(tokenString))
|
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")
|
||||||
|
|
||||||
// Get nonce
|
// Get nonce
|
||||||
storedNonce, err := redisClient.Get(code + "nonce").Result()
|
storedNonce, err := redisClient.Get(code + "nonce").Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete nonce
|
// Delete nonce
|
||||||
_, err = redisClient.Del(code + "nonce").Result()
|
_, err = redisClient.Del(code + "nonce").Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check nonce
|
// Check nonce
|
||||||
if nonce != storedNonce {
|
if nonce != storedNonce {
|
||||||
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete phone number
|
// Delete phone number
|
||||||
_, err = redisClient.Del(code + "phone").Result()
|
_, err = redisClient.Del(code + "phone").Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyReq, err := http.NewRequest(r.Method, coreURL, r.Body)
|
proxyReq, err := http.NewRequest(r.Method, coreURL, r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyReq.Header.Set("X-User-Claim", dummyToken)
|
proxyReq.Header.Set("X-User-Claim", dummyToken)
|
||||||
for header, values := range r.Header {
|
for header, values := range r.Header {
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
proxyReq.Header.Add(header, value)
|
proxyReq.Header.Add(header, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
proxyRes, err := client.Do(proxyReq)
|
proxyRes, err := client.Do(proxyReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for header, values := range proxyRes.Header {
|
for header, values := range proxyRes.Header {
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
w.Header().Add(header, value)
|
w.Header().Add(header, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
io.Copy(w, proxyRes.Body)
|
io.Copy(w, proxyRes.Body)
|
||||||
proxyRes.Body.Close()
|
proxyRes.Body.Close()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue