Newly created access tokens are now lowercase only

pull/774/head
binwiederhier 2023-06-14 11:20:29 -04:00
parent ae3e8a0094
commit e96e35b40b
4 changed files with 27 additions and 3 deletions

View File

@ -1227,6 +1227,7 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
* Support encoding any header as RFC 2047 ([#737](https://github.com/binwiederhier/ntfy/issues/737), thanks to [@cfouche3005](https://github.com/cfouche3005) for reporting) * Support encoding any header as RFC 2047 ([#737](https://github.com/binwiederhier/ntfy/issues/737), thanks to [@cfouche3005](https://github.com/cfouche3005) for reporting)
* Do not forward poll requests for UnifiedPush messages (no ticket, thanks to NoName for reporting) * Do not forward poll requests for UnifiedPush messages (no ticket, thanks to NoName for reporting)
* Fix `ntfy pub %` segfaulting ([#760](https://github.com/binwiederhier/ntfy/issues/760), thanks to [@clesmian](https://github.com/clesmian) for reporting) * Fix `ntfy pub %` segfaulting ([#760](https://github.com/binwiederhier/ntfy/issues/760), thanks to [@clesmian](https://github.com/clesmian) for reporting)
* Newly created access tokens are now lowercase only to fully support `<topic>+<token>@<domain>` email syntax ([#773](https://github.com/binwiederhier/ntfy/issues/773), thanks to gingervitiz for reporting)
**Maintenance:** **Maintenance:**

View File

@ -508,7 +508,7 @@ func (a *Manager) AuthenticateToken(token string) (*User, error) {
// after a fixed duration unless ChangeToken is called. This function also prunes tokens for the // after a fixed duration unless ChangeToken is called. This function also prunes tokens for the
// given user, if there are too many of them. // given user, if there are too many of them.
func (a *Manager) CreateToken(userID, label string, expires time.Time, origin netip.Addr) (*Token, error) { func (a *Manager) CreateToken(userID, label string, expires time.Time, origin netip.Addr) (*Token, error) {
token := util.RandomStringPrefix(tokenPrefix, tokenLength) token := util.RandomLowerStringPrefix(tokenPrefix, tokenLength) // Lowercase only to support "<topic>+<token>@<domain>" email addresses
tx, err := a.db.Begin() tx, err := a.db.Begin()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -183,6 +183,19 @@ func TestManager_MarkUserRemoved_RemoveDeletedUsers(t *testing.T) {
require.Equal(t, ErrUserNotFound, err) require.Equal(t, ErrUserNotFound, err)
} }
func TestManager_CreateToken_Only_Lower(t *testing.T) {
a := newTestManager(t, PermissionDenyAll)
// Create user, add reservations and token
require.Nil(t, a.AddUser("user", "pass", RoleAdmin))
u, err := a.User("user")
require.Nil(t, err)
token, err := a.CreateToken(u.ID, "", time.Now().Add(time.Hour), netip.IPv4Unspecified())
require.Nil(t, err)
require.Equal(t, token.Value, strings.ToLower(token.Value))
}
func TestManager_UserManagement(t *testing.T) { func TestManager_UserManagement(t *testing.T) {
a := newTestManager(t, PermissionDenyAll) a := newTestManager(t, PermissionDenyAll)
require.Nil(t, a.AddUser("phil", "phil", RoleAdmin)) require.Nil(t, a.AddUser("phil", "phil", RoleAdmin))

View File

@ -23,7 +23,8 @@ import (
) )
const ( const (
randomStringCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" randomStringCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
randomStringLowerCaseCharset = "abcdefghijklmnopqrstuvwxyz0123456789"
) )
var ( var (
@ -112,11 +113,20 @@ func RandomString(length int) string {
// RandomStringPrefix returns a random string with a given length, with a prefix // RandomStringPrefix returns a random string with a given length, with a prefix
func RandomStringPrefix(prefix string, length int) string { func RandomStringPrefix(prefix string, length int) string {
return randomStringPrefixWithCharset(prefix, length, randomStringCharset)
}
// RandomLowerStringPrefix returns a random lowercase-only string with a given length, with a prefix
func RandomLowerStringPrefix(prefix string, length int) string {
return randomStringPrefixWithCharset(prefix, length, randomStringLowerCaseCharset)
}
func randomStringPrefixWithCharset(prefix string, length int, charset string) string {
randomMutex.Lock() // Who would have thought that random.Intn() is not thread-safe?! randomMutex.Lock() // Who would have thought that random.Intn() is not thread-safe?!
defer randomMutex.Unlock() defer randomMutex.Unlock()
b := make([]byte, length-len(prefix)) b := make([]byte, length-len(prefix))
for i := range b { for i := range b {
b[i] = randomStringCharset[random.Intn(len(randomStringCharset))] b[i] = charset[random.Intn(len(charset))]
} }
return prefix + string(b) return prefix + string(b)
} }