Skip to content

Commit 19d4c9b

Browse files
committed
CSRF example, update deps
1 parent 29922f0 commit 19d4c9b

File tree

4 files changed

+93
-24
lines changed

4 files changed

+93
-24
lines changed

cookbook/csrf/main.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"html/template"
6+
"net/http"
7+
8+
"github.com/labstack/echo/v5"
9+
"github.com/labstack/echo/v5/middleware"
10+
)
11+
12+
// 1. Start the program
13+
// 2. Open http://localhost:8080/form in browser
14+
// 3. Submit the form
15+
// 4. Result has submitted token value. It is a random string if your browser is old
16+
// or `_echo_csrf_using_sec_fetch_site_` when you are using a browser that supports the `Sec-Fetch-Site` header
17+
18+
func main() {
19+
e := echo.New()
20+
e.Renderer = &echo.TemplateRenderer{
21+
Template: template.Must(template.New("form.html").Parse(formHTML)),
22+
}
23+
24+
// CSRF middleware:
25+
// - sets a CSRF cookie
26+
// - expects the token in form field named `csrf`
27+
e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{
28+
// IMPORTANT: if you want to submit via hidden form field, include "form:<fieldname>"
29+
// Here we accept token from the form field named "csrf".
30+
TokenLookup: "form:csrf",
31+
CookieName: "_csrf",
32+
CookieHTTPOnly: true,
33+
}))
34+
35+
e.GET("/form", func(c *echo.Context) error {
36+
// Echo CSRF middleware stores the token in the context under the key "csrf".
37+
// We'll render it into the form as a hidden field.
38+
token, err := echo.ContextGet[string](c, "csrf")
39+
if err != nil {
40+
return err
41+
}
42+
data := map[string]any{
43+
"CSRFToken": token,
44+
}
45+
return c.Render(http.StatusOK, "form.html", data)
46+
})
47+
48+
e.POST("/submit", func(c *echo.Context) error {
49+
// If the CSRF token is invalid/missing, middleware returns 403 and this handler is not executed.
50+
name := c.FormValue("name")
51+
formToken := c.FormValue("csrf")
52+
return c.String(http.StatusOK, fmt.Sprintf("OK, submitted name: '%s', token value in form: '%s'", name, formToken))
53+
})
54+
55+
if err := e.Start(":8080"); err != nil {
56+
e.Logger.Error("failed to start server: ", "error", err)
57+
}
58+
}
59+
60+
const formHTML = `
61+
{{ define "form.html" }}
62+
<!doctype html>
63+
<html>
64+
<head><meta charset="utf-8"><title>Echo CSRF Form</title></head>
65+
<body>
66+
<h1>CSRF Hidden Field Example</h1>
67+
68+
<form method="POST" action="/submit">
69+
<input type="hidden" name="csrf" value="{{ .CSRFToken }}">
70+
<label>Name: <input type="text" name="name" /></label>
71+
<button type="submit">Submit</button>
72+
</form>
73+
74+
</body>
75+
</html>
76+
{{ end }}
77+
`

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ module github.com/labstack/echox
33
go 1.25.0
44

