feat: recover password & refresh token
This commit is contained in:
+102
-14
@@ -5,7 +5,10 @@ import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FernandoVideira/LK_API_Temp/internal/mailer"
|
||||
@@ -47,7 +50,7 @@ type AuthResponse struct {
|
||||
// @Success 201 {object} UserWithToken "User Registered"
|
||||
// @Failure 400 {object} error "User payload error"
|
||||
// @Failure 500 {object} error "Internal Server Error"
|
||||
// @Router /authentication/user [post]
|
||||
// @Router /authentication/register [post]
|
||||
func (api *api) registerUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var payload RegisterUserPayload
|
||||
if err := readJSON(w, r, &payload); err != nil {
|
||||
@@ -187,25 +190,76 @@ func (api *api) createTokenHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
claims := &jwt.MapClaims{
|
||||
"sub": user.ID,
|
||||
"exp": time.Now().Add(api.config.auth.token.exp).Unix(),
|
||||
"iat": time.Now().Unix(),
|
||||
"nbf": time.Now().Unix(),
|
||||
"iss": api.config.auth.token.iss,
|
||||
"aud": api.config.auth.token.aud,
|
||||
}
|
||||
|
||||
//* generate a new token -> add the claims
|
||||
token, err := api.authenticator.GenerateToken(claims)
|
||||
//* send the token back to the user
|
||||
authResponse, err := api.createTokens(user)
|
||||
if err != nil {
|
||||
api.internalServerError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
//* send the token back to the user
|
||||
if err := api.jsonResponse(w, http.StatusCreated, authResponse); err != nil {
|
||||
api.internalServerError(w, r, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := api.jsonResponse(w, http.StatusCreated, token); err != nil {
|
||||
// RefreshTokenHandler godoc
|
||||
//
|
||||
// @Summary Refresh a token
|
||||
// @Description Refresh a token for the user
|
||||
// @Tags authentication
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param Authorization header string true "Refresh Token"
|
||||
// @Success 201 {string} string "Token Created"
|
||||
// @Failure 400 {object} error
|
||||
// @Failure 401 {object} error
|
||||
// @Failure 500 {object} error
|
||||
// @Router /authentication/refresh [post]
|
||||
func (api *api) refreshTokenHandler(w http.ResponseWriter, r *http.Request) {
|
||||
//* parse the refresh token from the request
|
||||
refreshHeader := r.Header.Get("Authorization")
|
||||
if refreshHeader == "" {
|
||||
api.unauthorizedError(w, r, errors.New("refresh token is required"))
|
||||
return
|
||||
}
|
||||
parts := strings.Split(refreshHeader, " ")
|
||||
if len(parts) != 2 || parts[0] != "Bearer" {
|
||||
api.unauthorizedError(w, r, fmt.Errorf("invalid Authorization header"))
|
||||
return
|
||||
}
|
||||
|
||||
refreshToken := parts[1]
|
||||
|
||||
token, err := api.authenticator.ValidateRefreshToken(refreshToken)
|
||||
if err != nil {
|
||||
api.unauthorizedError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
|
||||
//* get the user id from the token
|
||||
userID, err := strconv.ParseInt(fmt.Sprintf("%.f", claims["sub"]), 10, 64)
|
||||
if err != nil {
|
||||
api.unauthorizedError(w, r, fmt.Errorf("invalid token"))
|
||||
return
|
||||
}
|
||||
|
||||
//* get the user from the database
|
||||
user, err := api.store.Users.GetByID(r.Context(), userID)
|
||||
if err != nil {
|
||||
api.unauthorizedError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
authResponse, err := api.createTokens(user)
|
||||
if err != nil {
|
||||
api.unauthorizedError(w, r, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := api.jsonResponse(w, http.StatusCreated, authResponse); err != nil {
|
||||
api.internalServerError(w, r, err)
|
||||
return
|
||||
}
|
||||
@@ -288,3 +342,37 @@ func (api *api) forgotPasswordHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (api *api) createTokens(user *store.User) (AuthResponse, error) {
|
||||
claims := &jwt.MapClaims{
|
||||
"sub": user.ID,
|
||||
"exp": time.Now().Add(api.config.auth.token.exp).Unix(),
|
||||
"iat": time.Now().Unix(),
|
||||
"nbf": time.Now().Unix(),
|
||||
"iss": api.config.auth.token.iss,
|
||||
"aud": api.config.auth.token.aud,
|
||||
}
|
||||
|
||||
//* generate a new token -> add the claims
|
||||
token, err := api.authenticator.GenerateToken(claims)
|
||||
if err != nil {
|
||||
return AuthResponse{}, err
|
||||
}
|
||||
|
||||
refreshClaims := &jwt.MapClaims{
|
||||
"sub": user.ID,
|
||||
"exp": time.Now().Add(api.config.auth.token.refreshExp).Unix(),
|
||||
}
|
||||
|
||||
log.Println(time.Now().Add(api.config.auth.token.refreshExp).Unix())
|
||||
|
||||
refreshToken, err := api.authenticator.GenerateRefreshToken(refreshClaims)
|
||||
if err != nil {
|
||||
return AuthResponse{}, err
|
||||
}
|
||||
|
||||
return AuthResponse{
|
||||
Token: token,
|
||||
RefreshToken: refreshToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user