Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
"filename": "core/auth/apis.go",
"hashed_secret": "394e3412459f79523e12e1fa95a4cf141ccff122",
"is_verified": false,
"line_number": 2249
"line_number": 2269
}
],
"core/auth/auth.go": [
Expand Down Expand Up @@ -347,5 +347,5 @@
}
]
},
"generated_at": "2025-11-05T17:05:03Z"
"generated_at": "2025-11-12T08:42:48Z"
}
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
### Changed
- Improve refresh token grace period logging [#814](https://github.com/rokwire/core-building-block/issues/814)

## [1.60.0] - 2025-11-110
### Changed
- Implement refresh token reuse detection grace period [#811](https://github.com/rokwire/core-building-block/issues/811)
Expand Down
38 changes: 29 additions & 9 deletions core/auth/apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,22 +309,42 @@ func (a *Auth) Refresh(refreshToken string, apiKey string, clientVersion *string
}
if refreshToken != currentToken {
//allow refresh if the previous token is being used and we are in the grace period
previousToken, err := loginSession.PreviousRefreshToken()
gracePeriodRefresh := (err == nil) && (refreshToken == previousToken) && loginSession.IsInRefreshGracePeriod(nil)
if !gracePeriodRefresh {
l.Infof("previous refresh token being used, so delete login session and return null - %s", refreshToken)
if err != nil {
l.Errorf("error getting previous refresh token - %v", err)
}

//remove the session
masked := utils.MaskString(refreshToken, 5)
l.Infof("old refresh token being used - %s", masked)

//small helper to avoid repeating cleanup
cleanup := func() (*model.LoginSession, error) {
err = a.deleteLoginSession(nil, *loginSession, l)
if err != nil {
return nil, errors.WrapErrorAction(logutils.ActionDelete, model.TypeLoginSession, logutils.StringArgs("previous refresh token"), err)
}

return nil, nil
}

//get the previous token as it is what we allow during grace period
previousToken, err := loginSession.PreviousRefreshToken()
if err != nil {
//we cannot get the previous token, so we cannot allow refresh
l.Infof("error getting previous refresh token - %v", err)
return cleanup()
}

//now check if the provided token is the previous token
if refreshToken != previousToken {
//not the previous token, so we cannot allow refresh
l.Infof("not the previous token, so we cannot allow refresh - %s", masked)
return cleanup()
}

//now check if we are in the grace period
if !loginSession.IsInRefreshGracePeriod(nil) {
l.Infof("not in grace period, so we cannot allow refresh - %s", masked)
return cleanup()
}

//the provided token is the previous token and we are in grace period, so allow refresh
l.Info("the provided token is the previous token and we are in grace period, so allow refresh")
}

//TODO: Ideally we would not make many database calls before validating the API key. Currently needed to get app ID
Expand Down