Skip to content

Commit

Permalink
Merge pull request #60 from jovandeginste/allow-api-via-jwt
Browse files Browse the repository at this point in the history
Allow API access via JWT authentication
  • Loading branch information
jovandeginste committed Apr 6, 2024
2 parents 5d28924 + 12e67b4 commit 179acb7
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 29 deletions.
53 changes: 35 additions & 18 deletions pkg/app/api_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (
"strconv"

"github.com/jovandeginste/workout-tracker/pkg/database"
echojwt "github.com/labstack/echo-jwt/v4"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/labstack/gommon/log"
)

var ErrInvalidAPIKey = errors.New("invalid API key")
Expand All @@ -19,6 +21,18 @@ type APIResponse struct {

func (a *App) apiRoutes(e *echo.Group) {
apiGroup := e.Group("/api/v1")
apiGroup.Use(echojwt.WithConfig(echojwt.Config{
SigningKey: a.jwtSecret(),
TokenLookup: "cookie:token",
ErrorHandler: func(c echo.Context, err error) error {
log.Warn(err.Error())
return c.JSON(http.StatusForbidden, "Not authorized")
},
Skipper: func(ctx echo.Context) bool {
return ctx.Request().Header.Get("Authorization") != ""
},
SuccessHandler: a.ValidateUserMiddleware,
}))
apiGroup.Use(a.ValidateAPIKeyMiddleware())

apiGroup.GET("/whoami", a.apiWhoamiHandler).Name = "api-whoami"
Expand All @@ -27,28 +41,31 @@ func (a *App) apiRoutes(e *echo.Group) {
}

func (a *App) ValidateAPIKeyMiddleware() echo.MiddlewareFunc {
return middleware.KeyAuth(func(key string, c echo.Context) (bool, error) {
u, err := database.GetUserByAPIKey(a.db, key)
if err != nil {
return false, ErrInvalidAPIKey
}

if !u.IsActive() || !u.Profile.APIActive {
return false, ErrInvalidAPIKey
}

c.Set("user_info", u)
c.Set("user_language", u.Profile.Language)
c.Set("user_totals_show", u.Profile.TotalsShow)

return true, nil
return middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{
Validator: func(key string, c echo.Context) (bool, error) {
u, err := database.GetUserByAPIKey(a.db, key)
if err != nil {
return false, ErrInvalidAPIKey
}

if !u.IsActive() || !u.Profile.APIActive {
return false, ErrInvalidAPIKey
}

c.Set("user_info", u)
c.Set("user_language", u.Profile.Language)
c.Set("user_totals_show", u.Profile.TotalsShow)

return true, nil
},
Skipper: func(ctx echo.Context) bool {
return ctx.Request().Header.Get("Authorization") == ""
},
})
}

func (a *App) apiWhoamiHandler(c echo.Context) error {
data := a.defaultData(c)

return c.JSON(http.StatusOK, data)
return c.JSON(http.StatusOK, a.getCurrentUser(c))
}

func (a *App) apiWorkoutsHandler(c echo.Context) error {
Expand Down
13 changes: 4 additions & 9 deletions pkg/app/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,9 @@ func (a *App) ValidateAdminMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
}
}

func (a *App) ValidateUserMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(ctx echo.Context) error {
if err := a.setUser(ctx); err != nil {
log.Warn(err.Error())
return ctx.Redirect(http.StatusFound, a.echo.Reverse("user-signout"))
}

return next(ctx)
func (a *App) ValidateUserMiddleware(ctx echo.Context) {
if err := a.setUser(ctx); err != nil {
log.Warn(err.Error())
}
}

Expand All @@ -117,8 +112,8 @@ func (a *App) secureRoutes(e *echo.Group) *echo.Group {
log.Warn(err.Error())
return c.Redirect(http.StatusFound, a.echo.Reverse("user-signout"))
},
SuccessHandler: a.ValidateUserMiddleware,
}))
secureGroup.Use(a.ValidateUserMiddleware)

secureGroup.GET("/", a.dashboardHandler).Name = "dashboard"
secureGroup.GET("/statistics", a.statisticsHandler).Name = "statistics"
Expand Down
2 changes: 1 addition & 1 deletion pkg/database/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type Profile struct {
Timezone string `form:"timezone"`
AutoImportDirectory string `form:"auto_import_directory"`

User *User `gorm:"foreignKey:UserID"`
User *User `gorm:"foreignKey:UserID" json:"-"`
}

func (p *Profile) Save(db *gorm.DB) error {
Expand Down
2 changes: 1 addition & 1 deletion pkg/database/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type User struct {
Admin bool `form:"admin"`

Profile Profile
Workouts []Workout
Workouts []Workout `json:"-"`
}

func (u *User) Timezone() *time.Location {
Expand Down

0 comments on commit 179acb7

Please sign in to comment.