Tuesday, January 21, 2025
HomeGolangHow do I Implement Bearer Tokens with Gin - Getting Assist

How do I Implement Bearer Tokens with Gin – Getting Assist


so to offer higher context to my downside, my crudapi is about simulating a bikeshop.
I create an account by passing an account obj. to POST “localhost:8080/customers”, which if profitable provides the information to the usernames, usercontacts and passwords desk respectively. usernames maintain the person’s username, usercontacts shops their delicate knowledge(addres, fname, lname) and passwords saved their passwords as an encrypted hash. When an account is created the response {user_id: #, msg: registered } is shipped again.

My present login route is a Publish ‘localhost:8080/person/login’.
It hashes person offered pswd and checks its in opposition to
the at the moment hashed pswd saved within the database.
Nonetheless, I need to return a token after authenticating.
Let me know if there’s something lacking.

JSON OBJECTS

Account
{
  "username": string,
  "fname": string,
  "lname": string,
  "tackle": string,
  "password": string
}
usernames
{ 
  "id": int,
  "user_id": int,
  "username": string,
}
usercontacts
{ 
  "id": int,
  "user_id": int,
  "fname": string,
  "lname": string,
  "tackle": string
}
passwords
{ 
  "id": int,
  "user_id": int,
  "password": string,
}
Login-Creds
{
  "username": string,
  "pswd": []byte
}

ROUTES

My Implmenetation

  • Routes > predominant.go
  • Account information & Authentication > accts.go
  • Subject Error dealing with > fields.go

MAIN FILE

Create Account Route

func createAcct(r *gin.Engine) *gin.Engine {
	r.POST("/customers/", func(c *gin.Context) {
		var acct accts.Account
		var acctErr fields.GrammarError
		var acctStatus *accts.Registered
		err := c.ShouldBind(&acct)
		if err != nil {
			acctErr.AddMsg(fields.BadRequest,
				"Binding Error: didn't bind fields to account object, mismatched data-types")
			c.JSON(fields.ErrorCode, acctErr)
			return
		}

		// validate account information
		acctStatus, acctErr = accts.AddAccount(&acct)

		// ship response again
		errMsgSize := len(acctErr.ErrMsgs)
		swap {
		case errMsgSize > 0:
			c.JSON(fields.ErrorCode, acctErr)
		default:
			c.JSON(statusOK, *acctStatus)
		}

		//log.Println("Account: ", acct)
	})
	return r
}

Login Route

func logIn(r *gin.Engine) *gin.Engine {
	r.POST("/person/login", func(c *gin.Context) {
		var loginErr fields.GrammarError
		var rqstData respBodyData
		var userCred accts.LoginCred

		loginErr = rqstData.FieldErr
		err := c.ShouldBind(&userCred)
		if err != nil {
			loginErr.AddMsg(fields.BadRequest,
				"Binding Error: didn't bind fields to account object, mismatched data-types")
			c.JSON(fields.ErrorCode, loginErr)
			return
		}

		// validate account information
		authStatus, loginErr := accts.LogIntoAcct(userCred)
		if err != nil {
			loginErr.AddMsg(fields.BadRequest,
				"Binding Error: didn't bind fields to account object, mismatched data-types")
			c.JSON(fields.ErrorCode, loginErr)
			return
		}

		// ship response again
		errMsgSize := len(loginErr.ErrMsgs)
		swap {
		case errMsgSize > 0:
			c.JSON(fields.ErrorCode, loginErr)
		default:
			c.JSON(statusOK, authStatus)
		}
	})
	return r
}

ACCTS FILE

Add Account

// provides the account information to the appropiate tables w/ the database
func AddAccount(acct *Account) (*Registered, fields.GrammarError) {
	acctErr := &fields.GrammarError{}
	validateAccount(acct, acctErr)

	if acctErr.ErrMsgs != nil {
		return nil, *acctErr
	}

	// if no errors add information to appropiate tables
	addUsername(acct, acctErr)
	if acctErr.ErrMsgs != nil {
		return nil, *acctErr
	}

	addUserContact(acct, acctErr)
	if acctErr.ErrMsgs != nil {
		return nil, *acctErr
	}

	// add passwords to desk, do not if err existf
	addPassword(acct, acctErr)
	if acctErr.ErrMsgs != nil {
		// fmt.Printf("Errors in AddAccount Func, %vn", acctErr.ErrMsgs)
		return nil, *acctErr
	}

	return &Registered{acct.ID, "registered"}, *acctErr
}

Login

// matches the consumer's username and pswd in opposition to the database
// if there is a match the person is logged in, in any other case
// there's a problem with username or password
func LogIntoAcct(userCred LoginCred) (*LoginStatus, fields.GrammarError) {
	// get the person struct verify if it exists
	usrs, fieldErr := readUserByUsername(userCred.UserName)
	if fieldErr.ErrMsgs != nil {
		return nil, fieldErr
	}

	// get the saved pswd hash
	usr := usrs[0]
	pswds, fieldErr := ReadHashByID(usr.ID)
	if fieldErr.ErrMsgs != nil {
		return nil, fieldErr
	}

	// hash the given pswd and evaluate it to whats
	// saved within the databse
	hashedPswd := pswds[0].Password
	err := bcrypt.CompareHashAndPassword(hashedPswd, []byte(userCred.Password))

	if err != nil {
		// log.Printf("The Password Hash Comparability Failed: %vn", err.Error())
		fieldErr.AddMsg(BadRequest, "Error: password is wrong")
		return nil, fieldErr
	}

	return &LoginStatus{usr.ID, "LoggedIn"}, fieldErr
}

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments