github.com/Ptt-official-app/go-bbs@v0.12.0/serverlet/route_token.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"log"
     7  	"net/http"
     8  	"strings"
     9  
    10  	"github.com/Ptt-official-app/go-bbs"
    11  	"github.com/golang-jwt/jwt"
    12  )
    13  
    14  func routeToken(w http.ResponseWriter, r *http.Request) {
    15  	if r.Method == "POST" {
    16  		postToken(w, r)
    17  		return
    18  	}
    19  
    20  }
    21  
    22  func postToken(w http.ResponseWriter, r *http.Request) {
    23  
    24  	r.ParseForm()
    25  
    26  	username := r.FormValue("username")
    27  	password := r.FormValue("password")
    28  
    29  	userec, err := findUserecByID(username)
    30  	if err != nil {
    31  		m := map[string]string{
    32  			"error":             "grant_error",
    33  			"error_description": err.Error(),
    34  		}
    35  		b, _ := json.MarshalIndent(m, "", "  ")
    36  		w.Write(b)
    37  		return
    38  
    39  	}
    40  
    41  	log.Println("found user:", userec)
    42  	err = verifyPassword(userec, password)
    43  	if err != nil {
    44  
    45  		// TODO: add delay, warning, notify user
    46  
    47  		m := map[string]string{
    48  			"error":             "grant_error",
    49  			"error_description": err.Error(),
    50  		}
    51  		b, _ := json.MarshalIndent(m, "", "  ")
    52  		w.Write(b)
    53  		return
    54  	}
    55  
    56  	// Generate Access Token
    57  	token := newAccessTokenWithUsername(username)
    58  	m := map[string]string{
    59  		"access_token": token,
    60  		"token_type":   "bearer",
    61  	}
    62  
    63  	b, _ := json.MarshalIndent(m, "", "  ")
    64  
    65  	w.Write(b)
    66  
    67  }
    68  
    69  func findUserecByID(userid string) (bbs.UserRecord, error) {
    70  	for _, it := range userRecs {
    71  		if userid == it.UserID() {
    72  			return it, nil
    73  		}
    74  	}
    75  	return nil, fmt.Errorf("user record not found")
    76  }
    77  
    78  func verifyPassword(userec bbs.UserRecord, password string) error {
    79  	log.Println("password", userec.HashedPassword())
    80  	return userec.VerifyPassword(password)
    81  }
    82  
    83  func getTokenFromRequest(r *http.Request) string {
    84  	a := r.Header.Get("Authorization")
    85  	s := strings.Split(a, " ")
    86  	if len(s) < 2 {
    87  		log.Println("getTokenFromRequest error: len(s) < 2, got", len(s))
    88  		return ""
    89  	}
    90  	return s[1]
    91  }
    92  
    93  func newAccessTokenWithUsername(username string) string {
    94  	claims := &jwt.StandardClaims{
    95  		ExpiresAt: 30 * 60, // TODO: Setting me in config
    96  		// Issuer:    "test",
    97  		Subject: username,
    98  	}
    99  
   100  	// TODO: Setting me in config
   101  	// openssl ecparam -name prime256v1 -genkey -noout -out pkey
   102  	privateKey := `-----BEGIN EC PRIVATE KEY-----
   103  MHcCAQEEIABVEwM0EuOpmOoe803/vYswLUtsaR71xfGzk06TGBy/oAoGCCqGSM49
   104  AwEHoUQDQgAEV8qJS5x98i0eM+UUiV5qB2JZhT67Ojl6/rZ4xKcHM/NLpUJP3wDp
   105  eFQfMaMiAKQHoGs6rk5z1l/tUUVjJWrw0A==
   106  -----END EC PRIVATE KEY-----`
   107  
   108  	// openssl ec -in pkey -pubout
   109  	// 	publicKey := `-----BEGIN PUBLIC KEY-----
   110  	// MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEV8qJS5x98i0eM+UUiV5qB2JZhT67
   111  	// Ojl6/rZ4xKcHM/NLpUJP3wDpeFQfMaMiAKQHoGs6rk5z1l/tUUVjJWrw0A==
   112  	// -----END PUBLIC KEY-----`
   113  
   114  	key, err := jwt.ParseECPrivateKeyFromPEM([]byte(privateKey))
   115  	if err != nil {
   116  		log.Println("parse private key failed:", err)
   117  		return ""
   118  	}
   119  
   120  	token := jwt.NewWithClaims(jwt.SigningMethodES256, claims)
   121  	ss, err := token.SignedString(key)
   122  	if err != nil {
   123  		log.Println("sign token failed:", err)
   124  		return ""
   125  	}
   126  	return ss
   127  }