diff --git a/build/docker/config/dendrite.yaml b/build/docker/config/dendrite.yaml index 94dcf4558..726e95be9 100644 --- a/build/docker/config/dendrite.yaml +++ b/build/docker/config/dendrite.yaml @@ -114,10 +114,10 @@ global: # Maximum number of entries to hold in the DNS cache, and # for how long those items should be considered valid in seconds. cache_size: 256 - cache_lifetime: 300 + cache_lifetime: "5m" # 5minutes; see https://pkg.go.dev/time@master#ParseDuration for more # Configuration for the Appservice API. -app_service_api: +appservice_api: internal_api: listen: http://0.0.0.0:7777 connect: http://appservice_api:7777 @@ -311,17 +311,18 @@ user_api: max_open_conns: 10 max_idle_conns: 2 conn_max_lifetime: -1 - -# Configuration for the Push Server API. -push_server: - internal_api: - listen: http://localhost:7782 - connect: http://localhost:7782 - database: - connection_string: postgresql://dendrite:itsasecret@postgres/dendrite_pushserver?sslmode=disable - max_open_conns: 10 - max_idle_conns: 2 - conn_max_lifetime: -1 + # The cost when hashing passwords on registration/login. Default: 10. Min: 4, Max: 31 + # See https://pkg.go.dev/golang.org/x/crypto/bcrypt for more information. + # Setting this lower makes registration/login consume less CPU resources at the cost of security + # should the database be compromised. Setting this higher makes registration/login consume more + # CPU resources but makes it harder to brute force password hashes. + # This value can be low if performing tests or on embedded Dendrite instances (e.g WASM builds) + # bcrypt_cost: 10 + # The length of time that a token issued for a relying party from + # /_matrix/client/r0/user/{userId}/openid/request_token endpoint + # is considered to be valid. + # The default lifetime is 60 minutes. + # openid_token_lifetime: "1h" # One hour; see https://pkg.go.dev/time@master#ParseDuration for more # Configuration for Opentracing. # See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on diff --git a/clientapi/routing/openid.go b/clientapi/routing/openid.go index 13656e288..244d14483 100644 --- a/clientapi/routing/openid.go +++ b/clientapi/routing/openid.go @@ -16,6 +16,7 @@ package routing import ( "net/http" + "time" "github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/setup/config" @@ -64,7 +65,7 @@ func CreateOpenIDToken( AccessToken: response.Token.Token, TokenType: "Bearer", MatrixServerName: string(cfg.Matrix.ServerName), - ExpiresIn: response.Token.ExpiresAtMS / 1000, // convert ms to s + ExpiresIn: int64(time.Until(response.Token.ExpiresAt.Time()).Seconds()), }, } } diff --git a/clientapi/routing/voip.go b/clientapi/routing/voip.go index c7ddaabcf..db1888a0f 100644 --- a/clientapi/routing/voip.go +++ b/clientapi/routing/voip.go @@ -35,23 +35,20 @@ func RequestTurnServer(req *http.Request, device *api.Device, cfg *config.Client turnConfig := cfg.TURN // TODO Guest Support - if len(turnConfig.URIs) == 0 || turnConfig.UserLifetime == "" { + if len(turnConfig.URIs) == 0 || turnConfig.UserLifetime.Seconds() == 0 { return util.JSONResponse{ Code: http.StatusOK, JSON: struct{}{}, } } - // Duration checked at startup, err not possible - duration, _ := time.ParseDuration(turnConfig.UserLifetime) - resp := gomatrix.RespTurnServer{ URIs: turnConfig.URIs, - TTL: int(duration.Seconds()), + TTL: int(turnConfig.UserLifetime.Seconds()), } if turnConfig.SharedSecret != "" { - expiry := time.Now().Add(duration).Unix() + expiry := time.Now().Add(turnConfig.UserLifetime).Unix() resp.Username = fmt.Sprintf("%d:%s", expiry, device.UserID) mac := hmac.New(sha1.New, []byte(turnConfig.SharedSecret)) _, err := mac.Write([]byte(resp.Username)) diff --git a/dendrite-config-monolith.yaml b/dendrite-config-monolith.yaml index 939269394..d62e255ee 100644 --- a/dendrite-config-monolith.yaml +++ b/dendrite-config-monolith.yaml @@ -140,7 +140,7 @@ global: cache_lifetime: "5m" # 5minutes; see https://pkg.go.dev/time@master#ParseDuration for more # Configuration for the Appservice API. -app_service_api: +appservice_api: # Disable the validation of TLS certificates of appservices. This is # not recommended in production since it may allow appservice traffic # to be sent to an unverified endpoint. @@ -174,7 +174,7 @@ client_api: # TURN server information that this homeserver should send to clients. turn: - turn_user_lifetime: "" + turn_user_lifetime: "24h" # 24 hours; see https://pkg.go.dev/time@master#ParseDuration for more turn_uris: [] turn_shared_secret: "" turn_username: "" @@ -268,9 +268,9 @@ user_api: # bcrypt_cost: 10 # The length of time that a token issued for a relying party from # /_matrix/client/r0/user/{userId}/openid/request_token endpoint - # is considered to be valid in milliseconds. - # The default lifetime is 3600000ms (60 minutes). - # openid_token_lifetime_ms: 3600000 + # is considered to be valid. + # The default lifetime is 60 minutes. + # openid_token_lifetime: "1h" # One hour; see https://pkg.go.dev/time@master#ParseDuration for more # Configuration for Opentracing. # See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on diff --git a/dendrite-config.yaml b/dendrite-config.yaml index ad5bd31a2..4871fa919 100644 --- a/dendrite-config.yaml +++ b/dendrite-config.yaml @@ -131,7 +131,7 @@ global: cache_lifetime: "5m" # 5minutes; see https://pkg.go.dev/time@master#ParseDuration for more # Configuration for the Appservice API. -app_service_api: +appservice_api: internal_api: listen: http://localhost:7777 # Only used in polylith deployments connect: http://localhost:7777 # Only used in polylith deployments @@ -180,7 +180,7 @@ client_api: # TURN server information that this homeserver should send to clients. turn: - turn_user_lifetime: "" + turn_user_lifetime: "24h" # 24 hours; see https://pkg.go.dev/time@master#ParseDuration for more turn_uris: [] turn_shared_secret: "" turn_username: "" @@ -342,9 +342,9 @@ user_api: conn_max_lifetime: -1 # The length of time that a token issued for a relying party from # /_matrix/client/r0/user/{userId}/openid/request_token endpoint - # is considered to be valid in milliseconds. - # The default lifetime is 3600000ms (60 minutes). - # openid_token_lifetime_ms: 3600000 + # is considered to be valid. + # The default lifetime is 60 minutes. + # openid_token_lifetime: "1h" # One hour; see https://pkg.go.dev/time@master#ParseDuration for more # Configuration for Opentracing. # See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on diff --git a/federationapi/routing/openid.go b/federationapi/routing/openid.go index 829dbccad..1c8490eb6 100644 --- a/federationapi/routing/openid.go +++ b/federationapi/routing/openid.go @@ -52,8 +52,7 @@ func GetOpenIDUserInfo( var res interface{} = openIDUserInfoResponse{Sub: openIDTokenAttrResponse.Sub} code := http.StatusOK - nowMS := time.Now().UnixNano() / int64(time.Millisecond) - if openIDTokenAttrResponse.Sub == "" || nowMS > openIDTokenAttrResponse.ExpiresAtMS { + if openIDTokenAttrResponse.Sub == "" || time.Now().After(openIDTokenAttrResponse.ExpiresAt.Time()) { code = http.StatusUnauthorized res = jsonerror.UnknownToken("Access Token unknown or expired") } diff --git a/setup/base/base.go b/setup/base/base.go index 4b771aa36..598149ad6 100644 --- a/setup/base/base.go +++ b/setup/base/base.go @@ -280,7 +280,7 @@ func (b *BaseDendrite) CreateAccountsDB() userdb.Database { &b.Cfg.UserAPI.AccountDatabase, b.Cfg.Global.ServerName, b.Cfg.UserAPI.BCryptCost, - b.Cfg.UserAPI.OpenIDTokenLifetimeMS, + b.Cfg.UserAPI.OpenIDTokenLifetime, userapi.DefaultLoginTokenLifetime, b.Cfg.Global.ServerNotices.LocalPart, ) diff --git a/setup/config/config.go b/setup/config/config.go index e03518e24..e236de575 100644 --- a/setup/config/config.go +++ b/setup/config/config.go @@ -29,7 +29,7 @@ import ( "github.com/matrix-org/gomatrixserverlib" "github.com/sirupsen/logrus" "golang.org/x/crypto/ed25519" - yaml "gopkg.in/yaml.v2" + "gopkg.in/yaml.v2" jaegerconfig "github.com/uber/jaeger-client-go/config" jaegermetrics "github.com/uber/jaeger-lib/metrics" @@ -54,7 +54,7 @@ type Dendrite struct { Version int `yaml:"version"` Global Global `yaml:"global"` - AppServiceAPI AppServiceAPI `yaml:"app_service_api"` + AppServiceAPI AppServiceAPI `yaml:"appservice_api"` ClientAPI ClientAPI `yaml:"client_api"` FederationAPI FederationAPI `yaml:"federation_api"` KeyServer KeyServer `yaml:"key_server"` diff --git a/setup/config/config_appservice.go b/setup/config/config_appservice.go index 679f160a3..98fb355b3 100644 --- a/setup/config/config_appservice.go +++ b/setup/config/config_appservice.go @@ -50,10 +50,10 @@ func (c *AppServiceAPI) Defaults(generate bool) { } func (c *AppServiceAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { - checkURL(configErrs, "app_service_api.internal_api.listen", string(c.InternalAPI.Listen)) - checkURL(configErrs, "app_service_api.internal_api.bind", string(c.InternalAPI.Connect)) + checkURL(configErrs, "appservice_api.internal_api.listen", string(c.InternalAPI.Listen)) + checkURL(configErrs, "appservice_api.internal_api.bind", string(c.InternalAPI.Connect)) setDatabase(c.Matrix.GlobalDatabaseOptions, &c.Database, "appservice.db") - checkNotEmpty(configErrs, "app_service_api.database.connection_string", string(c.Database.ConnectionString)) + checkNotEmpty(configErrs, "appservice_api.database.connection_string", string(c.Database.ConnectionString)) } // ApplicationServiceNamespace is the namespace that a specific application diff --git a/setup/config/config_clientapi.go b/setup/config/config_clientapi.go index 6104ed8b9..de2e76299 100644 --- a/setup/config/config_clientapi.go +++ b/setup/config/config_clientapi.go @@ -1,7 +1,6 @@ package config import ( - "fmt" "time" ) @@ -64,6 +63,7 @@ func (c *ClientAPI) Defaults(generate bool) { c.RegistrationDisabled = true c.OpenRegistrationWithoutVerificationEnabled = false c.RateLimiting.Defaults() + c.TURN.Defaults() } func (c *ClientAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { @@ -100,7 +100,7 @@ type TURN struct { // Whether or not guests can request TURN credentials // AllowGuests bool `yaml:"turn_allow_guests"` // How long the authorization should last - UserLifetime string `yaml:"turn_user_lifetime"` + UserLifetime time.Duration `yaml:"turn_user_lifetime"` // The list of TURN URIs to pass to clients URIs []string `yaml:"turn_uris"` @@ -115,12 +115,11 @@ type TURN struct { } func (c *TURN) Verify(configErrs *ConfigErrors) { - value := c.UserLifetime - if value != "" { - if _, err := time.ParseDuration(value); err != nil { - configErrs.Add(fmt.Sprintf("invalid duration for config key %q: %s", "client_api.turn.turn_user_lifetime", value)) - } - } + checkPositive(configErrs, "cache_lifetime", int64(c.UserLifetime)) +} + +func (c *TURN) Defaults() { + c.UserLifetime = time.Hour * 24 } type RateLimiting struct { diff --git a/setup/config/config_test.go b/setup/config/config_test.go index cbc57ad18..e1ed76e3f 100644 --- a/setup/config/config_test.go +++ b/setup/config/config_test.go @@ -63,7 +63,7 @@ global: display_name: "Server alerts" avatar: "" room_name: "Server Alerts" -app_service_api: +appservice_api: internal_api: listen: http://localhost:7777 connect: http://localhost:7777 @@ -87,20 +87,11 @@ client_api: recaptcha_bypass_secret: "" recaptcha_siteverify_api: "" turn: - turn_user_lifetime: "" + turn_user_lifetime: "1h" turn_uris: [] turn_shared_secret: "" turn_username: "" turn_password: "" -current_state_server: - internal_api: - listen: http://localhost:7782 - connect: http://localhost:7782 - database: - connection_string: file:currentstate.db - max_open_conns: 100 - max_idle_conns: 2 - conn_max_lifetime: -1 federation_api: internal_api: listen: http://localhost:7772 diff --git a/setup/config/config_userapi.go b/setup/config/config_userapi.go index 20be1297a..3ff3aa23f 100644 --- a/setup/config/config_userapi.go +++ b/setup/config/config_userapi.go @@ -1,6 +1,10 @@ package config -import "golang.org/x/crypto/bcrypt" +import ( + "time" + + "golang.org/x/crypto/bcrypt" +) type UserAPI struct { Matrix *Global `yaml:"-"` @@ -11,7 +15,7 @@ type UserAPI struct { BCryptCost int `yaml:"bcrypt_cost"` // The length of time an OpenID token is condidered valid in milliseconds - OpenIDTokenLifetimeMS int64 `yaml:"openid_token_lifetime_ms"` + OpenIDTokenLifetime time.Duration `yaml:"openid_token_lifetime"` // Disable TLS validation on HTTPS calls to push gatways. NOT RECOMMENDED! PushGatewayDisableTLSValidation bool `yaml:"push_gateway_disable_tls_validation"` @@ -21,7 +25,7 @@ type UserAPI struct { AccountDatabase DatabaseOptions `yaml:"account_database"` } -const DefaultOpenIDTokenLifetimeMS = 3600000 // 60 minutes +var DefaultOpenIDTokenLifetime = time.Hour func (c *UserAPI) Defaults(generate bool) { c.InternalAPI.Listen = "http://localhost:7781" @@ -31,7 +35,7 @@ func (c *UserAPI) Defaults(generate bool) { c.AccountDatabase.ConnectionString = "file:userapi_accounts.db" } c.BCryptCost = bcrypt.DefaultCost - c.OpenIDTokenLifetimeMS = DefaultOpenIDTokenLifetimeMS + c.OpenIDTokenLifetime = DefaultOpenIDTokenLifetime } func (c *UserAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { @@ -39,5 +43,5 @@ func (c *UserAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { checkURL(configErrs, "user_api.internal_api.connect", string(c.InternalAPI.Connect)) setDatabase(c.Matrix.GlobalDatabaseOptions, &c.AccountDatabase, "userapi.db") checkNotEmpty(configErrs, "user_api.account_database.connection_string", string(c.AccountDatabase.ConnectionString)) - checkPositive(configErrs, "user_api.openid_token_lifetime_ms", c.OpenIDTokenLifetimeMS) + checkPositive(configErrs, "user_api.openid_token_lifetime", c.OpenIDTokenLifetime.Milliseconds()) } diff --git a/userapi/api/api.go b/userapi/api/api.go index 6aa6a6842..caad62c7e 100644 --- a/userapi/api/api.go +++ b/userapi/api/api.go @@ -378,8 +378,8 @@ type QueryOpenIDTokenRequest struct { // QueryOpenIDTokenResponse is the response for QueryOpenIDToken type QueryOpenIDTokenResponse struct { - Sub string // The Matrix User ID that generated the token - ExpiresAtMS int64 + Sub string // The Matrix User ID that generated the token + ExpiresAt gomatrixserverlib.Timestamp } // Device represents a client's device (mobile, web, etc) @@ -415,15 +415,15 @@ type Account struct { // OpenIDToken represents an OpenID token type OpenIDToken struct { - Token string - UserID string - ExpiresAtMS int64 + Token string + UserID string + ExpiresAt gomatrixserverlib.Timestamp } // OpenIDTokenInfo represents the attributes associated with an issued OpenID token type OpenIDTokenAttributes struct { - UserID string - ExpiresAtMS int64 + UserID string + ExpiresAt gomatrixserverlib.Timestamp } // UserInfo is for returning information about the user an OpenID token was issued for diff --git a/userapi/internal/api.go b/userapi/internal/api.go index be58e2d8d..647597410 100644 --- a/userapi/internal/api.go +++ b/userapi/internal/api.go @@ -464,9 +464,9 @@ func (a *UserInternalAPI) PerformOpenIDTokenCreation(ctx context.Context, req *a exp, err := a.DB.CreateOpenIDToken(ctx, token, req.UserID) res.Token = api.OpenIDToken{ - Token: token, - UserID: req.UserID, - ExpiresAtMS: exp, + Token: token, + UserID: req.UserID, + ExpiresAt: exp, } return err @@ -480,7 +480,7 @@ func (a *UserInternalAPI) QueryOpenIDToken(ctx context.Context, req *api.QueryOp } res.Sub = openIDTokenAttrs.UserID - res.ExpiresAtMS = openIDTokenAttrs.ExpiresAtMS + res.ExpiresAt = openIDTokenAttrs.ExpiresAt return nil } diff --git a/userapi/storage/interface.go b/userapi/storage/interface.go index a4562cf19..d28f29868 100644 --- a/userapi/storage/interface.go +++ b/userapi/storage/interface.go @@ -22,6 +22,7 @@ import ( "github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/dendrite/userapi/storage/tables" + "github.com/matrix-org/gomatrixserverlib" ) type Profile interface { @@ -97,7 +98,7 @@ type LoginToken interface { } type OpenID interface { - CreateOpenIDToken(ctx context.Context, token, userID string) (exp int64, err error) + CreateOpenIDToken(ctx context.Context, token, userID string) (exp gomatrixserverlib.Timestamp, err error) GetOpenIDTokenAttributes(ctx context.Context, token string) (*api.OpenIDTokenAttributes, error) } diff --git a/userapi/storage/postgres/openid_table.go b/userapi/storage/postgres/openid_table.go index 29c3ddcb4..50a7bdc82 100644 --- a/userapi/storage/postgres/openid_table.go +++ b/userapi/storage/postgres/openid_table.go @@ -55,7 +55,7 @@ func (s *openIDTokenStatements) InsertOpenIDToken( ctx context.Context, txn *sql.Tx, token, localpart string, - expiresAtMS int64, + expiresAtMS gomatrixserverlib.Timestamp, ) (err error) { stmt := sqlutil.TxStmt(txn, s.insertTokenStmt) _, err = stmt.ExecContext(ctx, token, localpart, expiresAtMS) @@ -71,7 +71,7 @@ func (s *openIDTokenStatements) SelectOpenIDTokenAtrributes( var openIDTokenAttrs api.OpenIDTokenAttributes err := s.selectTokenStmt.QueryRowContext(ctx, token).Scan( &openIDTokenAttrs.UserID, - &openIDTokenAttrs.ExpiresAtMS, + &openIDTokenAttrs.ExpiresAt, ) if err != nil { if err != sql.ErrNoRows { diff --git a/userapi/storage/postgres/storage.go b/userapi/storage/postgres/storage.go index b2a517605..91a609467 100644 --- a/userapi/storage/postgres/storage.go +++ b/userapi/storage/postgres/storage.go @@ -30,7 +30,7 @@ import ( ) // NewDatabase creates a new accounts and profiles database -func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName, bcryptCost int, openIDTokenLifetimeMS int64, loginTokenLifetime time.Duration, serverNoticesLocalpart string) (*shared.Database, error) { +func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName, bcryptCost int, openIDTokenLifetimeMS, loginTokenLifetime time.Duration, serverNoticesLocalpart string) (*shared.Database, error) { db, err := sqlutil.Open(dbProperties) if err != nil { return nil, err @@ -94,22 +94,22 @@ func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserver return nil, fmt.Errorf("NewPostgresNotificationTable: %w", err) } return &shared.Database{ - AccountDatas: accountDataTable, - Accounts: accountsTable, - Devices: devicesTable, - KeyBackups: keyBackupTable, - KeyBackupVersions: keyBackupVersionTable, - LoginTokens: loginTokenTable, - OpenIDTokens: openIDTable, - Profiles: profilesTable, - ThreePIDs: threePIDTable, - Pushers: pusherTable, - Notifications: notificationsTable, - ServerName: serverName, - DB: db, - Writer: sqlutil.NewDummyWriter(), - LoginTokenLifetime: loginTokenLifetime, - BcryptCost: bcryptCost, - OpenIDTokenLifetimeMS: openIDTokenLifetimeMS, + AccountDatas: accountDataTable, + Accounts: accountsTable, + Devices: devicesTable, + KeyBackups: keyBackupTable, + KeyBackupVersions: keyBackupVersionTable, + LoginTokens: loginTokenTable, + OpenIDTokens: openIDTable, + Profiles: profilesTable, + ThreePIDs: threePIDTable, + Pushers: pusherTable, + Notifications: notificationsTable, + ServerName: serverName, + DB: db, + Writer: sqlutil.NewDummyWriter(), + LoginTokenLifetime: loginTokenLifetime, + BcryptCost: bcryptCost, + OpenIDTokenLifetime: openIDTokenLifetimeMS, }, nil } diff --git a/userapi/storage/shared/storage.go b/userapi/storage/shared/storage.go index f7212e030..3db9369fa 100644 --- a/userapi/storage/shared/storage.go +++ b/userapi/storage/shared/storage.go @@ -38,23 +38,23 @@ import ( // Database represents an account database type Database struct { - DB *sql.DB - Writer sqlutil.Writer - Accounts tables.AccountsTable - Profiles tables.ProfileTable - AccountDatas tables.AccountDataTable - ThreePIDs tables.ThreePIDTable - OpenIDTokens tables.OpenIDTable - KeyBackups tables.KeyBackupTable - KeyBackupVersions tables.KeyBackupVersionTable - Devices tables.DevicesTable - LoginTokens tables.LoginTokenTable - Notifications tables.NotificationTable - Pushers tables.PusherTable - LoginTokenLifetime time.Duration - ServerName gomatrixserverlib.ServerName - BcryptCost int - OpenIDTokenLifetimeMS int64 + DB *sql.DB + Writer sqlutil.Writer + Accounts tables.AccountsTable + Profiles tables.ProfileTable + AccountDatas tables.AccountDataTable + ThreePIDs tables.ThreePIDTable + OpenIDTokens tables.OpenIDTable + KeyBackups tables.KeyBackupTable + KeyBackupVersions tables.KeyBackupVersionTable + Devices tables.DevicesTable + LoginTokens tables.LoginTokenTable + Notifications tables.NotificationTable + Pushers tables.PusherTable + LoginTokenLifetime time.Duration + ServerName gomatrixserverlib.ServerName + BcryptCost int + OpenIDTokenLifetime time.Duration } const ( @@ -325,12 +325,12 @@ func (d *Database) DeactivateAccount(ctx context.Context, localpart string) (err func (d *Database) CreateOpenIDToken( ctx context.Context, token, localpart string, -) (int64, error) { - expiresAtMS := time.Now().UnixNano()/int64(time.Millisecond) + d.OpenIDTokenLifetimeMS +) (gomatrixserverlib.Timestamp, error) { + expiresAt := gomatrixserverlib.AsTimestamp(time.Now().Add(d.OpenIDTokenLifetime)) err := d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error { - return d.OpenIDTokens.InsertOpenIDToken(ctx, txn, token, localpart, expiresAtMS) + return d.OpenIDTokens.InsertOpenIDToken(ctx, txn, token, localpart, expiresAt) }) - return expiresAtMS, err + return expiresAt, err } // GetOpenIDTokenAttributes gets the attributes of issued an OIDC auth token diff --git a/userapi/storage/sqlite3/openid_table.go b/userapi/storage/sqlite3/openid_table.go index d6090e0da..e7c5662dd 100644 --- a/userapi/storage/sqlite3/openid_table.go +++ b/userapi/storage/sqlite3/openid_table.go @@ -57,7 +57,7 @@ func (s *openIDTokenStatements) InsertOpenIDToken( ctx context.Context, txn *sql.Tx, token, localpart string, - expiresAtMS int64, + expiresAtMS gomatrixserverlib.Timestamp, ) (err error) { stmt := sqlutil.TxStmt(txn, s.insertTokenStmt) _, err = stmt.ExecContext(ctx, token, localpart, expiresAtMS) @@ -73,7 +73,7 @@ func (s *openIDTokenStatements) SelectOpenIDTokenAtrributes( var openIDTokenAttrs api.OpenIDTokenAttributes err := s.selectTokenStmt.QueryRowContext(ctx, token).Scan( &openIDTokenAttrs.UserID, - &openIDTokenAttrs.ExpiresAtMS, + &openIDTokenAttrs.ExpiresAt, ) if err != nil { if err != sql.ErrNoRows { diff --git a/userapi/storage/sqlite3/storage.go b/userapi/storage/sqlite3/storage.go index 03c013f00..c59d853d0 100644 --- a/userapi/storage/sqlite3/storage.go +++ b/userapi/storage/sqlite3/storage.go @@ -31,7 +31,7 @@ import ( ) // NewDatabase creates a new accounts and profiles database -func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName, bcryptCost int, openIDTokenLifetimeMS int64, loginTokenLifetime time.Duration, serverNoticesLocalpart string) (*shared.Database, error) { +func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName, bcryptCost int, openIDTokenLifetimeMS, loginTokenLifetime time.Duration, serverNoticesLocalpart string) (*shared.Database, error) { db, err := sqlutil.Open(dbProperties) if err != nil { return nil, err @@ -95,22 +95,22 @@ func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserver return nil, fmt.Errorf("NewPostgresNotificationTable: %w", err) } return &shared.Database{ - AccountDatas: accountDataTable, - Accounts: accountsTable, - Devices: devicesTable, - KeyBackups: keyBackupTable, - KeyBackupVersions: keyBackupVersionTable, - LoginTokens: loginTokenTable, - OpenIDTokens: openIDTable, - Profiles: profilesTable, - ThreePIDs: threePIDTable, - Pushers: pusherTable, - Notifications: notificationsTable, - ServerName: serverName, - DB: db, - Writer: sqlutil.NewExclusiveWriter(), - LoginTokenLifetime: loginTokenLifetime, - BcryptCost: bcryptCost, - OpenIDTokenLifetimeMS: openIDTokenLifetimeMS, + AccountDatas: accountDataTable, + Accounts: accountsTable, + Devices: devicesTable, + KeyBackups: keyBackupTable, + KeyBackupVersions: keyBackupVersionTable, + LoginTokens: loginTokenTable, + OpenIDTokens: openIDTable, + Profiles: profilesTable, + ThreePIDs: threePIDTable, + Pushers: pusherTable, + Notifications: notificationsTable, + ServerName: serverName, + DB: db, + Writer: sqlutil.NewExclusiveWriter(), + LoginTokenLifetime: loginTokenLifetime, + BcryptCost: bcryptCost, + OpenIDTokenLifetime: openIDTokenLifetimeMS, }, nil } diff --git a/userapi/storage/storage.go b/userapi/storage/storage.go index faf1ce75c..04060d410 100644 --- a/userapi/storage/storage.go +++ b/userapi/storage/storage.go @@ -30,12 +30,12 @@ import ( // NewUserAPIDatabase opens a new Postgres or Sqlite database (based on dataSourceName scheme) // and sets postgres connection parameters -func NewUserAPIDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName, bcryptCost int, openIDTokenLifetimeMS int64, loginTokenLifetime time.Duration, serverNoticesLocalpart string) (Database, error) { +func NewUserAPIDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName, bcryptCost int, openIDTokenLifetime, loginTokenLifetime time.Duration, serverNoticesLocalpart string) (Database, error) { switch { case dbProperties.ConnectionString.IsSQLite(): - return sqlite3.NewDatabase(dbProperties, serverName, bcryptCost, openIDTokenLifetimeMS, loginTokenLifetime, serverNoticesLocalpart) + return sqlite3.NewDatabase(dbProperties, serverName, bcryptCost, openIDTokenLifetime, loginTokenLifetime, serverNoticesLocalpart) case dbProperties.ConnectionString.IsPostgres(): - return postgres.NewDatabase(dbProperties, serverName, bcryptCost, openIDTokenLifetimeMS, loginTokenLifetime, serverNoticesLocalpart) + return postgres.NewDatabase(dbProperties, serverName, bcryptCost, openIDTokenLifetime, loginTokenLifetime, serverNoticesLocalpart) default: return nil, fmt.Errorf("unexpected database type") } diff --git a/userapi/storage/storage_test.go b/userapi/storage/storage_test.go index ef25b8000..9586f10cb 100644 --- a/userapi/storage/storage_test.go +++ b/userapi/storage/storage_test.go @@ -20,18 +20,20 @@ import ( "golang.org/x/crypto/bcrypt" ) -const loginTokenLifetime = time.Minute +const ( + loginTokenLifetime = time.Minute + openIDLifetime = time.Minute +) var ( - openIDLifetimeMS = time.Minute.Milliseconds() - ctx = context.Background() + ctx = context.Background() ) func mustCreateDatabase(t *testing.T, dbType test.DBType) (storage.Database, func()) { connStr, close := test.PrepareDBConnectionString(t, dbType) db, err := storage.NewUserAPIDatabase(&config.DatabaseOptions{ ConnectionString: config.DataSource(connStr), - }, "localhost", bcrypt.MinCost, openIDLifetimeMS, loginTokenLifetime, "_server") + }, "localhost", bcrypt.MinCost, openIDLifetime, loginTokenLifetime, "_server") if err != nil { t.Fatalf("NewUserAPIDatabase returned %s", err) } @@ -328,15 +330,15 @@ func Test_OpenID(t *testing.T) { db, close := mustCreateDatabase(t, dbType) defer close() - expiresAtMS := time.Now().UnixNano()/int64(time.Millisecond) + openIDLifetimeMS + expiresAt := gomatrixserverlib.AsTimestamp(time.Now().Add(openIDLifetime)) expires, err := db.CreateOpenIDToken(ctx, token, alice.ID) assert.NoError(t, err, "unable to create OpenID token") - assert.Equal(t, expiresAtMS, expires) + assert.Equal(t, expiresAt, expires) attributes, err := db.GetOpenIDTokenAttributes(ctx, token) assert.NoError(t, err, "unable to get OpenID token attributes") assert.Equal(t, alice.ID, attributes.UserID) - assert.Equal(t, expiresAtMS, attributes.ExpiresAtMS) + assert.Equal(t, expiresAt, attributes.ExpiresAt) }) } diff --git a/userapi/storage/storage_wasm.go b/userapi/storage/storage_wasm.go index a8e6f031c..ad26d1fdd 100644 --- a/userapi/storage/storage_wasm.go +++ b/userapi/storage/storage_wasm.go @@ -27,13 +27,12 @@ func NewUserAPIDatabase( dbProperties *config.DatabaseOptions, serverName gomatrixserverlib.ServerName, bcryptCost int, - openIDTokenLifetimeMS int64, - loginTokenLifetime time.Duration, + openIDTokenLifetime, loginTokenLifetime time.Duration, serverNoticesLocalpart string, ) (Database, error) { switch { case dbProperties.ConnectionString.IsSQLite(): - return sqlite3.NewDatabase(dbProperties, serverName, bcryptCost, openIDTokenLifetimeMS, loginTokenLifetime, serverNoticesLocalpart) + return sqlite3.NewDatabase(dbProperties, serverName, bcryptCost, openIDTokenLifetime, loginTokenLifetime, serverNoticesLocalpart) case dbProperties.ConnectionString.IsPostgres(): return nil, fmt.Errorf("can't use Postgres implementation") default: diff --git a/userapi/storage/tables/interface.go b/userapi/storage/tables/interface.go index eb0cae314..e9965e7cf 100644 --- a/userapi/storage/tables/interface.go +++ b/userapi/storage/tables/interface.go @@ -21,6 +21,7 @@ import ( "github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/dendrite/userapi/api" + "github.com/matrix-org/gomatrixserverlib" ) type AccountDataTable interface { @@ -75,7 +76,7 @@ type LoginTokenTable interface { } type OpenIDTable interface { - InsertOpenIDToken(ctx context.Context, txn *sql.Tx, token, localpart string, expiresAtMS int64) (err error) + InsertOpenIDToken(ctx context.Context, txn *sql.Tx, token, localpart string, expiresAtMS gomatrixserverlib.Timestamp) (err error) SelectOpenIDTokenAtrributes(ctx context.Context, token string) (*api.OpenIDTokenAttributes, error) } diff --git a/userapi/userapi_test.go b/userapi/userapi_test.go index 076b4f3c6..808bfc900 100644 --- a/userapi/userapi_test.go +++ b/userapi/userapi_test.go @@ -52,7 +52,7 @@ func MustMakeInternalAPI(t *testing.T, opts apiTestOpts) (api.UserInternalAPI, s MaxOpenConnections: 1, MaxIdleConnections: 1, } - accountDB, err := storage.NewUserAPIDatabase(dbopts, serverName, bcrypt.MinCost, config.DefaultOpenIDTokenLifetimeMS, opts.loginTokenLifetime, "") + accountDB, err := storage.NewUserAPIDatabase(dbopts, serverName, bcrypt.MinCost, config.DefaultOpenIDTokenLifetime, opts.loginTokenLifetime, "") if err != nil { t.Fatalf("failed to create account DB: %s", err) }