Real feel-less refresh token

This commit is contained in:
2024-02-18 15:51:27 +08:00
parent cc2aa8ef40
commit 00028cfce8
20 changed files with 250 additions and 210 deletions

View File

@ -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(

View File

@ -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",
})

View 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
}

View File

@ -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,

View File

@ -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")
{

View File

@ -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"},