Skip to content

Commit 4e8275f

Browse files
hffadymak
andauthored
fix: mfa verify now works with refresh token algorithm v2 (#2246)
Verification didn't work as MFA verify issues a new refresh token. This was not moved to support v2 refresh tokens. --------- Co-authored-by: issuedat <165281975+issuedat@users.noreply.github.com>
1 parent 74f1529 commit 4e8275f

1 file changed

Lines changed: 33 additions & 6 deletions

File tree

internal/api/token.go

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/gofrs/uuid"
88

99
"github.com/supabase/auth/internal/api/apierrors"
10+
"github.com/supabase/auth/internal/crypto"
1011
"github.com/supabase/auth/internal/hooks/v0hooks"
1112
"github.com/supabase/auth/internal/metering"
1213
"github.com/supabase/auth/internal/models"
@@ -303,7 +304,8 @@ func (a *API) updateMFASessionAndClaims(r *http.Request, tx *storage.Connection,
303304
config := a.config
304305
var tokenString string
305306
var expiresAt int64
306-
var refreshToken *models.RefreshToken
307+
var issuedRefreshToken string
308+
307309
currentClaims := getClaims(ctx)
308310
sessionId, err := uuid.FromString(currentClaims.SessionId)
309311
if err != nil {
@@ -325,11 +327,36 @@ func (a *API) updateMFASessionAndClaims(r *http.Request, tx *storage.Connection,
325327
if err := tx.Load(user, "Identities"); err != nil {
326328
return err
327329
}
328-
// Swap to ensure current token is the latest one
329-
refreshToken, terr = models.GrantRefreshTokenSwap(config.AuditLog, r, tx, user, currentToken)
330-
if terr != nil {
331-
return terr
330+
331+
// issue a new refresh token on successful verification
332+
if session.RefreshTokenHmacKey != nil && session.RefreshTokenCounter != nil {
333+
signingKey, _, terr := session.GetRefreshTokenHmacKey(config.Security.DBEncryption)
334+
if terr != nil {
335+
return apierrors.NewInternalServerError("Failed to get session's refresh token key").WithInternalError(terr)
336+
}
337+
338+
counter := *session.RefreshTokenCounter + 1
339+
session.RefreshTokenCounter = &counter
340+
341+
issuedRefreshToken = (&crypto.RefreshToken{
342+
Version: 0,
343+
SessionID: session.ID,
344+
Counter: *session.RefreshTokenCounter,
345+
}).Encode(signingKey)
346+
347+
if terr := session.UpdateOnlyRefreshToken(tx); terr != nil {
348+
return apierrors.NewInternalServerError("Failed to update session").WithInternalError(terr)
349+
}
350+
} else {
351+
// Legacy RTs: swap to ensure current token is the latest one
352+
refreshToken, terr := models.GrantRefreshTokenSwap(config.AuditLog, r, tx, user, currentToken)
353+
if terr != nil {
354+
return terr
355+
}
356+
357+
issuedRefreshToken = refreshToken.Token
332358
}
359+
333360
aal, _, terr := session.CalculateAALAndAMR(user)
334361
if terr != nil {
335362
return terr
@@ -362,7 +389,7 @@ func (a *API) updateMFASessionAndClaims(r *http.Request, tx *storage.Connection,
362389
TokenType: "bearer",
363390
ExpiresIn: config.JWT.Exp,
364391
ExpiresAt: expiresAt,
365-
RefreshToken: refreshToken.Token,
392+
RefreshToken: issuedRefreshToken,
366393
User: user,
367394
}, nil
368395
}

0 commit comments

Comments
 (0)