Implementing signed links for email message
This commit is contained in:
parent
2642f706bf
commit
7a7a823715
@ -31,6 +31,8 @@ type config struct {
|
|||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
}
|
}
|
||||||
|
secretkey string
|
||||||
|
frontend string
|
||||||
}
|
}
|
||||||
|
|
||||||
type application struct {
|
type application struct {
|
||||||
@ -79,6 +81,8 @@ func main() {
|
|||||||
flag.IntVar(&cfg.smtp.port, "smtpport", 1025, "smtp host")
|
flag.IntVar(&cfg.smtp.port, "smtpport", 1025, "smtp host")
|
||||||
flag.StringVar(&cfg.smtp.username, "smtpuser", "user", "smtp user")
|
flag.StringVar(&cfg.smtp.username, "smtpuser", "user", "smtp user")
|
||||||
flag.StringVar(&cfg.smtp.password, "smtppwd", "password", "smtp password")
|
flag.StringVar(&cfg.smtp.password, "smtppwd", "password", "smtp password")
|
||||||
|
flag.StringVar(&cfg.secretkey, "secret", "secRetKeY", "secret key")
|
||||||
|
flag.StringVar(&cfg.frontend, "frontend", "http://localhost:4000", "frontend address")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@ -5,6 +5,7 @@ go 1.22.5
|
|||||||
require (
|
require (
|
||||||
github.com/alexedwards/scs/mysqlstore v0.0.0-20240316134038-7e11d57e8885
|
github.com/alexedwards/scs/mysqlstore v0.0.0-20240316134038-7e11d57e8885
|
||||||
github.com/alexedwards/scs/v2 v2.8.0
|
github.com/alexedwards/scs/v2 v2.8.0
|
||||||
|
github.com/bwmarrin/go-alone v0.0.0-20190806015146-742bb55d1631
|
||||||
github.com/go-chi/chi/v5 v5.1.0
|
github.com/go-chi/chi/v5 v5.1.0
|
||||||
github.com/go-chi/cors v1.2.1
|
github.com/go-chi/cors v1.2.1
|
||||||
github.com/go-sql-driver/mysql v1.8.1
|
github.com/go-sql-driver/mysql v1.8.1
|
||||||
@ -17,4 +18,5 @@ require (
|
|||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
github.com/go-test/deep v1.1.1 // indirect
|
github.com/go-test/deep v1.1.1 // indirect
|
||||||
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect
|
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect
|
||||||
|
golang.org/x/sys v0.23.0 // indirect
|
||||||
)
|
)
|
||||||
|
4
go.sum
4
go.sum
@ -4,6 +4,8 @@ github.com/alexedwards/scs/mysqlstore v0.0.0-20240316134038-7e11d57e8885 h1:C7QA
|
|||||||
github.com/alexedwards/scs/mysqlstore v0.0.0-20240316134038-7e11d57e8885/go.mod h1:p8jK3D80sw1PFrCSdlcJF1O75bp55HqbgDyyCLM0FrE=
|
github.com/alexedwards/scs/mysqlstore v0.0.0-20240316134038-7e11d57e8885/go.mod h1:p8jK3D80sw1PFrCSdlcJF1O75bp55HqbgDyyCLM0FrE=
|
||||||
github.com/alexedwards/scs/v2 v2.8.0 h1:h31yUYoycPuL0zt14c0gd+oqxfRwIj6SOjHdKRZxhEw=
|
github.com/alexedwards/scs/v2 v2.8.0 h1:h31yUYoycPuL0zt14c0gd+oqxfRwIj6SOjHdKRZxhEw=
|
||||||
github.com/alexedwards/scs/v2 v2.8.0/go.mod h1:ToaROZxyKukJKT/xLcVQAChi5k6+Pn1Gvmdl7h3RRj8=
|
github.com/alexedwards/scs/v2 v2.8.0/go.mod h1:ToaROZxyKukJKT/xLcVQAChi5k6+Pn1Gvmdl7h3RRj8=
|
||||||
|
github.com/bwmarrin/go-alone v0.0.0-20190806015146-742bb55d1631 h1:Xb5rra6jJt5Z1JsZhIMby+IP5T8aU+Uc2RC9RzSxs9g=
|
||||||
|
github.com/bwmarrin/go-alone v0.0.0-20190806015146-742bb55d1631/go.mod h1:P86Dksd9km5HGX5UMIocXvX87sEp2xUARle3by+9JZ4=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
||||||
@ -33,6 +35,8 @@ golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
|||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||||
|
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||||
|
44
internal/urlsigner/signer.go
Normal file
44
internal/urlsigner/signer.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package urlsigner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
goalone "github.com/bwmarrin/go-alone"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Signer struct {
|
||||||
|
Secret []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Signer) GenerateTokenFromString(data string) string {
|
||||||
|
var urlToSign string
|
||||||
|
|
||||||
|
crypt := goalone.New(s.Secret, goalone.Timestamp)
|
||||||
|
if strings.Contains(data, "?") {
|
||||||
|
urlToSign = fmt.Sprintf("%s&hash=", data)
|
||||||
|
} else {
|
||||||
|
urlToSign = fmt.Sprintf("%s?hash=", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenBytes := crypt.Sign([]byte(urlToSign))
|
||||||
|
token := string(tokenBytes)
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Signer) VerifyToken(token string) bool {
|
||||||
|
crypt := goalone.New(s.Secret, goalone.Timestamp)
|
||||||
|
_, err := crypt.Unsign([]byte(token))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Signer) Expired(token string, minutesUntilExpire int) bool {
|
||||||
|
crypt := goalone.New(s.Secret, goalone.Timestamp)
|
||||||
|
ts := crypt.Parse([]byte(token))
|
||||||
|
|
||||||
|
return time.Since(ts.Timestamp) > time.Duration(minutesUntilExpire)*time.Minute
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user