diff --git a/web/scheduler/server/backup_controller.go b/web/scheduler/server/backup_controller.go index 3c4f3f9..b93deb2 100644 --- a/web/scheduler/server/backup_controller.go +++ b/web/scheduler/server/backup_controller.go @@ -10,7 +10,11 @@ import ( ) const ( - ErrRetrievingOauthCode = "error retrieving oauth login credentials; try again" + ErrRetrievingOauthCode = "error retrieving oauth login credentials; try again" + ErrCreatingPortwardenUser = "error creating a portwarden user" + + FrontEndBaseAddressTest = "http://localhost:8000/" + FrontEndBaseAddressProd = "" ) func EncryptBackupHandler(c *gin.Context) { @@ -51,14 +55,15 @@ func (ps *PortwardenServer) GetGoogleDriveLoginHandler(c *gin.Context) { c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error(), "message": "Login failure"}) return } - // pu := &PortwardenUser{GoogleToken: tok} - body, err := GetUserInfo(tok) + pu := &PortwardenUser{GoogleToken: tok} + err = pu.CreateWithGoogle() if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "message": ""}) + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(), "message": ErrCreatingPortwardenUser}) return } - spew.Dump(string(body)) - c.JSON(200, "Login Successful") + + spew.Dump(pu) + c.Redirect(http.StatusMovedPermanently, FrontEndBaseAddressTest+"?access_token="+pu.GoogleToken.AccessToken) return } diff --git a/web/scheduler/server/google_drive.go b/web/scheduler/server/google_drive.go index c843916..e5481c8 100644 --- a/web/scheduler/server/google_drive.go +++ b/web/scheduler/server/google_drive.go @@ -182,39 +182,6 @@ func UploadFile(fileBytes []byte, client *http.Client, token *oauth2.Token) erro return nil } -func GetUserInfo(token *oauth2.Token) ([]byte, error) { - - postURL := "https://www.googleapis.com/oauth2/v2/userinfo" - - // Extract auth or access token from Token file - // See https://godoc.org/gnolang.org/x/oauth2#Token - // authToken := token.AccessToken - - // Post to Drive with RESTful method - request, err := http.NewRequest("GET", postURL, nil) - if err != nil { - return nil, err - } - request.Header.Add("Host", "www.googleapis.com") - request.Header.Add("Authorization", "Bearer "+"authToken") - request.Header.Add("Content-Length", strconv.FormatInt(request.ContentLength, 10)) - - // For debugging - //fmt.Println(request) - GoogleDriveClient := GoogleDriveAppConfig.Client(oauth2.NoContext, token) - response, err := GoogleDriveClient.Do(request) - if err != nil { - return nil, err - } - - defer response.Body.Close() - body, err := ioutil.ReadAll(response.Body) - if err != nil { - return nil, err - } - return body, nil -} - /* func main() { diff --git a/web/scheduler/server/middleware.go b/web/scheduler/server/middleware.go index e64926f..0a87b01 100644 --- a/web/scheduler/server/middleware.go +++ b/web/scheduler/server/middleware.go @@ -1,11 +1,11 @@ package server import ( - "fmt" "net/http" + "strconv" + "strings" "github.com/gin-gonic/gin" - "golang.org/x/oauth2" ) const ( @@ -14,23 +14,19 @@ const ( func TokenAuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { - fmt.Println("middleware called") - code := c.Query("code") + var token string + HeaderAuthorization, ok := c.Request.Header["Authorization"] + if ok && len(HeaderAuthorization) >= 1 { + token = HeaderAuthorization[0] + token = strings.TrimPrefix(token, "Bearer ") + } - tok, err := GoogleDriveAppConfig.Exchange(oauth2.NoContext, code) - if err != nil { - c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error(), "message": "Login failure"}) + verified, err := VerifyGoogleAccessToekn(token) + if err != nil || !verified { + c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error(), "message": "Verification status is " + strconv.FormatBool(verified)}) c.Abort() return } - _, err = GetUserInfo(tok) - if err != nil { - c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error(), "message": "Login failure"}) - c.Abort() - return - } - c.Set(GoogleOauth2TokenContextVariableName, tok) - fmt.Println("middleware passed") c.Next() } } diff --git a/web/scheduler/server/model.go b/web/scheduler/server/model.go index 2aa2d07..a71ae28 100644 --- a/web/scheduler/server/model.go +++ b/web/scheduler/server/model.go @@ -2,6 +2,7 @@ package server import ( "encoding/json" + "errors" "io/ioutil" "mime/multipart" "net/http" @@ -26,6 +27,17 @@ type DecryptBackupInfo struct { Passphrase string `form:"passphrase"` } +type GoogleTokenVerifyResponse struct { + IssuedTo string `json:"issued_to"` + Audience string `json:"audience"` + UserID string `json:"user_id"` + Scope string `json:"scope"` + ExpiresIn int64 `json:"expires_in"` + Email string `json:"email"` + VerifiedEmail bool `json:"verified_email"` + AccessType string `json:"access_type"` +} + type GoogleDriveCredentials struct { State string `form:"state"` Code string `form:"code"` @@ -80,3 +92,24 @@ func (pu *PortwardenUser) CreateWithGoogle() error { pu.Email = pu.GoogleUserInfo.Email return nil } + +func VerifyGoogleAccessToekn(access_token string) (bool, error) { + url := "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=" + access_token + response, err := http.Get(url) + defer response.Body.Close() + if err != nil { + return false, err + } + body, err := ioutil.ReadAll(response.Body) + if err != nil { + return false, err + } + var gtvr GoogleTokenVerifyResponse + if err := json.Unmarshal(body, >vr); err != nil { + return false, err + } + if !gtvr.VerifiedEmail { + return false, errors.New(string(body)) + } + return true, nil +} diff --git a/web/scheduler/server/server.go b/web/scheduler/server/server.go index 2b74203..a4a4b78 100644 --- a/web/scheduler/server/server.go +++ b/web/scheduler/server/server.go @@ -57,11 +57,16 @@ func (ps *PortwardenServer) Run() { http.ServeFile(c.Writer, c.Request, "index.html") }) - ps.Router.POST("/encrypt", EncryptBackupHandler) ps.Router.POST("/decrypt", DecryptBackupHandler) ps.Router.GET("/gdrive/loginUrl", ps.GetGoogleDriveLoginURLHandler) ps.Router.GET("/gdrive/login", ps.GetGoogleDriveLoginHandler) + ps.Router.Use(TokenAuthMiddleware()) + ps.Router.GET("/test/TokenAuthMiddleware", func(c *gin.Context) { + c.JSON(200, "success") + }) + ps.Router.POST("/encrypt", EncryptBackupHandler) + ps.Router.Run(":" + strconv.Itoa(ps.Port)) }