extend jwt claim with flags

This commit is contained in:
Umputun
2018-07-18 21:05:51 -05:00
parent 3abe4146b1
commit 0ae7f226af
8 changed files with 22 additions and 16 deletions
+2 -1
View File
@@ -108,7 +108,8 @@ func (a *admin) deleteMeRequestCtrl(w http.ResponseWriter, r *http.Request) {
log.Printf("[INFO] delete all user comments by request for %s, site %s", claims.User.ID, claims.SiteID)
if !claims.DeleteMe { // deletme set by deleteMeCtrl, this check just to make sure we not trying to delete with leaked token
// deleteme set by deleteMeCtrl, this check just to make sure we not trying to delete with leaked token
if !claims.Flags.DeleteMe {
rest.SendErrorJSON(w, r, http.StatusForbidden, errors.New("forbidden"), "can't use provided token")
return
}
+3 -3
View File
@@ -497,8 +497,8 @@ func TestAdmin_DeleteMeRequest(t *testing.T) {
User: &store.User{
ID: "user1",
},
DeleteMe: true,
}
claims.Flags.DeleteMe = true
token, err := srv.Authenticator.JWTService.Token(&claims)
assert.Nil(t, err)
@@ -552,8 +552,8 @@ func TestAdmin_DeleteMeRequestFailed(t *testing.T) {
User: &store.User{
ID: "user1",
},
DeleteMe: true,
}
claims.Flags.DeleteMe = true
token, err := srv.Authenticator.JWTService.Token(&claims)
assert.Nil(t, err)
@@ -578,7 +578,7 @@ func TestAdmin_DeleteMeRequestFailed(t *testing.T) {
// try without deleteme flag
badClaims2 := claims
badClaims2.DeleteMe = false
badClaims2.Flags.DeleteMe = false
token, err = srv.Authenticator.JWTService.Token(&badClaims2)
assert.Nil(t, err)
req, err = http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/v1/admin/deleteme?token=%s", ts.URL, token), nil)
+2 -2
View File
@@ -255,9 +255,9 @@ func (s *Rest) deleteMeCtrl(w http.ResponseWriter, r *http.Request) {
ExpiresAt: time.Now().AddDate(0, 3, 0).Unix(),
NotBefore: time.Now().Add(-1 * time.Minute).Unix(),
},
User: &user,
DeleteMe: true, // prevent this token from being used for login
User: &user,
}
claims.Flags.DeleteMe = true // prevent this token from being used for login
tokenStr, err := s.Authenticator.JWTService.Token(&claims)
if err != nil {
+1 -1
View File
@@ -73,7 +73,7 @@ func (a *Authenticator) Auth(reqAuth bool) func(http.Handler) http.Handler {
return
}
if claims.DeleteMe {
if a.JWTService.HasFlags(claims) {
log.Printf("[DEBUG] invalid token flags for %s/%s", claims.User.Name, claims.User.ID)
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
+1 -1
View File
@@ -15,7 +15,7 @@ import (
var testJwtUserBlocked = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjI3ODkxOTE4MjIsImp0aSI6InJhbmRvbSBpZCIsImlzcyI6InJlbWFyazQyIiwibmJmIjoxNTI2ODg0MjIyLCJ1c2VyIjp7Im5hbWUiOiJuYW1lMSIsImlkIjoiaWQxIiwicGljdHVyZSI6IiIsImFkbWluIjpmYWxzZSwiYmxvY2siOnRydWV9LCJzdGF0ZSI6IjEyMzQ1NiIsImZyb20iOiJmcm9tIn0.6P_OwGf8CUJRtvNSlW20GmaMb5pFvCNemP94fHCqb5Q"
var testJwtDeleteMe = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjI3ODkxOTE4MjIsImp0aSI6InJhbmRvbSBpZCIsImlzcyI6InJlbWFyazQyIiwibmJmIjoxNTI2ODg0MjIyLCJ1c2VyIjp7Im5hbWUiOiJuYW1lMSIsImlkIjoiaWQxIiwicGljdHVyZSI6IiIsImFkbWluIjpmYWxzZSwiYmxvY2siOmZhbHNlfSwiZGVsZXRlbWUiOnRydWV9.3wiT5fqDv_bzPky6-3IilU8ExfzCyvLpKDMPYOAFWEo"
var testJwtDeleteMe = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjI3ODkxOTE4MjIsImp0aSI6InJhbmRvbSBpZCIsImlzcyI6InJlbWFyazQyIiwibmJmIjoxNTI2ODg0MjIyLCJ1c2VyIjp7Im5hbWUiOiJuYW1lMSIsImlkIjoiaWQxIiwicGljdHVyZSI6IiIsImFkbWluIjpmYWxzZSwiYmxvY2siOmZhbHNlfSwiZmxhZ3MiOnsiZGVsZXRlbWUiOnRydWV9fQ.SLh1QpFytWZqcT99VgcdAOtgFKhvpKCcZwqWTvAd63g"
func TestAuthJWTCookie(t *testing.T) {
a := Authenticator{DevPasswd: "123456", JWTService: NewJWT("xyz 12345", false, time.Hour, time.Hour),
+9 -1
View File
@@ -31,7 +31,10 @@ type CustomClaims struct {
SessionOnly bool `json:"sess_only,omitempty"`
// flags indicate different uses
DeleteMe bool `json:"deleteme,omitempty"`
Flags struct {
Login bool `json:"login,omitempty"`
DeleteMe bool `json:"deleteme,omitempty"`
} `json:"flags,omitempty"`
}
const jwtCookieName = "JWT"
@@ -60,6 +63,11 @@ func (j *JWT) Token(claims *CustomClaims) (string, error) {
return tokenString, nil
}
// HasFlags indicates presense of special flags
func (j *JWT) HasFlags(claims *CustomClaims) bool {
return claims.Flags.DeleteMe || claims.Flags.Login
}
// Parse token string and verify. Not checking for expiration
func (j *JWT) Parse(tokenString string) (*CustomClaims, error) {
parser := jwt.Parser{SkipClaimsValidation: true} // allow parsing of expired tokens
+3 -7
View File
@@ -14,13 +14,9 @@ import (
"github.com/umputun/remark/backend/app/store"
)
var testJwtValid = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjI3ODkxOTE4MjIsImp0aSI6InJhbmRvbSBpZCI" +
"sImlzcyI6InJlbWFyazQyIiwibmJmIjoxNTI2ODg0MjIyLCJ1c2VyIjp7Im5hbWUiOiJuYW1lMSIsImlkIjoiaWQxIiwicGljdHVyZS" +
"I6IiIsImFkbWluIjpmYWxzZX0sInN0YXRlIjoiMTIzNDU2IiwiZnJvbSI6ImZyb20ifQ._loFgh3g45gr9TtGqvM3N584I_6EHEOJnYb6Py84stQ"
var testJwtValid = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjI3ODkxOTE4MjIsImp0aSI6InJhbmRvbSBpZCIsImlzcyI6InJlb" + "WFyazQyIiwibmJmIjoxNTI2ODg0MjIyLCJ1c2VyIjp7Im5hbWUiOiJuYW1lMSIsImlkIjoiaWQxIiwicGljdHVyZSI6IiIsImFkbWluIjpmYWxzZX0" + "sInN0YXRlIjoiMTIzNDU2IiwiZnJvbSI6ImZyb20iLCJmbGFncyI6e319.E2Blxqo1wsY855q258c0obxFJ1lgJciv1av1ewzlJBs"
var testJwtValidSess = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjI3ODkxOTE4MjIsImp0aSI6InJhbmRvbSBpZCIsImlzcyI6In" +
"JlbWFyazQyIiwibmJmIjoxNTI2ODg0MjIyLCJ1c2VyIjp7Im5hbWUiOiJuYW1lMSIsImlkIjoiaWQxIiwicGljdHVyZSI6IiIsIm" +
"FkbWluIjpmYWxzZX0sInN0YXRlIjoiMTIzNDU2IiwiZnJvbSI6ImZyb20iLCJzZXNzX29ubHkiOnRydWV9.p6w0sM_NYaRuyhyA9jqfWlB5cx1vZPGhXGC5geSX7nA"
var testJwtValidSess = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjI3ODkxOTE4MjIsImp0aSI6InJhbmRvbSBpZCIs" + "ImlzcyI6InJlbWFyazQyIiwibmJmIjoxNTI2ODg0MjIyLCJ1c2VyIjp7Im5hbWUiOiJuYW1lMSIsImlkIjoiaWQxIiwicGljdHVyZSI6IiIsImFk" + "bWluIjpmYWxzZX0sInN0YXRlIjoiMTIzNDU2IiwiZnJvbSI6ImZyb20iLCJzZXNzX29ubHkiOnRydWUsImZsYWdzIjp7fX0." + "nKhehF1Xiome1yK1ewfOiIsrATvq7Tx7p1BCSJqKHuo"
var testJwtExpired = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MjY4ODc4MjIsImp0aSI6InJhbmRvbSBpZCIs" +
"ImlzcyI6InJlbWFyazQyIiwibmJmIjoxNTI2ODg0MjIyLCJ1c2VyIjp7Im5hbWUiOiJuYW1lMSIsImlkIjoiaWQxIiwicGljdHVyZSI6IiI" +
@@ -89,9 +85,9 @@ func TestJWT_Set(t *testing.T) {
ExpiresAt: time.Date(2058, 5, 21, 1, 30, 22, 0, time.Local).Unix(),
NotBefore: time.Date(2018, 5, 21, 1, 30, 22, 0, time.Local).Unix(),
},
SessionOnly: false,
}
claims.SessionOnly = false
rr := httptest.NewRecorder()
err := j.Set(rr, claims, claims.SessionOnly)
assert.Nil(t, err)
+1
View File
@@ -99,6 +99,7 @@ func (p Provider) loginHandler(w http.ResponseWriter, r *http.Request) {
NotBefore: time.Now().Add(-1 * time.Minute).Unix(),
},
}
claims.Flags.Login = true
if err := p.JwtService.Set(w, &claims, false); err != nil {
rest.SendErrorJSON(w, r, http.StatusInternalServerError, err, "failed to set jwt")