Improvements for tokens
This commit is contained in:
parent
effa79aacd
commit
8ccd490bed
15 changed files with 34 additions and 30 deletions
1
API.md
1
API.md
|
|
@ -21,6 +21,7 @@ All routes can be found under `/api/v1/http/`
|
|||
- `/api/v1/systems`: Returns a (publically visible) list of systems
|
||||
- `/api/v1/news`: Returns JSON containing all news items
|
||||
|
||||
|
||||
## Interactive Websocket API
|
||||
|
||||
Some API calls require interactivity or provide streaming content to clients.
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -16,7 +16,7 @@ require (
|
|||
github.com/pquerna/otp v1.4.0
|
||||
github.com/rs/zerolog v1.29.1
|
||||
github.com/tkw1536/goprogram v0.3.5
|
||||
github.com/tkw1536/pkglib v0.0.0-20230530085130-4f049f64e420
|
||||
github.com/tkw1536/pkglib v0.0.0-20230629065114-9b97337c75a0
|
||||
github.com/yuin/goldmark v1.5.4
|
||||
github.com/yuin/goldmark-meta v1.1.0
|
||||
golang.org/x/crypto v0.8.0
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -114,8 +114,8 @@ github.com/tdewolff/parse v2.3.4+incompatible/go.mod h1:8oBwCsVmUkgHO8M5iCzSIDtp
|
|||
github.com/tdewolff/test v1.0.7 h1:8Vs0142DmPFW/bQeHRP3MV19m1gvndjUb1sn8yy74LM=
|
||||
github.com/tkw1536/goprogram v0.3.5 h1:S0axKo3R/vGa4zhYqYDKAZEPhAfwUSSeMtVwnAu4sNY=
|
||||
github.com/tkw1536/goprogram v0.3.5/go.mod h1:pYr4dMHOSVurbPQ4KTR0ett8XWNISbsRS6zlh9Nsxa8=
|
||||
github.com/tkw1536/pkglib v0.0.0-20230530085130-4f049f64e420 h1:ZZ7Hhf4cMKXWbOfh6A1FWmhOgD8US0Tz9Ky2fPiaZ3I=
|
||||
github.com/tkw1536/pkglib v0.0.0-20230530085130-4f049f64e420/go.mod h1:0A1B9Cc5+yJXR3eeB14CqD4dFSbEjjWRo5Pr9M3XYuI=
|
||||
github.com/tkw1536/pkglib v0.0.0-20230629065114-9b97337c75a0 h1:M1iZRhxJtw9SZSGjowf1IpZx96U5fQK/c3uhK9vZOxk=
|
||||
github.com/tkw1536/pkglib v0.0.0-20230629065114-9b97337c75a0/go.mod h1:0A1B9Cc5+yJXR3eeB14CqD4dFSbEjjWRo5Pr9M3XYuI=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
|
|
|
|||
|
|
@ -43,11 +43,9 @@ func (a *API) HandleRoute(ctx context.Context, path string) (http.Handler, error
|
|||
Methods: []string{"GET"},
|
||||
|
||||
Handler: func(s string, r *http.Request) (ai AuthInfo, err error) {
|
||||
var user *auth.AuthUser
|
||||
user, err = a.Dependencies.Auth.SessionOf(r)
|
||||
if user != nil {
|
||||
ai.User = user.User.User
|
||||
}
|
||||
session, _, err := a.Dependencies.Auth.SessionOf(r)
|
||||
ai.User = session.Username()
|
||||
ai.Token = session.Token
|
||||
return
|
||||
},
|
||||
}, nil
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ var (
|
|||
func (next *Next) Routes() component.Routes {
|
||||
return component.Routes{
|
||||
Prefix: "/next/",
|
||||
Decorator: next.Dependencies.Auth.Require(true, scopes.ScopeUserLoggedIn, nil),
|
||||
Decorator: next.Dependencies.Auth.Require(true, scopes.ScopeUserValid, nil),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func (panel *UserPanel) Routes() component.Routes {
|
|||
return component.Routes{
|
||||
Prefix: "/user/",
|
||||
CSRF: true,
|
||||
Decorator: panel.Dependencies.Auth.Require(false, scopes.ScopeUserLoggedIn, nil),
|
||||
Decorator: panel.Dependencies.Auth.Require(false, scopes.ScopeUserValid, nil),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ func (panel *UserPanel) HandleRoute(ctx context.Context, route string) (http.Han
|
|||
}
|
||||
|
||||
// ensure that the user is logged in!
|
||||
return panel.Dependencies.Auth.Protect(router, false, scopes.ScopeUserLoggedIn, nil), nil
|
||||
return panel.Dependencies.Auth.Protect(router, false, scopes.ScopeUserValid, nil), nil
|
||||
}
|
||||
|
||||
type userFormContext struct {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ func (panel *UserPanel) routeUser(ctx context.Context) http.Handler {
|
|||
return uc, nil, err
|
||||
}
|
||||
|
||||
uc.ShowAdminURLs = panel.Dependencies.Auth.CheckScope("", scopes.ScopeAdminLoggedIn, r) == nil
|
||||
uc.ShowAdminURLs = panel.Dependencies.Auth.CheckScope("", scopes.ScopeUserAdmin, r) == nil
|
||||
|
||||
// replace the totp action in the menu
|
||||
var totpAction component.MenuItem
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ func (auth *Auth) Protect(handler http.Handler, AllowToken bool, scope component
|
|||
var paramValue string
|
||||
|
||||
// load the user in the session
|
||||
// TODO<tokens>: Check if API access is allowed
|
||||
user, token, err := auth.SessionOf(r)
|
||||
// TODO: In a future version of sessions, check if token has the permitted scope.
|
||||
session, user, err := auth.SessionOf(r)
|
||||
if err != nil {
|
||||
goto err
|
||||
}
|
||||
|
||||
// token was set, but not allowed!
|
||||
if token && !AllowToken {
|
||||
if session.Token && !AllowToken {
|
||||
goto forbidden
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,19 +19,19 @@ var (
|
|||
)
|
||||
|
||||
const (
|
||||
ScopeAdminLoggedIn Scope = "login.admin"
|
||||
ScopeUserAdmin Scope = "user.admin"
|
||||
)
|
||||
|
||||
func (*AdminLoggedIn) Scope() component.ScopeInfo {
|
||||
return component.ScopeInfo{
|
||||
Scope: ScopeAdminLoggedIn,
|
||||
Description: "session has a signed in admin",
|
||||
DeniedMessage: "user must be signed into an admin account with TOTP enabled",
|
||||
Scope: ScopeUserAdmin,
|
||||
Description: "session must have a valid admin",
|
||||
DeniedMessage: "user must have an admin account with TOTP enabled",
|
||||
TakesParam: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (al *AdminLoggedIn) HasScope(param string, r *http.Request) (bool, error) {
|
||||
user, _, err := al.Dependencies.Auth.SessionOf(r)
|
||||
_, user, err := al.Dependencies.Auth.SessionOf(r)
|
||||
return user != nil && user.IsAdmin() && user.IsTOTPEnabled(), err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,18 +19,18 @@ var (
|
|||
)
|
||||
|
||||
const (
|
||||
ScopeUserLoggedIn Scope = "login.user"
|
||||
ScopeUserValid Scope = "user.valid"
|
||||
)
|
||||
|
||||
func (*UserLoggedIn) Scope() component.ScopeInfo {
|
||||
return component.ScopeInfo{
|
||||
Scope: ScopeUserLoggedIn,
|
||||
Description: "session has an associated user",
|
||||
Scope: ScopeUserValid,
|
||||
Description: "session must have a valid user",
|
||||
TakesParam: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (iu *UserLoggedIn) HasScope(param string, r *http.Request) (bool, error) {
|
||||
user, _, err := iu.Dependencies.Auth.SessionOf(r)
|
||||
_, user, err := iu.Dependencies.Auth.SessionOf(r)
|
||||
return user != nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,11 +41,15 @@ func (auth *Auth) SessionOf(r *http.Request) (session component.SessionInfo, use
|
|||
if err != nil {
|
||||
return component.SessionInfo{}, nil, err
|
||||
}
|
||||
if user == nil {
|
||||
return component.SessionInfo{}, nil, nil
|
||||
}
|
||||
return component.SessionInfo{User: &user.User, Token: false}, user, nil
|
||||
}
|
||||
}
|
||||
|
||||
// UserOfToken returns the user associated with the token in request.
|
||||
// To check the user of a token or session, use SessionOf.
|
||||
func (auth *Auth) UserOfToken(r *http.Request) (user *AuthUser, err error) {
|
||||
// get the token object
|
||||
token, err := auth.Dependencies.Tokens.TokenOf(r)
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ func (resolver *Resolver) HandleRoute(ctx context.Context, route string) (http.H
|
|||
IndexContext: context,
|
||||
}
|
||||
|
||||
if resolver.Dependencies.Auth.CheckScope("", scopes.ScopeUserLoggedIn, r) != nil {
|
||||
if resolver.Dependencies.Auth.CheckScope("", scopes.ScopeUserValid, r) != nil {
|
||||
ctx.IndexContext.Prefixes = nil
|
||||
}
|
||||
httpx.WriteHTML(tpl.Context(r, ctx), nil, t, "", w, r)
|
||||
|
|
|
|||
|
|
@ -47,12 +47,12 @@ func (admin *Admin) Routes() component.Routes {
|
|||
return component.Routes{
|
||||
Prefix: "/admin/",
|
||||
CSRF: true,
|
||||
Decorator: admin.Dependencies.Auth.Require(false, scopes.ScopeAdminLoggedIn, nil),
|
||||
Decorator: admin.Dependencies.Auth.Require(false, scopes.ScopeUserAdmin, nil),
|
||||
}
|
||||
}
|
||||
|
||||
func (admin *Admin) Menu(r *http.Request) []component.MenuItem {
|
||||
if admin.Dependencies.Auth.CheckScope("", scopes.ScopeAdminLoggedIn, r) != nil {
|
||||
if admin.Dependencies.Auth.CheckScope("", scopes.ScopeUserAdmin, r) != nil {
|
||||
return nil
|
||||
}
|
||||
return []component.MenuItem{
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func (li *ListInstances) ShouldShowList(r *http.Request) bool {
|
|||
return allowPrivate
|
||||
}
|
||||
|
||||
user, _, _ := li.Dependencies.Auth.SessionOf(r)
|
||||
_, user, _ := li.Dependencies.Auth.SessionOf(r)
|
||||
if user == nil {
|
||||
return allowPublic
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -45,10 +45,11 @@ func (server *Server) Server(ctx context.Context, progress io.Writer) (public ht
|
|||
DefaultDomain: slug == "" && ok,
|
||||
}
|
||||
}
|
||||
publicM.Panic = func(panic any, w http.ResponseWriter, r *http.Request) {
|
||||
publicM.Panic = func(p any, stack []byte, w http.ResponseWriter, r *http.Request) {
|
||||
// log the panic
|
||||
logger.Error().
|
||||
Str("panic", fmt.Sprint(panic)).
|
||||
Str("panic", fmt.Sprint(p)).
|
||||
Str("stack", string(stack)).
|
||||
Str("path", r.URL.Path).
|
||||
Msg("panic serving handler")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue