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 }