updated jwt and added share token invalidation
This commit is contained in:
parent
095fb1573b
commit
c28249e1ce
11 changed files with 48 additions and 34 deletions
2
go.mod
2
go.mod
|
|
@ -2,7 +2,7 @@ module git.giftfish.de/ston1th/gowiki
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.giftfish.de/ston1th/godrop/v2 v2.1.0
|
git.giftfish.de/ston1th/godrop/v2 v2.1.0
|
||||||
git.giftfish.de/ston1th/jwt/v3 v3.1.0
|
git.giftfish.de/ston1th/jwt/v3 v3.2.0
|
||||||
github.com/RoaringBitmap/roaring v0.4.16 // indirect
|
github.com/RoaringBitmap/roaring v0.4.16 // indirect
|
||||||
github.com/Smerity/govarint v0.0.0-20150407073650-7265e41f48f1 // indirect
|
github.com/Smerity/govarint v0.0.0-20150407073650-7265e41f48f1 // indirect
|
||||||
github.com/blevesearch/bleve v0.7.0
|
github.com/blevesearch/bleve v0.7.0
|
||||||
|
|
|
||||||
4
go.sum
4
go.sum
|
|
@ -1,7 +1,7 @@
|
||||||
git.giftfish.de/ston1th/godrop/v2 v2.1.0 h1:vR4aWVeMGJ+tHQH0p44esZrSl5dYJzuCmZqhKWP/vwI=
|
git.giftfish.de/ston1th/godrop/v2 v2.1.0 h1:vR4aWVeMGJ+tHQH0p44esZrSl5dYJzuCmZqhKWP/vwI=
|
||||||
git.giftfish.de/ston1th/godrop/v2 v2.1.0/go.mod h1:z8KA3HP/vB04wddLXZfYVKURYDxBGau9hlHtV61x9mM=
|
git.giftfish.de/ston1th/godrop/v2 v2.1.0/go.mod h1:z8KA3HP/vB04wddLXZfYVKURYDxBGau9hlHtV61x9mM=
|
||||||
git.giftfish.de/ston1th/jwt/v3 v3.1.0 h1:SaSpVyl98iqnsRIh9tA8/XJpU6nCYIGa4L85rLvQWC0=
|
git.giftfish.de/ston1th/jwt/v3 v3.2.0 h1:V6Lh7OjXn4D3HPd/LoDf7w5N7cyiSXEPAQCIfSVZ05c=
|
||||||
git.giftfish.de/ston1th/jwt/v3 v3.1.0/go.mod h1:jDALrW7OKeIaqYuMxs3GWyPRnQZmk/R+Lu9p/Em3Ziw=
|
git.giftfish.de/ston1th/jwt/v3 v3.2.0/go.mod h1:jDALrW7OKeIaqYuMxs3GWyPRnQZmk/R+Lu9p/Em3Ziw=
|
||||||
github.com/RoaringBitmap/roaring v0.4.16 h1:NholfewybRLOwACgfqfzn/N5xa6keKNs4fP00t0cwLo=
|
github.com/RoaringBitmap/roaring v0.4.16 h1:NholfewybRLOwACgfqfzn/N5xa6keKNs4fP00t0cwLo=
|
||||||
github.com/RoaringBitmap/roaring v0.4.16/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
|
github.com/RoaringBitmap/roaring v0.4.16/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
|
||||||
github.com/Smerity/govarint v0.0.0-20150407073650-7265e41f48f1 h1:G/NOANWMQev0CftoyxQwtRakdyNNNMB3qxkt/tj1HGs=
|
github.com/Smerity/govarint v0.0.0-20150407073650-7265e41f48f1 h1:G/NOANWMQev0CftoyxQwtRakdyNNNMB3qxkt/tj1HGs=
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,15 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
userClaim = "user"
|
userClaim = "user"
|
||||||
adminClaim = "admin"
|
adminClaim = "admin"
|
||||||
createdClaim = "created"
|
userCreatedClaim = "user_created"
|
||||||
sharedClaim = "shared"
|
pageCreatedClaim = "page_created"
|
||||||
sectionClaim = "section"
|
sharedClaim = "shared"
|
||||||
titleClaim = "title"
|
sectionClaim = "section"
|
||||||
totpClaim = "totp"
|
titleClaim = "title"
|
||||||
rememberClaim = "remember"
|
totpClaim = "totp"
|
||||||
|
rememberClaim = "remember"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newContext(w http.ResponseWriter, r *http.Request, s *HTTPServer) (ctx *Context) {
|
func newContext(w http.ResponseWriter, r *http.Request, s *HTTPServer) (ctx *Context) {
|
||||||
|
|
@ -60,7 +61,7 @@ func newContext(w http.ResponseWriter, r *http.Request, s *HTTPServer) (ctx *Con
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
if !s.DB.LockedOut(t.Claims.GetString(userClaim), t.Claims.GetString(createdClaim)) {
|
if !s.DB.LockedOut(t.Claims.GetString(userClaim), t.Claims.GetString(userCreatedClaim)) {
|
||||||
ctx.Token = *t
|
ctx.Token = *t
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -239,7 +240,7 @@ func (c *Context) Login(u core.User, remember string) {
|
||||||
if remember != "" {
|
if remember != "" {
|
||||||
d = day * 7
|
d = day * 7
|
||||||
}
|
}
|
||||||
c.SetCookie(jwt.Claims{userClaim: u.Username, createdClaim: u.Created, adminClaim: u.Admin}, d)
|
c.SetCookie(jwt.Claims{userClaim: u.Username, userCreatedClaim: u.Created, adminClaim: u.Admin}, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) SetCookie(claims jwt.Claims, d time.Duration) {
|
func (c *Context) SetCookie(claims jwt.Claims, d time.Duration) {
|
||||||
|
|
|
||||||
|
|
@ -251,13 +251,15 @@ func pageNewHandler(ctx *Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func pageHandler(ctx *Context) {
|
func pageHandler(ctx *Context) {
|
||||||
|
var pageCreated string
|
||||||
ctx.Data = webData{
|
ctx.Data = webData{
|
||||||
Admin: ctx.Admin(),
|
Admin: ctx.Admin(),
|
||||||
}
|
}
|
||||||
section := ctx.Var("section")
|
section := ctx.Var("section")
|
||||||
title := ctx.Var("title")
|
title := ctx.Var("title")
|
||||||
user := ctx.User()
|
user := ctx.User()
|
||||||
if key := ctx.Var("key"); key != "" {
|
key := ctx.Var("key")
|
||||||
|
if key != "" {
|
||||||
t, err := jwt.DecodeToken(key)
|
t, err := jwt.DecodeToken(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("share: DecodeToken:", err)
|
log.Println("share: DecodeToken:", err)
|
||||||
|
|
@ -270,7 +272,7 @@ func pageHandler(ctx *Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user = t.Claims.GetString(sharedClaim)
|
user = t.Claims.GetString(sharedClaim)
|
||||||
if ctx.Srv.DB.LockedOut(user, t.Claims.GetString(createdClaim)) {
|
if ctx.Srv.DB.LockedOut(user, t.Claims.GetString(userCreatedClaim)) {
|
||||||
if err = ctx.Srv.JWT.Invalidate(t); err != nil {
|
if err = ctx.Srv.JWT.Invalidate(t); err != nil {
|
||||||
log.Println("share: Invalidate:", err)
|
log.Println("share: Invalidate:", err)
|
||||||
}
|
}
|
||||||
|
|
@ -279,6 +281,7 @@ func pageHandler(ctx *Context) {
|
||||||
}
|
}
|
||||||
section = t.Claims.GetString(sectionClaim)
|
section = t.Claims.GetString(sectionClaim)
|
||||||
title = t.Claims.GetString(titleClaim)
|
title = t.Claims.GetString(titleClaim)
|
||||||
|
pageCreated = t.Claims.GetString(pageCreatedClaim)
|
||||||
ctx.Data.Key = key
|
ctx.Data.Key = key
|
||||||
if ctx.T == nil {
|
if ctx.T == nil {
|
||||||
ctx.Template("pageViewHandler")
|
ctx.Template("pageViewHandler")
|
||||||
|
|
@ -294,6 +297,10 @@ func pageHandler(ctx *Context) {
|
||||||
ctx.NotFound()
|
ctx.NotFound()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if key != "" && page.Created != pageCreated {
|
||||||
|
ctx.NotFound()
|
||||||
|
return
|
||||||
|
}
|
||||||
ctx.Data.Data = page
|
ctx.Data.Data = page
|
||||||
ctx.Data.Title = page.Title
|
ctx.Data.Title = page.Title
|
||||||
ctx.Data.BodyTitle = page.Title
|
ctx.Data.BodyTitle = page.Title
|
||||||
|
|
@ -339,11 +346,12 @@ func pageShareHandler(ctx *Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t := jwt.NewToken(map[string]interface{}{
|
t := jwt.NewToken(map[string]interface{}{
|
||||||
sharedClaim: user,
|
sharedClaim: user,
|
||||||
createdClaim: ctx.Token.Claims.GetString(createdClaim),
|
userCreatedClaim: ctx.Token.Claims.GetString(userCreatedClaim),
|
||||||
sectionClaim: section,
|
pageCreatedClaim: page.Created,
|
||||||
titleClaim: title,
|
sectionClaim: section,
|
||||||
jwt.ExpClaim: jwt.NewExp(d),
|
titleClaim: title,
|
||||||
|
jwt.ExpClaim: jwt.NewExp(d),
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
||||||
if err = ctx.Srv.JWT.Sign(t); err != nil {
|
if err = ctx.Srv.JWT.Sign(t); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -396,7 +396,7 @@ const (
|
||||||
<input type="hidden" name="token" value="{{.Token}}">
|
<input type="hidden" name="token" value="{{.Token}}">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-form-label" for="duration">Lifetime</label>
|
<label class="col-form-label" for="duration">Lifetime</label>
|
||||||
<input class="form-control input-sm" type="text" id="duration" name="duration" placeholder="min: 30s max: 90d" autocomplete="off" autofocus required>
|
<input class="form-control input-sm" type="text" id="duration" name="duration" autocomplete="off" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="custom-control custom-radio">
|
<div class="custom-control custom-radio">
|
||||||
|
|
@ -405,7 +405,7 @@ const (
|
||||||
</div>
|
</div>
|
||||||
<div class="custom-control custom-radio">
|
<div class="custom-control custom-radio">
|
||||||
<input type="radio" id="mode2" name="mode" value="2" class="custom-control-input">
|
<input type="radio" id="mode2" name="mode" value="2" class="custom-control-input">
|
||||||
<label class="custom-control-label" for="mode2">Day</label>
|
<label class="custom-control-label" for="mode2">Day(s) (Numbers only)</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-sm btn-primary" type="submit">Share</button>
|
<button class="btn btn-sm btn-primary" type="submit">Share</button>
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@ func genKey(length int) (bytes []byte) {
|
||||||
|
|
||||||
func newXsrf(secret []byte) string {
|
func newXsrf(secret []byte) string {
|
||||||
rnd := genKey(keySize)
|
rnd := genKey(keySize)
|
||||||
return base64.StdEncoding.EncodeToString(append(rnd, xor(rnd, secret)...))
|
return base64.RawStdEncoding.EncodeToString(append(rnd, xor(rnd, secret)...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkXsrf(xsrf string, secret []byte) bool {
|
func checkXsrf(xsrf string, secret []byte) bool {
|
||||||
t, err := base64.StdEncoding.DecodeString(xsrf)
|
t, err := base64.RawStdEncoding.DecodeString(xsrf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<input type="hidden" name="token" value="{{.Token}}">
|
<input type="hidden" name="token" value="{{.Token}}">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-form-label" for="duration">Lifetime</label>
|
<label class="col-form-label" for="duration">Lifetime</label>
|
||||||
<input class="form-control input-sm" type="text" id="duration" name="duration" placeholder="min: 30s max: 90d" autocomplete="off" autofocus required>
|
<input class="form-control input-sm" type="text" id="duration" name="duration" autocomplete="off" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="custom-control custom-radio">
|
<div class="custom-control custom-radio">
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="custom-control custom-radio">
|
<div class="custom-control custom-radio">
|
||||||
<input type="radio" id="mode2" name="mode" value="2" class="custom-control-input">
|
<input type="radio" id="mode2" name="mode" value="2" class="custom-control-input">
|
||||||
<label class="custom-control-label" for="mode2">Day</label>
|
<label class="custom-control-label" for="mode2">Day(s) (Numbers only)</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-sm btn-primary" type="submit">Share</button>
|
<button class="btn btn-sm btn-primary" type="submit">Share</button>
|
||||||
|
|
|
||||||
7
vendor/git.giftfish.de/ston1th/jwt/v3/encoding.go
vendored
Normal file
7
vendor/git.giftfish.de/ston1th/jwt/v3/encoding.go
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
// Copyright (C) 2018 Marius Schellenberger
|
||||||
|
|
||||||
|
package jwt
|
||||||
|
|
||||||
|
import "encoding/base64"
|
||||||
|
|
||||||
|
var enc = base64.RawURLEncoding
|
||||||
5
vendor/git.giftfish.de/ston1th/jwt/v3/jwt.go
vendored
5
vendor/git.giftfish.de/ston1th/jwt/v3/jwt.go
vendored
|
|
@ -6,7 +6,6 @@ package jwt
|
||||||
import (
|
import (
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
|
@ -210,9 +209,9 @@ func (jwt *JWT) Sign(t *Token) (err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.data = base64.URLEncoding.EncodeToString(head) + TokenSeparator + base64.URLEncoding.EncodeToString(claims)
|
t.data = enc.EncodeToString(head) + TokenSeparator + enc.EncodeToString(claims)
|
||||||
t.rawSignature = jwt.sum(t.data, h)
|
t.rawSignature = jwt.sum(t.data, h)
|
||||||
t.signature = base64.URLEncoding.EncodeToString(t.rawSignature)
|
t.signature = enc.EncodeToString(t.rawSignature)
|
||||||
t.raw = t.data + TokenSeparator + t.signature
|
t.raw = t.data + TokenSeparator + t.signature
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
package jwt
|
package jwt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
@ -75,7 +74,7 @@ func DecodeToken(token string) (t *Token, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t = new(Token)
|
t = new(Token)
|
||||||
header, err := base64.URLEncoding.DecodeString(parts[0])
|
header, err := enc.DecodeString(parts[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -83,7 +82,7 @@ func DecodeToken(token string) (t *Token, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
claims, err := base64.URLEncoding.DecodeString(parts[1])
|
claims, err := enc.DecodeString(parts[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +90,7 @@ func DecodeToken(token string) (t *Token, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.rawSignature, err = base64.URLEncoding.DecodeString(parts[2])
|
t.rawSignature, err = enc.DecodeString(parts[2])
|
||||||
t.signature = parts[2]
|
t.signature = parts[2]
|
||||||
t.data = parts[0] + TokenSeparator + parts[1]
|
t.data = parts[0] + TokenSeparator + parts[1]
|
||||||
t.raw = token
|
t.raw = token
|
||||||
|
|
|
||||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
# git.giftfish.de/ston1th/godrop/v2 v2.1.0
|
# git.giftfish.de/ston1th/godrop/v2 v2.1.0
|
||||||
git.giftfish.de/ston1th/godrop/v2
|
git.giftfish.de/ston1th/godrop/v2
|
||||||
# git.giftfish.de/ston1th/jwt/v3 v3.1.0
|
# git.giftfish.de/ston1th/jwt/v3 v3.2.0
|
||||||
git.giftfish.de/ston1th/jwt/v3
|
git.giftfish.de/ston1th/jwt/v3
|
||||||
# github.com/RoaringBitmap/roaring v0.4.16
|
# github.com/RoaringBitmap/roaring v0.4.16
|
||||||
github.com/RoaringBitmap/roaring
|
github.com/RoaringBitmap/roaring
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue