Aula 13 – Golang – Fiber – Usuário Autenticado

Aula 13 – Golang – Fiber – Usuário Autenticado

Voltar para página principal do site

Todas as aulas desse curso

Aula 12                                               Aula 14

Fiber

Fiber

Pacote Programador Fullstack

Pacote Programador Fullstack

Redes Sociais:

facebook        

Link para a Digital Innovation

Quer aprender python3 de graça e com certificado? Acesse então:

workover

Meus link de afiliados:

Hostinger

Digital Ocean

One.com

Código da aula: Github

Melhore seu NETWORKING

Participe de comunidades de desenvolvedores:

Fiquem a vontade para me adicionar ao linkedin.

E também para me seguir no GITHUB.

Canais do Youtube

Toti

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

PIX para doações

PIX Nubank

PIX Nubank


Aula 13 – Golang – Fiber – Usuário Autenticado

Claims

Em geral, em sistemas de autenticação e autorização, um “claim” (ou “reivindicação“, em português) é uma afirmação feita sobre um usuário autenticado ou um recurso a ser protegido.

Essa afirmação pode incluir informações como nome de usuário, papel ou função, permissões de acesso, propriedades personalizadas e assim por diante.

Em um contexto de token de acesso, como um token JWT, as reivindicações são campos que armazenam informações adicionais sobre o token e o usuário autenticado.

As reivindicações podem ser incluídas no token para fornecer informações adicionais sobre o usuário, como seu ID, nome, função ou outros detalhes relevantes.

As reivindicações são frequentemente usadas em sistemas de autorização para permitir ou negar o acesso a recursos com base nas informações fornecidas no token.

Por exemplo, um recurso pode ser protegido por uma política de acesso que permite apenas usuários com uma determinada função acessarem o recurso.

Nesse caso, a função do usuário seria incluída como uma reivindicação no token de acesso e seria usada para tomar decisões de autorização.

No contexto do JWT, as reivindicações são armazenadas como pares de chave-valor no corpo do token.

Existem três tipos de reivindicações definidas pela especificação JWT:

  • Reivindicações registradas (Registered Claims): incluem informações comuns, como o emissor do token, a data de expiração, etc.
  • Reivindicações públicas (Public Claims): são definidas pelo usuário e compartilhadas publicamente, mas não são obrigatórias ou registradas.
  • Reivindicações privadas (Private Claims): são definidas pelo usuário e não compartilhadas publicamente.

Juntos, esses tipos de reivindicações fornecem um meio flexível e extensível para incluir informações adicionais em um token de acesso JWT.

Agora que entendemos um pouco mais sobre Claims, vamos usar no nosso código, mas, antes vamos criar o endpoint /user.

fiber-project/routes/routes.go


package routes

import (
	"fiber-project/controllers"

	"github.com/gofiber/fiber/v2"
)

func Setup(app *fiber.App) {
	app.Post("/api/register", controllers.Register)
	app.Post("/api/login", controllers.Login)
	app.Get("/api/user", controllers.User)
}

fiber-project/controllers/authController.go

package controllers

import (
	"fiber-project/database"
	"fiber-project/models"

	"github.com/gofiber/fiber/v2"
	"golang.org/x/crypto/bcrypt"
        "github.com/golang-jwt/jwt/v4"
        "strconv"
        "time"
)

type Claims struct {
	jwt.StandardClaims
}

func Register(c *fiber.Ctx) error {
	var data map[string]string

	if err := c.BodyParser(&data); err != nil {
		return err
	}
	if data["password"] != data["confirm_password"] {
		c.Status(400)
		return c.JSON(fiber.Map{
			"message": "Passwords do not match!",
		})
	}

	password, _ := bcrypt.GenerateFromPassword([]byte(data["password"]), 14)

	user := models.User{
		FirstName: data["first_name"],
		LastName:  data["last_name"],
		Email:     data["email"],
		Password:  password,
	}

	database.DB.Create(&user)
	return c.JSON(user)
}

func Login(c *fiber.Ctx) error {
	//get the request parameter
	var data map[string]string

	if err := c.BodyParser(&data); err != nil {
		return err
	}

	var user models.User
	//get user by email
	database.DB.Where("email = ?", data["email"]).First(&user)

        //user not found
	if user.Id == 0 {
		c.Status(404)
		return c.JSON(fiber.Map{
			"message": "User not found!",
		})
	}
        //incorrect password
        if err := bcrypt.CompareHashAndPassword(user.Password, []byte(data["password"])); err != nil {
		c.Status(400)
		return c.JSON(fiber.Map{
			"message": "Incorrect password!",
		})
	}
        claims := jwt.RegisteredClaims{
		Issuer:        strconv.Itoa(int(user.Id)),
		ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
	}
	jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	token, err := jwtToken.SignedString([]byte("secret"))
	if err != nil {
		return c.SendStatus(fiber.StatusInternalServerError)
	}
        cookie := fiber.Cookie{
            Name: "jwt",
            Value: token,
            Expires: time.Now().Add(24 * time.Hour),
            HTTPOnly: true,
        }
        c.Cookie(&cookie)
	return c.JSON(fiber.Map{
		"jwt": token,
	})
}

func User(c *fiber.Ctx) error {
	cookie := c.Cookies("jwt")
	token, err := jwt.ParseWithClaims(cookie, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte("secret"), nil
	})

	if err != nil || !token.Valid {
		c.Status(fiber.StatusUnauthorized)
		return c.JSON(fiber.Map{
			"message": "unauthenticated",
		})
	}

	return c.JSON(token)
}

Faça o login através do Postman no endopoint abaixo: http://localhost:3000/api/login

Postman, Login Post Request

Postman, Login Post Request

Crie uma request para o novo endpoint: http://localhost:3000/api/user

Get User Request

Get User Request

Veja que o cookie do usuário foi retornado.

fiber-project/controllers/authController.go

package controllers

import (
	"fiber-project/database"
	"fiber-project/models"

	"github.com/gofiber/fiber/v2"
	"golang.org/x/crypto/bcrypt"
        "github.com/golang-jwt/jwt/v4"
        "strconv"
        "time"
)
type Claims interface {
        jwt.StandardClaims
}
func Register(c *fiber.Ctx) error {
	var data map[string]string

	if err := c.BodyParser(&data); err != nil {
		return err
	}
	if data["password"] != data["confirm_password"] {
		c.Status(400)
		return c.JSON(fiber.Map{
			"message": "Passwords do not match!",
		})
	}

	password, _ := bcrypt.GenerateFromPassword([]byte(data["password"]), 14)

	user := models.User{
		FirstName: data["first_name"],
		LastName:  data["last_name"],
		Email:     data["email"],
		Password:  password,
	}

	database.DB.Create(&user)
	return c.JSON(user)
}

func Login(c *fiber.Ctx) error {
	//get the request parameter
	var data map[string]string

	if err := c.BodyParser(&data); err != nil {
		return err
	}

	var user models.User
	//get user by email
	database.DB.Where("email = ?", data["email"]).First(&user)

        //user not found
	if user.Id == 0 {
		c.Status(404)
		return c.JSON(fiber.Map{
			"message": "User not found!",
		})
	}
        //incorrect password
        if err := bcrypt.CompareHashAndPassword(user.Password, []byte(data["password"])); err != nil {
		c.Status(400)
		return c.JSON(fiber.Map{
			"message": "Incorrect password!",
		})
	}
        claims := jwt.RegisteredClaims{
		Issuer:        strconv.Itoa(int(user.Id)),
		ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
	}
	jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	token, err := jwtToken.SignedString([]byte("secret"))
	if err != nil {
		return c.SendStatus(fiber.StatusInternalServerError)
	}
        cookie := fiber.Cookie{
            Name: "jwt",
            Value: token,
            Expires: time.Now().Add(24 * time.Hour),
            HTTPOnly: true,
        }
        c.Cookie(&cookie)
	return c.JSON(fiber.Map{
		"jwt": token,
	})
}

