package auth import ( "fmt" "net/url" "time" "backend/app/consts" "backend/app/http/users" "backend/database/fields" "backend/providers/jwt" "backend/providers/otel" "backend/providers/wechat" "github.com/gofiber/fiber/v3" "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) const StatePrefix = "sns_basic_auth" // @provider type Controller struct { svc *Service userSvc *users.Service jwt *jwt.JWT wechat *wechat.Client log *log.Entry `inject:"false"` } func (ctl *Controller) Prepare() error { ctl.log = log.WithField("module", "auth.Controller") return nil } // @Router /auth/wechat/jump [get] // @Bind redirectUri query func (ctl *Controller) JumpToAuth(ctx fiber.Ctx, redirectUri string) error { _, span := otel.Start(ctx.Context(), "auth.controller.wechat") defer span.End() ctl.log.Debugf("%s, query: %v", ctx.OriginalURL(), ctx.Queries()) paramRedirect := ctx.Query("redirect") // 添加 redirect 参数 u, err := url.Parse(string(ctx.Request().URI().FullURI())) if err != nil { return err } query := u.Query() query.Set("redirect", paramRedirect) u.RawQuery = query.Encode() u.Path = "/auth/wechat/login" fullUrl := u.String() ctl.log.WithField("module", "middleware.SilentAuth").Debug("redirect_uri: ", fullUrl) to, err := ctl.wechat.ScopeAuthorizeURL( wechat.ScopeAuthorizeURLWithRedirectURI(fullUrl), wechat.ScopeAuthorizeURLWithState(fmt.Sprintf("%s-%d", StatePrefix, time.Now().UnixNano())), ) if err != nil { return errors.Wrap(err, "failed to get wechat auth url") } return ctx.Redirect().To(to.String()) } // @Router /auth/login [get] // @Bind code query // @Bind state query // @Bind redirectUri query func (ctl *Controller) Login(ctx fiber.Ctx, code, state, redirectUri string) error { ctl.log.Debugf("code: %s, state: %s", code, state) // get the openid token, err := ctl.wechat.AuthorizeCode2Token(code) if err != nil { return errors.Wrap(err, "failed to get openid") } ctl.log.Debugf("tokenInfo %+v", token) userID, err := ctl.userSvc.GetUserIDByOpenID(ctx.Context(), fields.AuthChannelWeChat, token.GetOpenID()) if err != nil { return errors.Wrap(err, "failed to get user") } jwtToken, err := ctl.jwt.CreateToken(ctl.jwt.CreateClaims(jwt.BaseClaims{UserID: userID})) if err != nil { return errors.Wrap(err, "failed to create token") } ctx.Cookie(&fiber.Cookie{ Name: consts.TokenTypeUser.String(), Value: jwtToken, Expires: time.Now().Add(6 * time.Hour), HTTPOnly: true, }) return ctx.Redirect().To(redirectUri) } // @Router /MP_verify_:uuid.txt [get] // @Bind uuid path func (ctl *Controller) Verify(ctx fiber.Ctx, uuid string) error { v, err := ctl.wechat.VerifySite(uuid) if err != nil { return err } return ctx.SendString(v) }