Fix subject, add token refresh route

This commit is contained in:
Daniel 2024-08-10 18:21:13 -04:00
parent 41b87da905
commit 6455b4ad4c
3 changed files with 52 additions and 4 deletions

View file

@ -1,5 +1,4 @@
all:
@[ ! -e client/calls/index.html ] && make getcalls
all: checkcalls
go build -o gordio ./cmd/gordio/
go build -o calls ./cmd/calls/
@ -7,6 +6,9 @@ clean:
rm -rf client/calls/ && mkdir client/calls && touch client/calls/.gitkeep
rm -f gordio calls
checkcalls:
test ! -e client/calls/index.html && make getcalls
getcalls:
rm -rf client/calls/*
cd client/calls/ && curl -OL https://nightly.link/amigan/calls/workflows/build-web/trunk/webBuild.zip && unzip -o webBuild.zip && rm webBuild.zip

View file

@ -3,6 +3,7 @@ package auth
import (
"context"
"net/http"
"strconv"
"time"
"golang.org/x/crypto/bcrypt"
@ -11,6 +12,7 @@ import (
"github.com/go-chi/chi/v5"
"github.com/go-chi/jwtauth/v5"
"github.com/lestrrat-go/jwx/v2/jwt"
"github.com/go-chi/render"
"github.com/rs/zerolog/log"
)
@ -28,8 +30,11 @@ type jwtAuth interface {
// InstallAuthMiddleware installs the JWT authenticator middleware to the provided chi Router.
AuthMiddleware() func(http.Handler) http.Handler
// InstallRoutes installs the auth route to the provided chi Router.
// PublicRoutes installs the auth route to the provided chi Router.
PublicRoutes(chi.Router)
// PublicRoutes installs the refresh route to the provided chi Router.
PrivateRoutes(chi.Router)
}
type claims map[string]interface{}
@ -79,7 +84,7 @@ func (a *authenticator) Login(ctx context.Context, username, password string) (t
func (a *authenticator) newToken(uid int32) string {
claims := claims{
"user_id": uid,
"sub": strconv.Itoa(int(uid)),
}
jwtauth.SetExpiryIn(claims, time.Hour*24*30) // one month
_, tokenString, err := a.jwt.Encode(claims)
@ -93,11 +98,51 @@ func (a *authenticator) PublicRoutes(r chi.Router) {
r.Post("/login", a.routeAuth)
}
func (a *authenticator) PrivateRoutes(r chi.Router) {
r.Get("/refresh", a.routeRefresh)
}
func (a *authenticator) allowInsecureCookie(r *http.Request) bool {
v, has := a.cfg.AllowInsecure[r.Host]
return has && v
}
func (a *authenticator) routeRefresh(w http.ResponseWriter, r *http.Request) {
existingSubjectUID := r.Context().Value(jwtauth.TokenCtxKey).(jwt.Token).Subject()
if existingSubjectUID == "" {
http.Error(w, "Invalid token", http.StatusBadRequest)
return
}
uid, err := strconv.Atoi(existingSubjectUID)
if err != nil {
log.Error().Str("sub", existingSubjectUID).Err(err).Msg("atoi uid for token refresh")
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
tok := a.newToken(int32(uid))
cookie := &http.Cookie{
Name: "jwt",
Value: tok,
HttpOnly: true,
Secure: !a.allowInsecureCookie(r),
}
if cookie.Secure {
cookie.Domain = a.cfg.Domain
}
http.SetCookie(w, cookie)
jr := struct {
JWT string `json:"jwt"`
}{
JWT: tok,
}
render.JSON(w, r, &jr)
}
func (a *authenticator) routeAuth(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {

View file

@ -27,6 +27,7 @@ func (s *Server) setupRoutes() {
// authenticated routes
r.Use(s.auth.VerifyMiddleware(), s.auth.AuthMiddleware())
s.nex.PrivateRoutes(r)
s.auth.PrivateRoutes(r)
})
r.Group(func(r chi.Router) {