forked from codehakase/golang-gin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
182 lines (157 loc) · 4.69 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package main
import (
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"os"
"strconv"
jwtmiddleware "github.com/auth0/go-jwt-middleware"
jwt "github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/contrib/static"
"github.com/gin-gonic/gin"
)
type Response struct {
Message string `json:"message"`
}
type Jwks struct {
Keys []JSONWebKeys `json:"keys"`
}
type JSONWebKeys struct {
Kty string `json:"kty"`
Kid string `json:"kid"`
Use string `json:"use"`
N string `json:"n"`
E string `json:"e"`
X5c []string `json:"x5c"`
}
type Joke struct {
ID int `json:"id" binding:"required"`
Likes int `json:"likes"`
Joke string `json:"joke" binding:"required"`
}
/** we'll create a list of jokes */
var jokes = []Joke{
Joke{1, 0, "Did you hear about the restaurant on the moon? Great food, no atmosphere."},
Joke{2, 0, "What do you call a fake noodle? An Impasta."},
Joke{3, 0, "How many apples grow on a tree? All of them."},
Joke{4, 0, "Want to hear a joke about paper? Nevermind it's tearable."},
Joke{5, 0, "I just watched a program about beavers. It was the best dam program I've ever seen."},
Joke{6, 0, "Why did the coffee file a police report? It got mugged."},
Joke{7, 0, "How does a penguin build it's house? Igloos it together."},
Joke{8, 0, "Dad, did you get a haircut? No I got them all cut."},
Joke{9, 0, "What do you call a Mexican who has lost his car? Carlos."},
Joke{10, 0, "Dad, can you put my shoes on? No, I don't think they'll fit me."},
Joke{11, 0, "Why did the scarecrow win an award? Because he was outstanding in his field."},
Joke{12, 0, "Why don't skeletons ever go trick or treating? Because they have no body to go with."},
}
var jwtMiddleWare *jwtmiddleware.JWTMiddleware
func main() {
jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
aud := os.Getenv("AUTH0_API_AUDIENCE")
checkAudience := token.Claims.(jwt.MapClaims).VerifyAudience(aud, false)
if !checkAudience {
return token, errors.New("Invalid audience.")
}
// verify iss claim
iss := os.Getenv("AUTH0_DOMAIN")
checkIss := token.Claims.(jwt.MapClaims).VerifyIssuer(iss, false)
if !checkIss {
return token, errors.New("Invalid issuer.")
}
cert, err := getPemCert(token)
if err != nil {
log.Fatalf("could not get cert: %+v", err)
}
result, _ := jwt.ParseRSAPublicKeyFromPEM([]byte(cert))
return result, nil
},
SigningMethod: jwt.SigningMethodRS256,
})
jwtMiddleWare = jwtMiddleware
// Set the router as the default one shipped with Gin
router := gin.Default()
// Serve the frontend
router.Use(static.Serve("/", static.LocalFile("./views", true)))
api := router.Group("/api")
{
api.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})
api.GET("/jokes", authMiddleware(), JokeHandler)
api.POST("/jokes/like/:jokeID", authMiddleware(), LikeJoke)
}
// Start the app
router.Run(":3000")
}
func getPemCert(token *jwt.Token) (string, error) {
cert := ""
resp, err := http.Get(os.Getenv("AUTH0_DOMAIN") + ".well-known/jwks.json")
if err != nil {
return cert, err
}
defer resp.Body.Close()
var jwks = Jwks{}
err = json.NewDecoder(resp.Body).Decode(&jwks)
if err != nil {
return cert, err
}
x5c := jwks.Keys[0].X5c
for k, v := range x5c {
if token.Header["kid"] == jwks.Keys[k].Kid {
cert = "-----BEGIN CERTIFICATE-----\n" + v + "\n-----END CERTIFICATE-----"
}
}
if cert == "" {
return cert, errors.New("unable to find appropriate key")
}
return cert, nil
}
// authMiddleware intercepts the requests, and check for a valid jwt token
func authMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// Get the client secret key
err := jwtMiddleWare.CheckJWT(c.Writer, c.Request)
if err != nil {
// Token not found
fmt.Println(err)
c.Abort()
c.Writer.WriteHeader(http.StatusUnauthorized)
c.Writer.Write([]byte("Unauthorized"))
return
}
}
}
// JokeHandler returns a list of jokes available (in memory)
func JokeHandler(c *gin.Context) {
c.Header("Content-Type", "application/json")
c.JSON(http.StatusOK, jokes)
}
func LikeJoke(c *gin.Context) {
// Check joke ID is valid
if jokeid, err := strconv.Atoi(c.Param("jokeID")); err == nil {
// find joke and increment likes
for i := 0; i < len(jokes); i++ {
if jokes[i].ID == jokeid {
jokes[i].Likes = jokes[i].Likes + 1
}
}
c.JSON(http.StatusOK, &jokes)
} else {
// the jokes ID is invalid
c.AbortWithStatus(http.StatusNotFound)
}
}
// getJokesByID returns a single joke
func getJokesByID(id int) (*Joke, error) {
for _, joke := range jokes {
if joke.ID == id {
return &joke, nil
}
}
return nil, errors.New("Joke not found")
}