55
require (
6+
github.com/casbin/casbin/v3 v3.10.0
67
github.com/golang-jwt/jwt/v5 v5.3.1
78
github.com/gorilla/websocket v1.5.3
8-
github.com/labstack/echo-contrib/v5 v5.0.0
9-
github.com/labstack/echo-jwt/v5 v5.0.0
10-
github.com/labstack/echo/v5 v5.0.3
9+
github.com/labstack/echo-contrib/v5 v5.0.1
10+
github.com/labstack/echo-jwt/v5 v5.0.1
11+
github.com/labstack/echo/v5 v5.0.4
1112
github.com/lestrrat-go/jwx/v3 v3.0.13
1213
github.com/prometheus/client_golang v1.23.2
1314
github.com/r3labs/sse/v2 v2.10.0
@@ -19,7 +20,6 @@ require (
1920
require (
2021
github.com/beorn7/perks v1.0.1 // indirect
2122
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
22-
github.com/casbin/casbin/v3 v3.10.0 // indirect
2323
github.com/casbin/govaluate v1.10.0 // indirect
2424
github.com/cespare/xxhash/v2 v2.3.0 // indirect
2525
github.com/davecgh/go-spew v1.1.1 // indirect

go.sum

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvw
1818
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
1919
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
2020
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
21-
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
22-
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
2321
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
2422
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
2523
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
@@ -36,14 +34,12 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
3634
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
3735
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
3836
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
39-
github.com/labstack/echo-contrib/v5 v5.0.0 h1:ZukJ7gzW/gEe9ZiqpSQGAkRR8E35eTvu1PQBjmp2tDs=
40-
github.com/labstack/echo-contrib/v5 v5.0.0/go.mod h1:oUtPer7/M+vUJjDATlgVUhHvVUDc7Nh/4Xs+/m52OKA=
41-
github.com/labstack/echo-jwt/v5 v5.0.0 h1:uPp+FpkI/PKpMPPygtnK3RQOpg5a2wlM04UgfpWLVyI=
42-
github.com/labstack/echo-jwt/v5 v5.0.0/go.mod h1:RYF2ojWXbaY09QQ5J9vVtPUtkyI5UztS0gJotmCRz/U=
43-
github.com/labstack/echo/v5 v5.0.1 h1:60L7x1KMWRIJuaFqvnEHH322g+YnsMWq5Rzaeo6lcP4=
44-
github.com/labstack/echo/v5 v5.0.1/go.mod h1:SyvlSdObGjRXeQfCCXW/sybkZdOOQZBmpKF0bvALaeo=
45-
github.com/labstack/echo/v5 v5.0.3 h1:Jql8sDtCYXrhh2Mbs6jKwjR6r7X8FSQQmch+w6QS7kc=
46-
github.com/labstack/echo/v5 v5.0.3/go.mod h1:SyvlSdObGjRXeQfCCXW/sybkZdOOQZBmpKF0bvALaeo=
37+
github.com/labstack/echo-contrib/v5 v5.0.1 h1:Z23m8p1F9Doax+pa8ek8ll5d6wvzCbvrAn25ZWmSgrE=
38+
github.com/labstack/echo-contrib/v5 v5.0.1/go.mod h1:ajrqEwSloW0vQSTfJ4j9u4tHoS+dg4umCDPxuTvChZs=
39+
github.com/labstack/echo-jwt/v5 v5.0.1 h1:uIpCHCiDPN3jA8Jb47i4EViToUl1uypMiPvVAAgKpIw=
40+
github.com/labstack/echo-jwt/v5 v5.0.1/go.mod h1:kcHmJPzrVSEJa1FRheVoi9EJrBLLUqr1ntlil6uPe1Q=
41+
github.com/labstack/echo/v5 v5.0.4 h1:ll3I/O8BifjMztj9dD1vx/peZQv8cR2CTUdQK6QxGGc=
42+
github.com/labstack/echo/v5 v5.0.4/go.mod h1:SyvlSdObGjRXeQfCCXW/sybkZdOOQZBmpKF0bvALaeo=
4743
github.com/lestrrat-go/blackmagic v1.0.4 h1:IwQibdnf8l2KoO+qC3uT4OaTWsW7tuRQXy9TRN9QanA=
4844
github.com/lestrrat-go/blackmagic v1.0.4/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw=
4945
github.com/lestrrat-go/dsig v1.0.0 h1:OE09s2r9Z81kxzJYRn07TFM9XA4akrUdoMwr0L8xj38=
@@ -52,8 +48,6 @@ github.com/lestrrat-go/dsig-secp256k1 v1.0.0 h1:JpDe4Aybfl0soBvoVwjqDbp+9S1Y2OM7
5248
github.com/lestrrat-go/dsig-secp256k1 v1.0.0/go.mod h1:CxUgAhssb8FToqbL8NjSPoGQlnO4w3LG1P0qPWQm/NU=
5349
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
5450
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
55-
github.com/lestrrat-go/httprc/v3 v3.0.3 h1:WjLHWkDkgWXeIUrKi/7lS/sGq2DjkSAwdTbH5RHXAKs=
56-
github.com/lestrrat-go/httprc/v3 v3.0.3/go.mod h1:mSMtkZW92Z98M5YoNNztbRGxbXHql7tSitCvaxvo9l0=
5751
github.com/lestrrat-go/httprc/v3 v3.0.4 h1:pXyH2ppK8GYYggygxJ3TvxpCZnbEUWc9qSwRTTApaLA=
5852
github.com/lestrrat-go/httprc/v3 v3.0.4/go.mod h1:mSMtkZW92Z98M5YoNNztbRGxbXHql7tSitCvaxvo9l0=
5953
github.com/lestrrat-go/jwx/v3 v3.0.13 h1:AdHKiPIYeCSnOJtvdpipPg/0SuFh9rdkN+HF3O0VdSk=
@@ -90,23 +84,15 @@ go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
9084
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
9185
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
9286
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
93-
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
94-
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
9587
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
9688
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
9789
golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
98-
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
99-
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
10090
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
10191
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
10292
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
103-
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
104-
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
10593
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
10694
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
10795
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
108-
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
109-
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
11096
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
11197
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
11298
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=

website/docs/middleware/csrf.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,9 @@ var DefaultCSRFConfig = CSRFConfig{
178178
CookieSameSite: http.SameSiteDefaultMode,
179179
}
180180
```
181+
182+
## Full example
183+
184+
```go reference
185+
https://github.com/labstack/echox/blob/master/cookbook/csrf/main.go
186+
```

0 commit comments

Comments
 (0)