Skip to content

Commit 35aeaf1

Browse files
J0joel
and
joel
authored
fix: impose expiry on auth code instead of magic link (#1440)
## What kind of change does this PR introduce? Currently, we check for flow state expiry rather than auth code expiry. The auth code is created at the point when `/magiclink` is called and expiry starts from then. However, the auth code should probably start expiring when the link is verified and the auth code is issued. We can eventually extend this to other magic link like flows if need. Note that the Flow State expiry is capped at 24 hours, as that is when the regular cleanup takes place. Considered adding a hard restriction on the maximum validity of `GOTRUE_MAILER_OTP_EXP` but there are a handful of projects which have it >86400. The handful of existing projects (number on internal channel) with a OTP expiry of longer than 24 hours will continue to have the expiry capped at 24 hours when using PKCE. This should be the same as the current behaviour since we aren't changing the cleanup duration. --------- Co-authored-by: joel <[email protected]>
1 parent 79725de commit 35aeaf1

File tree

5 files changed

+24
-1
lines changed

5 files changed

+24
-1
lines changed

internal/api/external.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ func (a *API) internalExternalProviderCallback(w http.ResponseWriter, r *http.Re
223223
flowState.ProviderAccessToken = providerAccessToken
224224
flowState.ProviderRefreshToken = providerRefreshToken
225225
flowState.UserID = &(user.ID)
226+
issueTime := time.Now()
227+
flowState.AuthCodeIssuedAt = &issueTime
228+
226229
terr = tx.Update(flowState)
227230
} else {
228231
token, terr = a.issueRefreshToken(ctx, tx, user, models.OAuth, grantParams)

internal/api/pkce.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ func issueAuthCode(tx *storage.Connection, user *models.User, authenticationMeth
4545
} else if err != nil {
4646
return "", err
4747
}
48+
if err := flowState.RecordAuthCodeIssuedAtTime(tx); err != nil {
49+
return "", err
50+
}
51+
4852
return flowState.AuthCode, nil
4953
}
5054

internal/api/verify.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,9 @@ func (a *API) verifyGet(w http.ResponseWriter, r *http.Request, params *VerifyPa
181181
if terr := tx.Reload(user); err != nil {
182182
return terr
183183
}
184+
184185
if isImplicitFlow(flowType) {
185186
token, terr = a.issueRefreshToken(ctx, tx, user, models.OTP, grantParams)
186-
187187
if terr != nil {
188188
return terr
189189
}

internal/models/flow_state.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type FlowState struct {
2828
ProviderType string `json:"provider_type" db:"provider_type"`
2929
ProviderAccessToken string `json:"provider_access_token" db:"provider_access_token"`
3030
ProviderRefreshToken string `json:"provider_refresh_token" db:"provider_refresh_token"`
31+
AuthCodeIssuedAt *time.Time `json:"auth_code_issued_at" db:"auth_code_issued_at"`
3132
CreatedAt time.Time `json:"created_at" db:"created_at"`
3233
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
3334
}
@@ -152,5 +153,17 @@ func (f *FlowState) VerifyPKCE(codeVerifier string) error {
152153
}
153154

154155
func (f *FlowState) IsExpired(expiryDuration time.Duration) bool {
156+
if f.AuthCodeIssuedAt != nil && f.AuthenticationMethod == MagicLink.String() {
157+
return time.Now().After(f.AuthCodeIssuedAt.Add(expiryDuration))
158+
}
155159
return time.Now().After(f.CreatedAt.Add(expiryDuration))
156160
}
161+
162+
func (f *FlowState) RecordAuthCodeIssuedAtTime(tx *storage.Connection) error {
163+
issueTime := time.Now()
164+
f.AuthCodeIssuedAt = &issueTime
165+
if err := tx.Update(f); err != nil {
166+
return err
167+
}
168+
return nil
169+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
do $$ begin
2+
alter table {{ index .Options "Namespace" }}.flow_state add column if not exists auth_code_issued_at timestamptz null;
3+
end $$

0 commit comments

Comments
 (0)