Fix subject, add token refresh route
This commit is contained in:
parent
41b87da905
commit
6455b4ad4c
3 changed files with 52 additions and 4 deletions
6
Makefile
6
Makefile
|
@ -1,5 +1,4 @@
|
||||||
all:
|
all: checkcalls
|
||||||
@[ ! -e client/calls/index.html ] && make getcalls
|
|
||||||
go build -o gordio ./cmd/gordio/
|
go build -o gordio ./cmd/gordio/
|
||||||
go build -o calls ./cmd/calls/
|
go build -o calls ./cmd/calls/
|
||||||
|
|
||||||
|
@ -7,6 +6,9 @@ clean:
|
||||||
rm -rf client/calls/ && mkdir client/calls && touch client/calls/.gitkeep
|
rm -rf client/calls/ && mkdir client/calls && touch client/calls/.gitkeep
|
||||||
rm -f gordio calls
|
rm -f gordio calls
|
||||||
|
|
||||||
|
checkcalls:
|
||||||
|
test ! -e client/calls/index.html && make getcalls
|
||||||
|
|
||||||
getcalls:
|
getcalls:
|
||||||
rm -rf client/calls/*
|
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
|
cd client/calls/ && curl -OL https://nightly.link/amigan/calls/workflows/build-web/trunk/webBuild.zip && unzip -o webBuild.zip && rm webBuild.zip
|
||||||
|
|
|
@ -3,6 +3,7 @@ package auth
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
@ -11,6 +12,7 @@ import (
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-chi/jwtauth/v5"
|
"github.com/go-chi/jwtauth/v5"
|
||||||
|
"github.com/lestrrat-go/jwx/v2/jwt"
|
||||||
"github.com/go-chi/render"
|
"github.com/go-chi/render"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
@ -28,8 +30,11 @@ type jwtAuth interface {
|
||||||
// InstallAuthMiddleware installs the JWT authenticator middleware to the provided chi Router.
|
// InstallAuthMiddleware installs the JWT authenticator middleware to the provided chi Router.
|
||||||
AuthMiddleware() func(http.Handler) http.Handler
|
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(chi.Router)
|
||||||
|
|
||||||
|
// PublicRoutes installs the refresh route to the provided chi Router.
|
||||||
|
PrivateRoutes(chi.Router)
|
||||||
}
|
}
|
||||||
|
|
||||||
type claims map[string]interface{}
|
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 {
|
func (a *authenticator) newToken(uid int32) string {
|
||||||
claims := claims{
|
claims := claims{
|
||||||
"user_id": uid,
|
"sub": strconv.Itoa(int(uid)),
|
||||||
}
|
}
|
||||||
jwtauth.SetExpiryIn(claims, time.Hour*24*30) // one month
|
jwtauth.SetExpiryIn(claims, time.Hour*24*30) // one month
|
||||||
_, tokenString, err := a.jwt.Encode(claims)
|
_, tokenString, err := a.jwt.Encode(claims)
|
||||||
|
@ -93,11 +98,51 @@ func (a *authenticator) PublicRoutes(r chi.Router) {
|
||||||
r.Post("/login", a.routeAuth)
|
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 {
|
func (a *authenticator) allowInsecureCookie(r *http.Request) bool {
|
||||||
v, has := a.cfg.AllowInsecure[r.Host]
|
v, has := a.cfg.AllowInsecure[r.Host]
|
||||||
return has && v
|
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) {
|
func (a *authenticator) routeAuth(w http.ResponseWriter, r *http.Request) {
|
||||||
err := r.ParseForm()
|
err := r.ParseForm()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -27,6 +27,7 @@ func (s *Server) setupRoutes() {
|
||||||
// authenticated routes
|
// authenticated routes
|
||||||
r.Use(s.auth.VerifyMiddleware(), s.auth.AuthMiddleware())
|
r.Use(s.auth.VerifyMiddleware(), s.auth.AuthMiddleware())
|
||||||
s.nex.PrivateRoutes(r)
|
s.nex.PrivateRoutes(r)
|
||||||
|
s.auth.PrivateRoutes(r)
|
||||||
})
|
})
|
||||||
|
|
||||||
r.Group(func(r chi.Router) {
|
r.Group(func(r chi.Router) {
|
||||||
|
|
Loading…
Reference in a new issue