commit 2efc3dfdfa73e28016b0bc0e50a5a1d8721a4ee9
parent 8278029fb1687f525a373aa3bd0a479d5368eb68
Author: MTRNord <mtrnord1@gmail.com>
Date: Sat, 31 Mar 2018 16:15:30 +0200
Add JWT Token as response
Diffstat:
2 files changed, 115 insertions(+), 47 deletions(-)
diff --git a/api/login/twitter.go b/api/login/twitter.go
@@ -1,12 +1,18 @@
package login
import (
+ "encoding/json"
+ "fmt"
+ "github.com/SocialNetworkNews/SocialNetworkNews_API/db"
"github.com/dghubble/gologin"
libLogin "github.com/dghubble/gologin/oauth1"
oauth1Login "github.com/dghubble/gologin/oauth1"
"github.com/dghubble/gologin/twitter"
"github.com/dghubble/oauth1"
"github.com/dghubble/sessions"
+ "github.com/dgraph-io/badger"
+ "github.com/dgrijalva/jwt-go"
+ "github.com/satori/go.uuid"
"log"
"net/http"
)
@@ -15,13 +21,81 @@ var TConfig *oauth1.Config
const (
sessionName = "ssn-app"
- sessionSecret = "example cookie signing secret"
+ sessionSecret = "006b2294-201d-4283-9114-149b3347b264"
sessionUserKey = "twitterID"
)
// sessionStore encodes and decodes session data stored in signed cookies
var sessionStore = sessions.NewCookieStore([]byte(sessionSecret), nil)
+func getUserSecret(id string) (string, error) {
+ var secret string
+ dataDB, err := db.OpenDB()
+ if err != nil {
+ return "", err
+ }
+
+ DBerr := dataDB.View(func(txn *badger.Txn) error {
+ data, err := db.Get(txn, []byte(fmt.Sprintf("users|%s|data", id)))
+ secret = fmt.Sprintf("%s", data)
+ return err
+ })
+
+ return secret, DBerr
+}
+
+func saveUser(id, accessToken, accessSecret string, data []byte) error {
+ dataDB, err := db.OpenDB()
+ if err != nil {
+ return err
+ }
+
+ return dataDB.Update(func(txn *badger.Txn) error {
+ ATerr := txn.Set([]byte(fmt.Sprintf("users|%s|accessToken", id)), []byte(accessToken))
+ if ATerr != nil {
+ return ATerr
+ }
+
+ ASerr := txn.Set([]byte(fmt.Sprintf("users|%s|accessSecret", id)), []byte(accessSecret))
+ if ASerr != nil {
+ return ASerr
+ }
+
+ puuid, UUIDerr := uuid.NewV4()
+ if UUIDerr != nil {
+ return UUIDerr
+ }
+ newUUID := puuid.String()
+
+ USerr := txn.Set([]byte(fmt.Sprintf("users|%s|userSecret", id)), []byte(newUUID))
+ if USerr != nil {
+ return USerr
+ }
+
+ return txn.Set([]byte(fmt.Sprintf("users|%s|data", id)), []byte(data))
+ })
+}
+
+func checkUserExists(id string) (bool, error) {
+ exists := true
+ dataDB, err := db.OpenDB()
+ if err != nil {
+ return true, err
+ }
+
+ dbErr := dataDB.View(func(txn *badger.Txn) error {
+ _, QueryErr := txn.Get([]byte(fmt.Sprintf("users|%s", id)))
+ if QueryErr != nil && QueryErr != badger.ErrKeyNotFound {
+ return QueryErr
+ }
+ if QueryErr == badger.ErrKeyNotFound {
+ exists = false
+ }
+ return nil
+ })
+ return exists, dbErr
+}
+
// issueSession issues a cookie session after successful Twitter login
func IssueSession() http.Handler {
fn := func(w http.ResponseWriter, req *http.Request) {
@@ -31,10 +105,50 @@ func IssueSession() http.Handler {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
+ if exists, err := checkUserExists(twitterUser.IDStr); !exists {
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ accessToken, accessSecret, err := oauth1Login.AccessTokenFromContext(ctx)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ b, err := json.Marshal(twitterUser)
+ if err != nil {
+ fmt.Println("error:", err)
+ }
+
+ SErr := saveUser(twitterUser.IDStr, accessToken, accessSecret, b)
+ if SErr != nil {
+ http.Error(w, SErr.Error(), http.StatusInternalServerError)
+ return
+ }
+ }
+
+ // Create a new token object, specifying signing method and the claims
+ // you would like it to contain.
+ token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
+ "loggedIn": "true",
+ })
+
+ secret, err := getUserSecret(twitterUser.IDStr)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ // Sign and get the complete encoded token as a string using the secret
+ tokenString, err := token.SignedString(secret)
+
// 2. Implement a success handler to issue some form of session
session := sessionStore.New(sessionName)
session.Values[sessionUserKey] = twitterUser.ID
session.Save(w)
+ w.Header().Set("Authorization", "Bearer "+tokenString)
domain := req.Header.Get("Host")
http.Redirect(w, req, domain, http.StatusFound)
}
diff --git a/db/passwords/passwords.go b/db/passwords/passwords.go
@@ -1,46 +0,0 @@
-package passwords
-
-import (
- "fmt"
- "github.com/SocialNetworkNews/SocialNetworkNews_API/db"
- "github.com/dgraph-io/badger"
- "golang.org/x/crypto/bcrypt"
-)
-
-func SavePassword(password, username string) error {
- hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
- if err != nil {
- return err
- }
-
- userDB, err := db.OpenDB()
- if err != nil {
- return err
- }
-
- return userDB.Update(func(txn *badger.Txn) error {
- return txn.Set([]byte(fmt.Sprintf("users|%s|password", username)), hash)
- })
-}
-
-func CheckPassword(username, password string) (bool, error) {
- userDB, err := db.OpenDB()
- if err != nil {
- return false, err
- }
- var hash []byte
-
- DBErr := userDB.View(func(txn *badger.Txn) error {
- var err error
- hash, err = db.Get(txn, []byte(fmt.Sprintf("users|%s|password", username)))
- return err
- })
- if DBErr != nil {
- return false, DBErr
- }
-
- if err := bcrypt.CompareHashAndPassword(hash, []byte(password)); err != nil {
- return false, err
- }
- return true, nil
-}