func User(c *fiber.Ctx) error {
	cookie := c.Cookies("jwt")
	token, err := jwt.ParseWithClaims(cookie, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte("secret"), nil
	})

	if err != nil || !token.Valid {
		c.Status(fiber.StatusUnauthorized)
		return c.JSON(fiber.Map{
			"message": "unauthenticated",
		})
	}
        claims := token.Claims.(*Claims)
	id := claims.Issuer
	return c.JSON(id)
}

Agora vejo o id retornado.

Retorno do id do usuário

Retorno do id do usuário

Vamos retornar o usuário

fiber-project/controllers/authController.go

package controllers

import (
	"fiber-project/database"
	"fiber-project/models"

	"github.com/gofiber/fiber/v2"
	"golang.org/x/crypto/bcrypt"
        "github.com/golang-jwt/jwt/v4"
        "strconv"
        "time"
)
type Claims interface {
        jwt.StandardClaims
}
func Register(c *fiber.Ctx) error {
	var data map[string]string

	if err := c.BodyParser(&data); err != nil {
		return err
	}
	if data["password"] != data["confirm_password"] {
		c.Status(400)
		return c.JSON(fiber.Map{
			"message": "Passwords do not match!",
		})
	}

	password, _ := bcrypt.GenerateFromPassword([]byte(data["password"]), 14)

	user := models.User{
		FirstName: data["first_name"],
		LastName:  data["last_name"],
		Email:     data["email"],
		Password:  password,
	}

	database.DB.Create(&user)
	return c.JSON(user)
}

func Login(c *fiber.Ctx) error {
	//get the request parameter
	var data map[string]string

	if err := c.BodyParser(&data); err != nil {
		return err
	}

	var user models.User
	//get user by email
	database.DB.Where("email = ?", data["email"]).First(&user)

        //user not found
	if user.Id == 0 {
		c.Status(404)
		return c.JSON(fiber.Map{
			"message": "User not found!",
		})
	}
        //incorrect password
        if err := bcrypt.CompareHashAndPassword(user.Password, []byte(data["password"])); err != nil {
		c.Status(400)
		return c.JSON(fiber.Map{
			"message": "Incorrect password!",
		})
	}
        claims := jwt.RegisteredClaims{
		Issuer:        strconv.Itoa(int(user.Id)),
		ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
	}
	jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	token, err := jwtToken.SignedString([]byte("secret"))
	if err != nil {
		return c.SendStatus(fiber.StatusInternalServerError)
	}
        cookie := fiber.Cookie{
            Name: "jwt",
            Value: token,
            Expires: time.Now().Add(24 * time.Hour),
            HTTPOnly: true,
        }
        c.Cookie(&cookie)
	return c.JSON(fiber.Map{
		"jwt": token,
	})
}

func User(c *fiber.Ctx) error {
	cookie := c.Cookies("jwt")
	token, err := jwt.ParseWithClaims(cookie, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte("secret"), nil
	})

	if err != nil || !token.Valid {
		c.Status(fiber.StatusUnauthorized)
		return c.JSON(fiber.Map{
			"message": "unauthenticated",
		})
	}
        claims := token.Claims.(*Claims)
	id := claims.Issuer
	var user models.User
	database.DB.Where("id = ?", id).First(&user)
	return c.JSON(user)
}

Agora o usuário é retornado.

Usuário Retornado

Usuário Retornado

É isso!

A gente se vê na próxima. 😉

Até lá!

\o/

Código da aula: Github

Voltar para página principal do blog

Todas as aulas desse curso

Aula 12                                               Aula 14

Redes Sociais:

facebook        

Novamente deixo meus link de afiliados:

Hostinger

Digital Ocean

One.com

Obrigado, até a próxima e bons estudos. 😉

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>