Skip to content

Commit 38159b7

Browse files
committed
initial commit
0 parents  commit 38159b7

File tree

6 files changed

+234
-0
lines changed

6 files changed

+234
-0
lines changed

go.mod

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module golangjwt
2+
3+
go 1.19
4+
5+
require (
6+
github.com/go-playground/validator/v10 v10.11.1
7+
github.com/golang-jwt/jwt v3.2.2+incompatible
8+
)
9+
10+
require (
11+
github.com/go-playground/locales v0.14.0 // indirect
12+
github.com/go-playground/universal-translator v0.18.0 // indirect
13+
github.com/leodido/go-urn v1.2.1 // indirect
14+
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
15+
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect
16+
golang.org/x/text v0.3.7 // indirect
17+
)

go.sum

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5+
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
6+
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
7+
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
8+
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
9+
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
10+
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
11+
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
12+
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
13+
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
14+
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
15+
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
16+
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
17+
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
18+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
19+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
20+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
21+
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
22+
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
23+
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
24+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
25+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
26+
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
27+
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
28+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
29+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
30+
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
31+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
32+
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
33+
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
34+
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
35+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
36+
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
37+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
38+
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU=
39+
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
40+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
41+
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
42+
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
43+
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
44+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
45+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
46+
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
47+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
48+
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
49+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
50+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
51+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

handlers/handlers.go

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package handlers
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
)
7+
8+
type message struct {
9+
Status string `json:"status"`
10+
Info string `json:"info"`
11+
}
12+
13+
func HandlePage(w http.ResponseWriter, r *http.Request) {
14+
w.Header().Set("Content-Type", "application/json")
15+
var msg message
16+
err := json.NewDecoder(r.Body).Decode(&msg)
17+
if err != nil {
18+
panic(err)
19+
}
20+
r.Body.Close()
21+
err = json.NewEncoder(w).Encode(msg)
22+
if err != nil {
23+
panic(err)
24+
}
25+
}
26+
27+
func ReservedPage(w http.ResponseWriter, r *http.Request) {
28+
w.Header().Set("Content-Type", "application/json")
29+
res := &message{Status: "private endpoint", Info: "this is a private endpoint, you must be authenticated for seeing it"}
30+
err := json.NewEncoder(w).Encode(res)
31+
if err != nil {
32+
panic(err)
33+
}
34+
}

handlers/login.go

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package handlers
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
"time"
7+
8+
"github.com/go-playground/validator/v10"
9+
"github.com/golang-jwt/jwt"
10+
)
11+
12+
// this key has to be kept secure. Whoever will have this key can authenticate our users
13+
var secretKey = []byte("Abcd1234!!")
14+
15+
type tokenRes struct {
16+
Token string `json:"token"`
17+
}
18+
19+
type tokenReq struct {
20+
Username string `json:"username" validate:"required"`
21+
Password string `json:"password" validate:"required"`
22+
}
23+
24+
func generateToken(username, password string) (string, error) {
25+
// TODO: here you can add logic to check against a DB
26+
//...
27+
28+
// create a new token by providing the cryptographic algorithm
29+
token := jwt.New(jwt.SigningMethodHS256)
30+
31+
// set default/custom claims
32+
claims := token.Claims.(jwt.MapClaims)
33+
claims["exp"] = time.Now().Add(10 * time.Minute).Unix()
34+
claims["username"] = username
35+
claims["password"] = password
36+
37+
tokenString, err := token.SignedString(secretKey)
38+
if err != nil {
39+
return "", err
40+
}
41+
return tokenString, nil
42+
}
43+
44+
func Login(w http.ResponseWriter, r *http.Request) {
45+
w.Header().Set("Content-Type", "application/json")
46+
47+
var req tokenReq
48+
err := json.NewDecoder(r.Body).Decode(&req)
49+
if err != nil {
50+
panic(err)
51+
}
52+
53+
r.Body.Close()
54+
55+
validator := validator.New()
56+
if err = validator.Struct(&req); err != nil {
57+
panic(err)
58+
}
59+
60+
bearerToken, err := generateToken(req.Username, req.Password)
61+
if err != nil {
62+
panic(err)
63+
}
64+
65+
res := &tokenRes{Token: bearerToken}
66+
err = json.NewEncoder(w).Encode(res)
67+
if err != nil {
68+
panic(err)
69+
}
70+
}

handlers/verify.go

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package handlers
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"strings"
7+
8+
"github.com/golang-jwt/jwt"
9+
)
10+
11+
func IsAuthorized(endpoint func(w http.ResponseWriter, r *http.Request)) http.HandlerFunc {
12+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
13+
// check if there is the token
14+
if r.Header["Authorization"] != nil {
15+
16+
// parse the token
17+
token, err := jwt.Parse(strings.Replace(r.Header["Authorization"][0], "Bearer ", "", 1), func(token *jwt.Token) (interface{}, error) {
18+
_, ok := token.Method.(*jwt.SigningMethodHMAC)
19+
if !ok {
20+
w.WriteHeader(http.StatusUnauthorized)
21+
w.Write([]byte(fmt.Sprintf("unexpected signing method: %v", token.Header["alg"])))
22+
}
23+
return secretKey, nil
24+
})
25+
// err while parsing the token
26+
if err != nil {
27+
w.WriteHeader(http.StatusUnauthorized)
28+
w.Write([]byte("err while parsing the jwt token!"))
29+
return
30+
}
31+
32+
// token valid
33+
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
34+
fmt.Printf("username: %q\n", claims["username"])
35+
fmt.Printf("password: %q\n", claims["password"])
36+
endpoint(w, r)
37+
return
38+
}
39+
40+
}
41+
w.WriteHeader(http.StatusUnauthorized)
42+
w.Write([]byte("you must provide the jwt token!"))
43+
})
44+
}

main.go

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
"golangjwt/handlers"
8+
)
9+
10+
func main() {
11+
http.HandleFunc("/home", handlers.HandlePage)
12+
http.HandleFunc("/login", handlers.Login)
13+
http.HandleFunc("/reserved", handlers.IsAuthorized(handlers.ReservedPage))
14+
err := http.ListenAndServe(":8000", nil)
15+
if err != nil {
16+
panic(fmt.Sprintf("err while listening on port 8000, err: %v", err))
17+
}
18+
}

0 commit comments

Comments
 (0)