Trying to figure out two factor authentication

so today i tried to implement two factor authentication.

in my non 2fa flow i send a TokenEvent in a login auth request which works fine.

what i thought to do for 2fa is add a flag to the connection token after login to indicate 2fa is required which redirects to a 2fa page,

what I’d like to do is trigger a 2nd TokenEvent with an additional flag that indicates 2fa is validated after the right code has been entered, this will allow me to have access handles which can check if 2fa was required and validated.

the problem is that the 2nd TokenEvent does not seem to update the token connection information.

I’m pretty sure the problem is the way I’m adding the flag (dereferencing issues and all) but i thought I’d check to see if there are any known issues with triggering multiple TokenEvents on the same connection in order to modify the token attributes

//TotpCode is the code used to validate the user
type TotpCode struct {
	Code string `json:"code"`
}

//validates a totp  
func (th *TotpHandler) validateProviderTotp(r res.AuthRequest) {
	var params TotpCode
	r.ParseParams(&params )

	var token Token
	r.ParseToken(&token)

	totp, err := th.validateTotp(token, params .Code)
	if err != nil {
		log.Error(err)
		r.InvalidParams(fmt.Sprintf("There was a problem: %s", err))
		return
	}

	if totp.valid == false {
		r.TokenEvent(nil)
		r.InvalidParams("Invalid Token!")
		return
	}

	token.Totp = true
	r.TokenEvent(token)//<---- this is where it seems to be failing, it sets here just fine, but other services when they get the token, totp is set to false 

	r.OK(map[string]string{
		"redirect": "/home/index.html",
	})

Well I think I’ve narrowed the problem down to how I refresh my connection, what seems to be happening is on a new page load when I pass the token in to refresh the connection, the relogin AuthHandler doesn’t have the token information until it re-establishes the connection, but at this point it seems the information from the previous connection is lost which poses an interesting problem. How do I pass information along information in the token if its lost on each page load

problem solved, I had to refactor my jwt service so the claims can be dynamically updated in order to pass around the information… so on login, if 2fa is enabled the token gets a claim “totp-validated = false” which is important that it happens during the login event so that it invalidates all previous sessions.

Doing this triggers the proper redirects and access denials, then in the totp service when the code is validated it updates the claim to “totp-validated = true”

Great to hear :slight_smile: . Sorry for the slow reply over the weekend.

Not sure you need these answers anymore, but thought I’d still type them down:

  • Updating a token (or setting a new token) on an existing connection is allowed
  • Tokens set with the token event does not persist across connections. Resgate only knows connections, not sessions.
  • Security wise, the login/2fa flow is preferably done in a separate flow which leads to a http-only jtw bearer token (or similar). That jwt is then used for authentication against the Resgate service.

The difference between old REST style and Resgate is not so much about login. The login flow that results in a JWT bearer token may be the same. What is different comes afterwards. With old style REST, a request may look like this:

  1. Client sends request
  2. Web service decodes and validates the header jwt token
  3. Web service verifies access to the resources, using the validated token
  4. Web service fetches the data.
  5. Client receives the response

With Resgate it is the same, but split into separate requests: 2 is done in the auth request, 3 is done in the access request, and 4 is done in the get request.

The splitting allows different services to handle the different requests. Also, 2 only has to be done once per connection, instead of once per request. And finally, 4 doesn’t have to be done at all, in case the resource is cached.

/Samuel