✨ Real feel-less refresh token
This commit is contained in:
@ -137,12 +137,12 @@ func doRegister(c *fiber.Ctx) error {
|
||||
return err
|
||||
} else if viper.GetBool("use_registration_magic_token") && len(data.MagicToken) <= 0 {
|
||||
return fmt.Errorf("missing magic token in request")
|
||||
}
|
||||
|
||||
if tk, err := services.ValidateMagicToken(data.MagicToken, models.RegistrationMagicToken); err != nil {
|
||||
return err
|
||||
} else {
|
||||
database.C.Delete(&tk)
|
||||
} else if viper.GetBool("use_registration_magic_token") {
|
||||
if tk, err := services.ValidateMagicToken(data.MagicToken, models.RegistrationMagicToken); err != nil {
|
||||
return err
|
||||
} else {
|
||||
database.C.Delete(&tk)
|
||||
}
|
||||
}
|
||||
|
||||
if user, err := services.CreateAccount(
|
||||
|
@ -1,36 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"code.smartsheep.studio/hydrogen/identity/pkg/security"
|
||||
"code.smartsheep.studio/hydrogen/identity/pkg/services"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/keyauth"
|
||||
)
|
||||
|
||||
var auth = keyauth.New(keyauth.Config{
|
||||
KeyLookup: "header:Authorization",
|
||||
AuthScheme: "Bearer",
|
||||
Validator: func(c *fiber.Ctx, token string) (bool, error) {
|
||||
claims, err := security.DecodeJwt(token)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
session, err := services.LookupSessionWithToken(claims.ID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
} else if err := session.IsAvailable(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
user, err := services.GetAccount(session.AccountID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
c.Locals("principal", user)
|
||||
|
||||
return true, nil
|
||||
},
|
||||
ContextKey: "token",
|
||||
})
|
72
pkg/server/auth_middleware.go
Normal file
72
pkg/server/auth_middleware.go
Normal file
@ -0,0 +1,72 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"code.smartsheep.studio/hydrogen/identity/pkg/security"
|
||||
"code.smartsheep.studio/hydrogen/identity/pkg/services"
|
||||
"fmt"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func authMiddleware(c *fiber.Ctx) error {
|
||||
var token string
|
||||
if cookie := c.Cookies(security.CookieAccessKey); len(cookie) > 0 {
|
||||
token = cookie
|
||||
}
|
||||
if header := c.Get(fiber.HeaderAuthorization); len(header) > 0 {
|
||||
tk := strings.Replace(header, "Bearer", "", 1)
|
||||
token = strings.TrimSpace(tk)
|
||||
}
|
||||
|
||||
c.Locals("token", token)
|
||||
|
||||
if err := authFunc(c); err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
func authFunc(c *fiber.Ctx, overrides ...string) error {
|
||||
var token string
|
||||
if len(overrides) > 0 {
|
||||
token = overrides[0]
|
||||
} else {
|
||||
if tk, ok := c.Locals("token").(string); !ok {
|
||||
return fiber.NewError(fiber.StatusUnauthorized)
|
||||
} else {
|
||||
token = tk
|
||||
}
|
||||
}
|
||||
|
||||
claims, err := security.DecodeJwt(token)
|
||||
if err != nil {
|
||||
rtk := c.Cookies(security.CookieRefreshKey)
|
||||
if len(rtk) > 0 && len(overrides) < 1 {
|
||||
// Auto refresh and retry
|
||||
access, refresh, err := security.RefreshToken(rtk)
|
||||
if err == nil {
|
||||
security.SetJwtCookieSet(c, access, refresh)
|
||||
return authFunc(c, access)
|
||||
}
|
||||
}
|
||||
return fiber.NewError(fiber.StatusUnauthorized, fmt.Sprintf("invalid auth key: %v", err))
|
||||
}
|
||||
|
||||
session, err := services.LookupSessionWithToken(claims.ID)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusUnauthorized, fmt.Sprintf("invalid auth session: %v", err))
|
||||
} else if err := session.IsAvailable(); err != nil {
|
||||
return fiber.NewError(fiber.StatusUnauthorized, fmt.Sprintf("unavailable auth session: %v", err))
|
||||
}
|
||||
|
||||
user, err := services.GetAccount(session.AccountID)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusUnauthorized, fmt.Sprintf("invalid account: %v", err))
|
||||
}
|
||||
|
||||
c.Locals("principal", user)
|
||||
|
||||
return nil
|
||||
}
|
@ -127,6 +127,8 @@ func exchangeToken(c *fiber.Ctx) error {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "unsupported exchange token type")
|
||||
}
|
||||
|
||||
security.SetJwtCookieSet(c, access, refresh)
|
||||
|
||||
return c.JSON(fiber.Map{
|
||||
"id_token": access,
|
||||
"access_token": access,
|
||||
|
@ -58,18 +58,18 @@ func NewServer() {
|
||||
api := A.Group("/api").Name("API")
|
||||
{
|
||||
api.Get("/avatar/:avatarId", getAvatar)
|
||||
api.Put("/avatar", auth, setAvatar)
|
||||
api.Put("/avatar", authMiddleware, setAvatar)
|
||||
|
||||
api.Get("/notifications", auth, getNotifications)
|
||||
api.Put("/notifications/:notificationId/read", auth, markNotificationRead)
|
||||
api.Post("/notifications/subscribe", auth, addNotifySubscriber)
|
||||
api.Get("/notifications", authMiddleware, getNotifications)
|
||||
api.Put("/notifications/:notificationId/read", authMiddleware, markNotificationRead)
|
||||
api.Post("/notifications/subscribe", authMiddleware, addNotifySubscriber)
|
||||
|
||||
api.Get("/users/me", auth, getUserinfo)
|
||||
api.Put("/users/me", auth, editUserinfo)
|
||||
api.Get("/users/me/events", auth, getEvents)
|
||||
api.Get("/users/me/challenges", auth, getChallenges)
|
||||
api.Get("/users/me/sessions", auth, getSessions)
|
||||
api.Delete("/users/me/sessions/:sessionId", auth, killSession)
|
||||
api.Get("/users/me", authMiddleware, getUserinfo)
|
||||
api.Put("/users/me", authMiddleware, editUserinfo)
|
||||
api.Get("/users/me/events", authMiddleware, getEvents)
|
||||
api.Get("/users/me/challenges", authMiddleware, getChallenges)
|
||||
api.Get("/users/me/sessions", authMiddleware, getSessions)
|
||||
api.Delete("/users/me/sessions/:sessionId", authMiddleware, killSession)
|
||||
|
||||
api.Post("/users", doRegister)
|
||||
api.Post("/users/me/confirm", doRegisterConfirm)
|
||||
@ -79,8 +79,8 @@ func NewServer() {
|
||||
api.Post("/auth/token", exchangeToken)
|
||||
api.Post("/auth/factors/:factorId", requestFactorToken)
|
||||
|
||||
api.Get("/auth/o/connect", auth, preConnect)
|
||||
api.Post("/auth/o/connect", auth, doConnect)
|
||||
api.Get("/auth/o/connect", authMiddleware, preConnect)
|
||||
api.Post("/auth/o/connect", authMiddleware, doConnect)
|
||||
|
||||
developers := api.Group("/dev").Name("Developers API")
|
||||
{
|
||||
|
@ -21,8 +21,8 @@ func getOidcConfiguration(c *fiber.Ctx) error {
|
||||
|
||||
return c.JSON(fiber.Map{
|
||||
"issuer": basepath,
|
||||
"authorization_endpoint": fmt.Sprintf("%s/auth/o/connect", basepath),
|
||||
"token_endpoint": fmt.Sprintf("%s/api/auth/token", basepath),
|
||||
"authorization_endpoint": fmt.Sprintf("%s/authMiddleware/o/connect", basepath),
|
||||
"token_endpoint": fmt.Sprintf("%s/api/authMiddleware/token", basepath),
|
||||
"userinfo_endpoint": fmt.Sprintf("%s/api/users/me", basepath),
|
||||
"response_types_supported": []string{"code", "token"},
|
||||
"grant_types_supported": []string{"authorization_code", "implicit", "refresh_token"},
|
||||
|
Reference in New Issue
Block a user