diff --git a/pkg/auth/authenticator.go b/pkg/auth/authenticator.go index f87669a..8056c9f 100644 --- a/pkg/auth/authenticator.go +++ b/pkg/auth/authenticator.go @@ -64,7 +64,7 @@ func (a *Authenticator) InitAuth(s storage.Store) error { return nil } -type AuthProvider interface { +type AuthProvider interface { // TODO: this should include stepping ProviderName() string ProviderID() *string ProviderType() string diff --git a/pkg/auth/flow.go b/pkg/auth/flow.go index 27ff791..f732976 100644 --- a/pkg/auth/flow.go +++ b/pkg/auth/flow.go @@ -239,7 +239,3 @@ func (a *Authenticator) LoginFlowHandler(c echo.Context) error { return flow.progress(a, c) } - -func (a *Authenticator) TokenHandler(c echo.Context) error { - return c.String(http.StatusOK, "token good I guess") -} diff --git a/pkg/auth/provider.go b/pkg/auth/provider.go index 4b6d240..895ad6e 100644 --- a/pkg/auth/provider.go +++ b/pkg/auth/provider.go @@ -3,6 +3,7 @@ package auth import ( "encoding/base64" + "github.com/rs/zerolog/log" "golang.org/x/crypto/bcrypt" "dynatron.me/x/blasphem/pkg/storage" @@ -69,7 +70,7 @@ func (hap *HomeAssistantProvider) ValidateCreds(rm map[string]interface{}) bool var hash []byte hash, err := base64.StdEncoding.DecodeString(found.Password) if err != nil { - // XXX: probably log this + log.Error().Err(err).Msg("b64 encode fail") return false } diff --git a/pkg/auth/session.go b/pkg/auth/session.go index d0f89cb..2dc6624 100644 --- a/pkg/auth/session.go +++ b/pkg/auth/session.go @@ -3,6 +3,8 @@ package auth import ( "net/http" "time" + + "github.com/labstack/echo/v4" ) type SessionStore struct { @@ -12,10 +14,10 @@ type SessionStore struct { type TokenID string -type Token struct { +type Token struct { // TODO: jwt bro ID TokenID Ctime time.Time - Expires time.Duration + Expires time.Time Addr string } @@ -28,7 +30,7 @@ const cullInterval = 5 * time.Minute func (ss *SessionStore) cull() { if now := time.Now(); now.Sub(ss.lastCull) > cullInterval { for k, v := range ss.s { - if now.After(v.Ctime.Add(v.Expires)) { + if now.After(v.Expires) { delete(ss.s, k) } } @@ -40,16 +42,51 @@ func (ss *SessionStore) register(t *Token) { ss.s[t.ID] = t } +func (ss *SessionStore) verify(tr *TokenRequest, r *http.Request) bool { + if t, hasToken := ss.s[tr.Code]; hasToken { + // TODO: JWT + if t.Expires.After(time.Now()) { + return true + } + } + + return false +} + +const defaultExpiration = 2 * time.Hour + func (a *Authenticator) NewToken(r *http.Request, f *Flow) TokenID { id := TokenID(genUUID()) t := &Token{ - ID: id, - Ctime: time.Now(), - Addr: r.RemoteAddr, + ID: id, + Ctime: time.Now(), + Expires: time.Now().Add(defaultExpiration), + Addr: r.RemoteAddr, } a.Sessions.register(t) return id } + +type TokenRequest struct { + ClientID string `query:"client_id"` // TODO: validate this? + Code TokenID `query:"code"` + GrantType string `query:"grant_type"` +} + +func (a *Authenticator) TokenHandler(c echo.Context) error { + var rq TokenRequest + err := c.Bind(&rq) + if err != nil { + return err + } + + if a.Sessions.verify(&rq, c.Request()) { + // TODO: success + return c.String(http.StatusOK, "token good I guess") + } + + return c.String(http.StatusUnauthorized, "token bad I guess") +}