forked from baron/baron-sso
기본 발송 중간
This commit is contained in:
@@ -31,6 +31,10 @@ const (
|
||||
prefixSession = "enchanted_session:"
|
||||
prefixToken = "enchanted_token:"
|
||||
prefixLoginCode = "login_code_flow:"
|
||||
prefixLoginCodePending = "login_code_pending:"
|
||||
prefixLoginCodeSmsTarget = "login_code_sms_target:"
|
||||
prefixLoginCodeSmsLookup = "login_code_sms_lookup:"
|
||||
prefixLoginCodeShort = "login_code_short:"
|
||||
prefixPollMeta = "poll_meta:"
|
||||
prefixSignupEmail = "signup:email:"
|
||||
prefixSignupPhone = "signup:phone:"
|
||||
@@ -202,7 +206,7 @@ func (h *AuthHandler) SendSignupEmailCode(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Email service not configured"})
|
||||
}
|
||||
|
||||
subject := "[Baron SSO] 회원가입 인증코드"
|
||||
subject := "[Baron 통합로그인] 회원가입 인증코드"
|
||||
body := fmt.Sprintf(`
|
||||
<div style="padding: 20px; font-family: sans-serif;">
|
||||
<h2>이메일 인증</h2>
|
||||
@@ -252,7 +256,7 @@ func (h *AuthHandler) SendSignupSmsCode(c *fiber.Ctx) error {
|
||||
h.saveSignupState(key, newState, signupStateExpiration)
|
||||
|
||||
// 4. Send SMS
|
||||
content := fmt.Sprintf("[Baron SSO] 인증번호 [%s]를 입력해주세요.", code)
|
||||
content := fmt.Sprintf("[Baron 통합로그인] 인증번호 [%s]를 입력해주세요.", code)
|
||||
go h.SmsService.SendSms(phone, content)
|
||||
|
||||
return c.JSON(fiber.Map{"message": "Verification code sent"})
|
||||
@@ -535,7 +539,7 @@ func (h *AuthHandler) SendSms(c *fiber.Ctx) error {
|
||||
sanitizedPhone := strings.ReplaceAll(req.PhoneNumber, "-", "")
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
code := fmt.Sprintf("%06d", rand.Intn(1000000))
|
||||
content := fmt.Sprintf("[Baron SSO] 인증번호: %s", code)
|
||||
content := fmt.Sprintf("[Baron 통합로그인] 인증번호: %s", code)
|
||||
|
||||
h.RedisService.StoreVerificationCode(sanitizedPhone, code)
|
||||
if err := h.SmsService.SendSms(sanitizedPhone, content); err != nil {
|
||||
@@ -621,8 +625,19 @@ func (h *AuthHandler) InitEnchantedLink(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
if init, err := h.IdpProvider.InitiateLinkLogin(lookupLoginID, userfrontURL); err == nil && init != nil && init.Mode != "" {
|
||||
keyLoginID := lookupLoginID
|
||||
if init.LoginID != "" {
|
||||
keyLoginID = init.LoginID
|
||||
}
|
||||
if init.FlowID != "" {
|
||||
_ = h.RedisService.Set(prefixLoginCode+lookupLoginID, init.FlowID, loginCodeExpiration)
|
||||
_ = h.RedisService.Set(prefixLoginCode+keyLoginID, init.FlowID, loginCodeExpiration)
|
||||
}
|
||||
pendingRef := GenerateSecureToken(3)
|
||||
h.RedisService.Set(prefixSession+pendingRef, fmt.Sprintf(`{"status":"%s"}`, statusPending), loginCodeExpiration)
|
||||
_ = h.RedisService.Set(prefixLoginCodePending+keyLoginID, pendingRef, loginCodeExpiration)
|
||||
if !strings.Contains(loginID, "@") && keyLoginID != lookupLoginID {
|
||||
_ = h.RedisService.Set(prefixLoginCodeSmsTarget+keyLoginID, lookupLoginID, loginCodeExpiration)
|
||||
_ = h.RedisService.Set(prefixLoginCodeSmsLookup+lookupLoginID, keyLoginID, loginCodeExpiration)
|
||||
}
|
||||
expiresIn := 0
|
||||
if !init.ExpiresAt.IsZero() {
|
||||
@@ -630,7 +645,7 @@ func (h *AuthHandler) InitEnchantedLink(c *fiber.Ctx) error {
|
||||
}
|
||||
return c.JSON(fiber.Map{
|
||||
"linkId": "Sent",
|
||||
"pendingRef": init.FlowID,
|
||||
"pendingRef": pendingRef,
|
||||
"maskedEmail": loginID,
|
||||
"mode": init.Mode,
|
||||
"provider": h.IdpProvider.Name(),
|
||||
@@ -665,7 +680,7 @@ func (h *AuthHandler) InitEnchantedLink(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Email service not configured"})
|
||||
}
|
||||
|
||||
subject := "[Baron SSO] 로그인 링크"
|
||||
subject := "[Baron 통합로그인] 링크"
|
||||
body := fmt.Sprintf(`
|
||||
<div style="font-family: sans-serif; padding: 20px; border: 1px solid #eee; border-radius: 10px; max-width: 500px;">
|
||||
<h2 style="color: #1A1F2C;">Baron SSO 로그인</h2>
|
||||
@@ -686,7 +701,7 @@ func (h *AuthHandler) InitEnchantedLink(c *fiber.Ctx) error {
|
||||
}
|
||||
} else {
|
||||
// Send SMS
|
||||
content := fmt.Sprintf("[Baron SSO] 로그인 링크: %s | 코드: %s", link, userCode)
|
||||
content := fmt.Sprintf("[Baron 통합로그인] 로그인 링크: %s | 코드: %s", link, userCode)
|
||||
slog.Info("[Enchanted] Sending SMS via Naver Cloud", "loginID", loginID)
|
||||
|
||||
if err := h.SmsService.SendSms(loginID, content); err != nil {
|
||||
@@ -714,7 +729,7 @@ func (h *AuthHandler) PollEnchantedLink(c *fiber.Ctx) error {
|
||||
|
||||
pollKey := prefixPollMeta + "enchanted:" + req.PendingRef
|
||||
if slowDown, interval := checkPollInterval(h.RedisService, pollKey, minPollInterval); slowDown {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
return c.JSON(fiber.Map{
|
||||
"error": "slow_down",
|
||||
"interval": interval,
|
||||
})
|
||||
@@ -722,7 +737,7 @@ func (h *AuthHandler) PollEnchantedLink(c *fiber.Ctx) error {
|
||||
|
||||
val, err := h.RedisService.Get(prefixSession + req.PendingRef)
|
||||
if err != nil || val == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "expired_token"})
|
||||
return c.JSON(fiber.Map{"error": "expired_token"})
|
||||
}
|
||||
|
||||
var data map[string]string
|
||||
@@ -736,7 +751,7 @@ func (h *AuthHandler) PollEnchantedLink(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
return c.JSON(fiber.Map{
|
||||
"error": "authorization_pending",
|
||||
"interval": int(minPollInterval.Seconds()),
|
||||
})
|
||||
@@ -802,8 +817,9 @@ func (h *AuthHandler) VerifyMagicLink(c *fiber.Ctx) error {
|
||||
// VerifyLoginCode - Verify Kratos login code and issue session.
|
||||
func (h *AuthHandler) VerifyLoginCode(c *fiber.Ctx) error {
|
||||
var req struct {
|
||||
LoginID string `json:"loginId"`
|
||||
Code string `json:"code"`
|
||||
LoginID string `json:"loginId"`
|
||||
Code string `json:"code"`
|
||||
PendingRef string `json:"pendingRef"`
|
||||
}
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
slog.Error("[LoginCode] Body parse error", "error", err)
|
||||
@@ -843,6 +859,110 @@ func (h *AuthHandler) VerifyLoginCode(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
h.RedisService.Delete(prefixLoginCode + lookupLoginID)
|
||||
h.RedisService.Delete(prefixLoginCodeSmsTarget + lookupLoginID)
|
||||
|
||||
pendingRef := strings.TrimSpace(req.PendingRef)
|
||||
if pendingRef == "" {
|
||||
storedRef, _ := h.RedisService.Get(prefixLoginCodePending + lookupLoginID)
|
||||
pendingRef = storedRef
|
||||
}
|
||||
if pendingRef != "" {
|
||||
sessionData, _ := json.Marshal(map[string]string{
|
||||
"status": statusSuccess,
|
||||
"jwt": authInfo.SessionToken.JWT,
|
||||
})
|
||||
h.RedisService.Set(prefixSession+pendingRef, string(sessionData), loginCodeExpiration)
|
||||
h.RedisService.Delete(prefixLoginCodePending + lookupLoginID)
|
||||
h.RedisService.Delete(prefixLoginCodeSmsTarget + lookupLoginID)
|
||||
return c.JSON(fiber.Map{
|
||||
"status": "approved",
|
||||
"pendingRef": pendingRef,
|
||||
"provider": h.IdpProvider.Name(),
|
||||
"subject": authInfo.Subject,
|
||||
"message": "Login approved",
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{
|
||||
"token": authInfo.SessionToken.JWT,
|
||||
"sessionJwt": authInfo.SessionToken.JWT,
|
||||
"provider": h.IdpProvider.Name(),
|
||||
"subject": authInfo.Subject,
|
||||
"message": "Login successful",
|
||||
})
|
||||
}
|
||||
|
||||
// VerifyLoginShortCode - Verify short code (2 letters + 6 digits) and issue/approve session.
|
||||
func (h *AuthHandler) VerifyLoginShortCode(c *fiber.Ctx) error {
|
||||
var req struct {
|
||||
ShortCode string `json:"shortCode"`
|
||||
}
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
slog.Error("[LoginShortCode] Body parse error", "error", err)
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request body"})
|
||||
}
|
||||
|
||||
shortCode := strings.ToUpper(strings.TrimSpace(req.ShortCode))
|
||||
if shortCode == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "shortCode is required"})
|
||||
}
|
||||
|
||||
val, _ := h.RedisService.Get(prefixLoginCodeShort + shortCode)
|
||||
if val == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid or expired code"})
|
||||
}
|
||||
|
||||
var payload shortLoginCodePayload
|
||||
if err := json.Unmarshal([]byte(val), &payload); err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Invalid code payload"})
|
||||
}
|
||||
if payload.LoginID == "" || payload.Code == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid or expired code"})
|
||||
}
|
||||
|
||||
if h.IdpProvider == nil {
|
||||
return c.Status(fiber.StatusServiceUnavailable).JSON(fiber.Map{"error": "Identity provider unavailable"})
|
||||
}
|
||||
|
||||
flowID, err := h.RedisService.Get(prefixLoginCode + payload.LoginID)
|
||||
if err != nil || flowID == "" {
|
||||
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "Login flow expired"})
|
||||
}
|
||||
|
||||
authInfo, err := h.IdpProvider.VerifyLoginCode(payload.LoginID, flowID, payload.Code)
|
||||
if err != nil {
|
||||
if errors.Is(err, domain.ErrNotSupported) {
|
||||
return c.Status(fiber.StatusNotImplemented).JSON(fiber.Map{"error": "Login method not supported"})
|
||||
}
|
||||
slog.Error("[LoginShortCode] Verify failed", "loginID", payload.LoginID, "error", err)
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid code"})
|
||||
}
|
||||
if authInfo == nil || authInfo.SessionToken == nil || authInfo.SessionToken.JWT == "" {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to issue session"})
|
||||
}
|
||||
|
||||
h.RedisService.Delete(prefixLoginCode + payload.LoginID)
|
||||
h.RedisService.Delete(prefixLoginCodeShort + shortCode)
|
||||
h.RedisService.Delete(prefixLoginCodeSmsTarget + payload.LoginID)
|
||||
h.RedisService.Delete(prefixLoginCodeSmsLookup + payload.LoginID)
|
||||
|
||||
if payload.PendingRef != "" {
|
||||
sessionData, _ := json.Marshal(map[string]string{
|
||||
"status": statusSuccess,
|
||||
"jwt": authInfo.SessionToken.JWT,
|
||||
})
|
||||
h.RedisService.Set(prefixSession+payload.PendingRef, string(sessionData), loginCodeExpiration)
|
||||
h.RedisService.Delete(prefixLoginCodePending + payload.LoginID)
|
||||
return c.JSON(fiber.Map{
|
||||
"status": "approved",
|
||||
"pendingRef": payload.PendingRef,
|
||||
"token": authInfo.SessionToken.JWT,
|
||||
"sessionJwt": authInfo.SessionToken.JWT,
|
||||
"provider": h.IdpProvider.Name(),
|
||||
"subject": authInfo.Subject,
|
||||
"message": "Login approved",
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{
|
||||
"token": authInfo.SessionToken.JWT,
|
||||
@@ -998,7 +1118,7 @@ func (h *AuthHandler) InitiatePasswordReset(c *fiber.Ctx) error {
|
||||
ale.Log(slog.LevelError, "Email service not configured")
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Email service not configured"})
|
||||
}
|
||||
subject := "[Baron SSO] 비밀번호 재설정"
|
||||
subject := "[Baron 통합로그인] 비밀번호 재설정"
|
||||
body := fmt.Sprintf(`
|
||||
<div style="font-family: sans-serif; padding: 20px; border: 1px solid #eee; border-radius: 10px; max-width: 500px;">
|
||||
<h2 style="color: #1A1F2C;">Baron SSO 비밀번호 재설정</h2>
|
||||
@@ -1017,7 +1137,7 @@ func (h *AuthHandler) InitiatePasswordReset(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to send reset email"})
|
||||
}
|
||||
} else {
|
||||
if err := h.SmsService.SendSms(loginID, fmt.Sprintf("[Baron SSO] 비밀번호 재설정 링크: %s", resetLink)); err != nil {
|
||||
if err := h.SmsService.SendSms(loginID, fmt.Sprintf("[Baron 통합로그인] 비밀번호 재설정 링크: %s", resetLink)); err != nil {
|
||||
ale.Status = fiber.StatusInternalServerError
|
||||
ale.LatencyMs = time.Since(startTime)
|
||||
ale.DescopeError = err.Error()
|
||||
@@ -1350,6 +1470,22 @@ func (h *AuthHandler) HandleKratosCourierRelay(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Empty message"})
|
||||
}
|
||||
|
||||
if strings.Contains(req.Recipient, "@") {
|
||||
if target, _ := h.RedisService.Get(prefixLoginCodeSmsTarget + req.Recipient); target != "" {
|
||||
phone := sanitizePhoneForSms(target)
|
||||
smsBody := h.buildKratosShortSmsBody(&req, req.Recipient, phone)
|
||||
if smsBody == "" {
|
||||
smsBody = body
|
||||
}
|
||||
if err := h.SmsService.SendSms(phone, smsBody); err != nil {
|
||||
slog.Error("[Kratos Courier] SMS send failed", "to", phone, "error", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to send SMS"})
|
||||
}
|
||||
slog.Info("[Kratos Courier] SMS sent (email relay)", "to", phone, "template", req.TemplateType)
|
||||
return c.JSON(fiber.Map{"status": "ok"})
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(req.Recipient, "@") {
|
||||
if h.EmailService == nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Email service not configured"})
|
||||
@@ -1366,7 +1502,20 @@ func (h *AuthHandler) HandleKratosCourierRelay(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "SMS service not configured"})
|
||||
}
|
||||
phone := sanitizePhoneForSms(req.Recipient)
|
||||
if err := h.SmsService.SendSms(phone, body); err != nil {
|
||||
loginID := req.Recipient
|
||||
if !strings.Contains(loginID, "@") {
|
||||
lookup := normalizePhoneForLoginID(loginID)
|
||||
if email, _ := h.RedisService.Get(prefixLoginCodeSmsLookup + lookup); email != "" {
|
||||
loginID = email
|
||||
} else {
|
||||
loginID = lookup
|
||||
}
|
||||
}
|
||||
smsBody := h.buildKratosShortSmsBody(&req, loginID, phone)
|
||||
if smsBody == "" {
|
||||
smsBody = body
|
||||
}
|
||||
if err := h.SmsService.SendSms(phone, smsBody); err != nil {
|
||||
slog.Error("[Kratos Courier] SMS send failed", "to", phone, "error", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to send SMS"})
|
||||
}
|
||||
@@ -1379,7 +1528,7 @@ func (h *AuthHandler) buildKratosCourierMessage(req *kratosCourierRequest) (stri
|
||||
body := strings.TrimSpace(req.Body)
|
||||
if body != "" || subject != "" {
|
||||
if subject == "" {
|
||||
subject = "[Baron SSO] 알림"
|
||||
subject = "[Baron 통합로그인] 알림"
|
||||
}
|
||||
return subject, body
|
||||
}
|
||||
@@ -1403,23 +1552,38 @@ func (h *AuthHandler) buildKratosCourierMessage(req *kratosCourierRequest) (stri
|
||||
|
||||
if subject == "" {
|
||||
if label == "알림" {
|
||||
subject = "[Baron SSO] 알림"
|
||||
subject = "[Baron 통합로그인] 알림"
|
||||
} else {
|
||||
subject = fmt.Sprintf("[Baron SSO] %s 코드", label)
|
||||
subject = fmt.Sprintf("[Baron 통합로그인] %s 코드", label)
|
||||
}
|
||||
}
|
||||
|
||||
if code == "" {
|
||||
return subject, fmt.Sprintf("[Baron SSO] %s 요청이 도착했습니다", label)
|
||||
return subject, fmt.Sprintf("[Baron 통합로그인] %s 요청이 도착했습니다", label)
|
||||
}
|
||||
|
||||
message := fmt.Sprintf("[Baron SSO] %s 코드: %s", label, code)
|
||||
message := fmt.Sprintf("[Baron 통합로그인] %s 코드: %s", label, code)
|
||||
if label == "로그인" {
|
||||
baseURL := os.Getenv("USERFRONT_URL")
|
||||
if baseURL == "" {
|
||||
baseURL = "http://localhost:5000"
|
||||
}
|
||||
baseURL = strings.TrimRight(baseURL, "/")
|
||||
loginID := req.Recipient
|
||||
if !strings.Contains(loginID, "@") {
|
||||
loginID = normalizePhoneForLoginID(loginID)
|
||||
}
|
||||
pendingRef, _ := h.RedisService.Get(prefixLoginCodePending + loginID)
|
||||
if pendingRef != "" {
|
||||
message = fmt.Sprintf("%s | 링크: %s/verify?loginId=%s&code=%s&pendingRef=%s",
|
||||
message,
|
||||
baseURL,
|
||||
url.QueryEscape(req.Recipient),
|
||||
url.QueryEscape(code),
|
||||
url.QueryEscape(pendingRef),
|
||||
)
|
||||
return subject, message
|
||||
}
|
||||
link := fmt.Sprintf("%s/verify?loginId=%s&code=%s",
|
||||
baseURL,
|
||||
url.QueryEscape(req.Recipient),
|
||||
@@ -1431,6 +1595,78 @@ func (h *AuthHandler) buildKratosCourierMessage(req *kratosCourierRequest) (stri
|
||||
return subject, message
|
||||
}
|
||||
|
||||
type shortLoginCodePayload struct {
|
||||
LoginID string `json:"loginId"`
|
||||
Code string `json:"code"`
|
||||
PendingRef string `json:"pendingRef"`
|
||||
}
|
||||
|
||||
func (h *AuthHandler) buildKratosShortSmsBody(req *kratosCourierRequest, loginID, phone string) string {
|
||||
if req == nil || loginID == "" {
|
||||
return ""
|
||||
}
|
||||
code := normalizeLoginCode(extractFirstString(req.TemplateData, "login_code"))
|
||||
if code == "" {
|
||||
return ""
|
||||
}
|
||||
shortCode := h.generateShortCode(code)
|
||||
if shortCode == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
pendingRef, _ := h.RedisService.Get(prefixLoginCodePending + loginID)
|
||||
payload := shortLoginCodePayload{
|
||||
LoginID: loginID,
|
||||
Code: code,
|
||||
PendingRef: pendingRef,
|
||||
}
|
||||
raw, _ := json.Marshal(payload)
|
||||
_ = h.RedisService.Set(prefixLoginCodeShort+shortCode, string(raw), loginCodeExpiration)
|
||||
|
||||
baseURL := strings.TrimRight(os.Getenv("USERFRONT_URL"), "/")
|
||||
if baseURL == "" {
|
||||
baseURL = "http://localhost:5000"
|
||||
}
|
||||
|
||||
link := fmt.Sprintf("%s/l/%s", baseURL, shortCode)
|
||||
return fmt.Sprintf("[Baron 통합로그인] %s", link)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) generateShortCode(code string) string {
|
||||
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
for i := 0; i < 10; i++ {
|
||||
b := make([]byte, 2)
|
||||
if _, err := crand.Read(b); err != nil {
|
||||
break
|
||||
}
|
||||
prefix := string(letters[int(b[0])%len(letters)]) + string(letters[int(b[1])%len(letters)])
|
||||
shortCode := prefix + code
|
||||
if val, _ := h.RedisService.Get(prefixLoginCodeShort + shortCode); val == "" {
|
||||
return shortCode
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func normalizeLoginCode(code string) string {
|
||||
if code == "" {
|
||||
return ""
|
||||
}
|
||||
digits := make([]rune, 0, len(code))
|
||||
for _, ch := range code {
|
||||
if ch >= '0' && ch <= '9' {
|
||||
digits = append(digits, ch)
|
||||
}
|
||||
}
|
||||
if len(digits) < 6 {
|
||||
return ""
|
||||
}
|
||||
if len(digits) > 6 {
|
||||
digits = digits[:6]
|
||||
}
|
||||
return string(digits)
|
||||
}
|
||||
|
||||
func firstNonEmpty(values ...string) string {
|
||||
for _, value := range values {
|
||||
if value != "" {
|
||||
@@ -1941,7 +2177,7 @@ func (h *AuthHandler) SendUpdateCode(c *fiber.Ctx) error {
|
||||
h.RedisService.Set(key, code, 5*time.Minute)
|
||||
|
||||
// Send SMS
|
||||
content := fmt.Sprintf("[Baron SSO] 정보 수정 인증번호: [%s]", code)
|
||||
content := fmt.Sprintf("[Baron 통합로그인] 정보 수정 인증번호: [%s]", code)
|
||||
go h.SmsService.SendSms(phone, content)
|
||||
|
||||
return c.JSON(fiber.Map{"message": "인증번호가 전송되었습니다."})
|
||||
|
||||
Reference in New Issue
Block a user