2fas-server/internal/pass/sync/handlers.go
Krzysztof Dryś 34d87a852a
feat/sync endpoint (#34)
feat: add sync endpoint to pass
2024-04-05 11:31:40 +02:00

143 lines
4.2 KiB
Go

package sync
import (
"errors"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/twofas/2fas-server/internal/common/logging"
"github.com/twofas/2fas-server/internal/pass/connection"
)
func ExtensionRequestSync(syncingApp *Syncing) gin.HandlerFunc {
return func(gCtx *gin.Context) {
token, err := connection.TokenFromWSProtocol(gCtx.Request)
if err != nil {
logging.Errorf("Failed to get token from request: %v", err)
gCtx.Status(http.StatusForbidden)
return
}
fcmToken, err := syncingApp.VerifyExtRequestSyncToken(gCtx, token)
if err != nil {
logging.Errorf("Failed to verify proxy token: %v", err)
gCtx.String(http.StatusUnauthorized, "Invalid auth token")
return
}
if err := syncingApp.ServeSyncingRequestWS(gCtx.Writer, gCtx.Request, fcmToken); err != nil {
logging.Errorf("Failed to verify proxy token: %v", err)
gCtx.Status(http.StatusInternalServerError)
return
}
}
}
func ExtensionProxyWSHandler(syncingApp *Syncing, proxy *connection.ProxyServer) gin.HandlerFunc {
return func(gCtx *gin.Context) {
token, err := connection.TokenFromWSProtocol(gCtx.Request)
if err != nil {
logging.Errorf("Failed to get token from request: %v", err)
gCtx.Status(http.StatusForbidden)
return
}
fcmToken, err := syncingApp.VerifyExtSyncToken(gCtx, token)
if err != nil {
logging.Errorf("Failed to verify proxy token: %v", err)
gCtx.Status(http.StatusInternalServerError)
return
}
ok := syncingApp.isSyncConfirmed(gCtx, fcmToken)
if !ok {
gCtx.String(http.StatusForbidden, "Syncing is not yet done")
return
}
if err := proxy.ServeExtensionProxyToMobileWS(gCtx.Writer, gCtx.Request, fcmToken); err != nil {
logging.Errorf("Failed to serve ws: %v", err)
gCtx.Status(http.StatusInternalServerError)
}
}
}
func MobileConfirmHandler(syncApp *Syncing) gin.HandlerFunc {
return func(gCtx *gin.Context) {
token, err := tokenFromRequest(gCtx)
if err != nil {
logging.Errorf("Failed to get token from request: %v", err)
gCtx.Status(http.StatusForbidden)
return
}
fcmToken, err := syncApp.VerifyMobileSyncConfirmToken(gCtx, token)
if err != nil {
logging.Errorf("Failed to verify connection token: %v", err)
gCtx.Status(http.StatusUnauthorized)
return
}
resp, err := syncApp.confirmSync(gCtx, fcmToken)
if err != nil {
if errors.Is(err, noSyncRequestErr) {
gCtx.String(http.StatusBadRequest, "no sync request was created for this token")
return
}
logging.Errorf("Failed to ConfirmPairing: %v", err)
gCtx.Status(http.StatusInternalServerError)
return
}
gCtx.JSON(http.StatusOK, resp)
}
}
func MobileProxyWSHandler(syncingApp *Syncing, proxy *connection.ProxyServer) gin.HandlerFunc {
return func(gCtx *gin.Context) {
token, err := connection.TokenFromWSProtocol(gCtx.Request)
if err != nil {
logging.Errorf("Failed to get token from request: %v", err)
gCtx.Status(http.StatusForbidden)
return
}
fcmToken, err := syncingApp.VerifyMobileSyncConfirmToken(gCtx, token)
if err != nil {
logging.Errorf("Invalid connection token: %v", err)
gCtx.Status(http.StatusUnauthorized)
return
}
ok := syncingApp.isSyncConfirmed(gCtx, fcmToken)
if !ok {
gCtx.String(http.StatusForbidden, "Syncing is not yet done")
return
}
if err := proxy.ServeMobileProxyToExtensionWS(gCtx.Writer, gCtx.Request, fcmToken); err != nil {
logging.Errorf("Failed to serve ws: %v", err)
gCtx.Status(http.StatusInternalServerError)
}
}
}
func MobileGenerateSyncToken(syncingApp *Syncing) gin.HandlerFunc {
return func(gCtx *gin.Context) {
fcm := gCtx.Param("fcm")
if fcm == "" {
gCtx.Status(http.StatusBadRequest)
return
}
if err := syncingApp.sendMobileToken(fcm, gCtx.Writer); err != nil {
logging.Errorf("Failed to send mobile token: %v", err)
gCtx.Status(http.StatusInternalServerError)
}
}
}
func tokenFromRequest(gCtx *gin.Context) (string, error) {
tokenHeader := gCtx.GetHeader("Authorization")
if tokenHeader == "" {
return "", errors.New("missing Authorization header")
}
splitToken := strings.Split(tokenHeader, "Bearer ")
if len(splitToken) != 2 {
gCtx.Status(http.StatusForbidden)
return "", errors.New("missing 'Bearer: value'")
}
return splitToken[1], nil
}