gogmagog/tokens/tokens.go

87 lines
2.1 KiB
Go

package tokens
import (
"fmt"
"gitea.deepak.science/deepak/gogmagog/models"
"github.com/go-chi/jwtauth"
"github.com/lestrrat-go/jwx/jwt"
"net/http"
"time"
)
// Toker represents a tokenizer, capable of encoding and verifying tokens.
type Toker interface {
EncodeUser(user *models.UserNoPassword) string
DecodeTokenString(tokenString string) (*UserToken, error)
Authenticator(http.Handler) http.Handler
}
type jwtToker struct {
tokenAuth *jwtauth.JWTAuth
}
// New returns a default Toker for a given secret key.
func New(key string) Toker {
return &jwtToker{tokenAuth: jwtauth.New("HS256", []byte(key), nil)}
}
func (tok *jwtToker) EncodeUser(user *models.UserNoPassword) string {
claims := map[string]interface{}{
"user_id": user.UserID,
"username": user.Username,
"display_name": user.DisplayName,
"iss": "gogmagog.deepak.science",
"aud": "gogmagog.deepak.science",
}
jwtauth.SetIssuedNow(claims)
jwtauth.SetExpiryIn(claims, 2*time.Hour)
_, tokenString, _ := tok.tokenAuth.Encode(claims)
return tokenString
}
// UserToken represents a decoded jwt token.
type UserToken struct {
ID int64
Username string
}
func (tok *jwtToker) DecodeTokenString(tokenString string) (*UserToken, error) {
token, err := tok.tokenAuth.Decode(tokenString)
if err != nil {
return nil, fmt.Errorf("Error decoding token")
}
// Should never happen, remove soon.
// if token == nil {
// return nil, fmt.Errorf("Token was nil")
// }
err = jwt.Validate(
token,
jwt.WithIssuer("gogmagog.deepak.science"),
jwt.WithAudience("gogmagog.deepak.science"),
)
if err != nil {
return nil, err
}
userIDRaw, ok := token.Get("user_id")
if !ok {
return nil, fmt.Errorf("error finding user_id claim")
}
userID, ok := userIDRaw.(float64)
if !ok {
return nil, fmt.Errorf("Could not parse [%s] as userID", userIDRaw)
}
usernameRaw, ok := token.Get("username")
if !ok {
return nil, fmt.Errorf("error finding username claim")
}
username, ok := usernameRaw.(string)
if !ok {
return nil, fmt.Errorf("Could not parse [%s] as username", usernameRaw)
}
return &UserToken{ID: int64(userID), Username: username}, nil
}