More config cleanup

This commit is contained in:
Till Faelligen 2022-05-02 13:24:59 +02:00
parent e5773a695f
commit 7f520fc053
25 changed files with 145 additions and 150 deletions

View file

@ -114,10 +114,10 @@ global:
# Maximum number of entries to hold in the DNS cache, and # Maximum number of entries to hold in the DNS cache, and
# for how long those items should be considered valid in seconds. # for how long those items should be considered valid in seconds.
cache_size: 256 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. # Configuration for the Appservice API.
app_service_api: appservice_api:
internal_api: internal_api:
listen: http://0.0.0.0:7777 listen: http://0.0.0.0:7777
connect: http://appservice_api:7777 connect: http://appservice_api:7777
@ -311,17 +311,18 @@ user_api:
max_open_conns: 10 max_open_conns: 10
max_idle_conns: 2 max_idle_conns: 2
conn_max_lifetime: -1 conn_max_lifetime: -1
# The cost when hashing passwords on registration/login. Default: 10. Min: 4, Max: 31
# Configuration for the Push Server API. # See https://pkg.go.dev/golang.org/x/crypto/bcrypt for more information.
push_server: # Setting this lower makes registration/login consume less CPU resources at the cost of security
internal_api: # should the database be compromised. Setting this higher makes registration/login consume more
listen: http://localhost:7782 # CPU resources but makes it harder to brute force password hashes.
connect: http://localhost:7782 # This value can be low if performing tests or on embedded Dendrite instances (e.g WASM builds)
database: # bcrypt_cost: 10
connection_string: postgresql://dendrite:itsasecret@postgres/dendrite_pushserver?sslmode=disable # The length of time that a token issued for a relying party from
max_open_conns: 10 # /_matrix/client/r0/user/{userId}/openid/request_token endpoint
max_idle_conns: 2 # is considered to be valid.
conn_max_lifetime: -1 # 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. # Configuration for Opentracing.
# See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on # See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on

View file

@ -16,6 +16,7 @@ package routing
import ( import (
"net/http" "net/http"
"time"
"github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/setup/config"
@ -64,7 +65,7 @@ func CreateOpenIDToken(
AccessToken: response.Token.Token, AccessToken: response.Token.Token,
TokenType: "Bearer", TokenType: "Bearer",
MatrixServerName: string(cfg.Matrix.ServerName), MatrixServerName: string(cfg.Matrix.ServerName),
ExpiresIn: response.Token.ExpiresAtMS / 1000, // convert ms to s ExpiresIn: int64(time.Until(response.Token.ExpiresAt.Time()).Seconds()),
}, },
} }
} }

View file

@ -35,23 +35,20 @@ func RequestTurnServer(req *http.Request, device *api.Device, cfg *config.Client
turnConfig := cfg.TURN turnConfig := cfg.TURN
// TODO Guest Support // TODO Guest Support
if len(turnConfig.URIs) == 0 || turnConfig.UserLifetime == "" { if len(turnConfig.URIs) == 0 || turnConfig.UserLifetime.Seconds() == 0 {
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusOK, Code: http.StatusOK,
JSON: struct{}{}, JSON: struct{}{},
} }
} }
// Duration checked at startup, err not possible
duration, _ := time.ParseDuration(turnConfig.UserLifetime)
resp := gomatrix.RespTurnServer{ resp := gomatrix.RespTurnServer{
URIs: turnConfig.URIs, URIs: turnConfig.URIs,
TTL: int(duration.Seconds()), TTL: int(turnConfig.UserLifetime.Seconds()),
} }
if turnConfig.SharedSecret != "" { 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) resp.Username = fmt.Sprintf("%d:%s", expiry, device.UserID)
mac := hmac.New(sha1.New, []byte(turnConfig.SharedSecret)) mac := hmac.New(sha1.New, []byte(turnConfig.SharedSecret))
_, err := mac.Write([]byte(resp.Username)) _, err := mac.Write([]byte(resp.Username))

View file

@ -140,7 +140,7 @@ global:
cache_lifetime: "5m" # 5minutes; see https://pkg.go.dev/time@master#ParseDuration for more cache_lifetime: "5m" # 5minutes; see https://pkg.go.dev/time@master#ParseDuration for more
# Configuration for the Appservice API. # Configuration for the Appservice API.
app_service_api: appservice_api:
# Disable the validation of TLS certificates of appservices. This is # Disable the validation of TLS certificates of appservices. This is
# not recommended in production since it may allow appservice traffic # not recommended in production since it may allow appservice traffic
# to be sent to an unverified endpoint. # to be sent to an unverified endpoint.
@ -174,7 +174,7 @@ client_api:
# TURN server information that this homeserver should send to clients. # TURN server information that this homeserver should send to clients.
turn: turn:
turn_user_lifetime: "" turn_user_lifetime: "24h" # 24 hours; see https://pkg.go.dev/time@master#ParseDuration for more
turn_uris: [] turn_uris: []
turn_shared_secret: "" turn_shared_secret: ""
turn_username: "" turn_username: ""
@ -268,9 +268,9 @@ user_api:
# bcrypt_cost: 10 # bcrypt_cost: 10
# The length of time that a token issued for a relying party from # The length of time that a token issued for a relying party from
# /_matrix/client/r0/user/{userId}/openid/request_token endpoint # /_matrix/client/r0/user/{userId}/openid/request_token endpoint
# is considered to be valid in milliseconds. # is considered to be valid.
# The default lifetime is 3600000ms (60 minutes). # The default lifetime is 60 minutes.
# openid_token_lifetime_ms: 3600000 # openid_token_lifetime: "1h" # One hour; see https://pkg.go.dev/time@master#ParseDuration for more
# Configuration for Opentracing. # Configuration for Opentracing.
# See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on # See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on

View file

@ -131,7 +131,7 @@ global:
cache_lifetime: "5m" # 5minutes; see https://pkg.go.dev/time@master#ParseDuration for more cache_lifetime: "5m" # 5minutes; see https://pkg.go.dev/time@master#ParseDuration for more
# Configuration for the Appservice API. # Configuration for the Appservice API.
app_service_api: appservice_api:
internal_api: internal_api:
listen: http://localhost:7777 # Only used in polylith deployments listen: http://localhost:7777 # Only used in polylith deployments
connect: 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 server information that this homeserver should send to clients.
turn: turn:
turn_user_lifetime: "" turn_user_lifetime: "24h" # 24 hours; see https://pkg.go.dev/time@master#ParseDuration for more
turn_uris: [] turn_uris: []
turn_shared_secret: "" turn_shared_secret: ""
turn_username: "" turn_username: ""
@ -342,9 +342,9 @@ user_api:
conn_max_lifetime: -1 conn_max_lifetime: -1
# The length of time that a token issued for a relying party from # The length of time that a token issued for a relying party from
# /_matrix/client/r0/user/{userId}/openid/request_token endpoint # /_matrix/client/r0/user/{userId}/openid/request_token endpoint
# is considered to be valid in milliseconds. # is considered to be valid.
# The default lifetime is 3600000ms (60 minutes). # The default lifetime is 60 minutes.
# openid_token_lifetime_ms: 3600000 # openid_token_lifetime: "1h" # One hour; see https://pkg.go.dev/time@master#ParseDuration for more
# Configuration for Opentracing. # Configuration for Opentracing.
# See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on # See https://github.com/matrix-org/dendrite/tree/master/docs/tracing for information on

View file

@ -52,8 +52,7 @@ func GetOpenIDUserInfo(
var res interface{} = openIDUserInfoResponse{Sub: openIDTokenAttrResponse.Sub} var res interface{} = openIDUserInfoResponse{Sub: openIDTokenAttrResponse.Sub}
code := http.StatusOK code := http.StatusOK
nowMS := time.Now().UnixNano() / int64(time.Millisecond) if openIDTokenAttrResponse.Sub == "" || time.Now().After(openIDTokenAttrResponse.ExpiresAt.Time()) {
if openIDTokenAttrResponse.Sub == "" || nowMS > openIDTokenAttrResponse.ExpiresAtMS {
code = http.StatusUnauthorized code = http.StatusUnauthorized
res = jsonerror.UnknownToken("Access Token unknown or expired") res = jsonerror.UnknownToken("Access Token unknown or expired")
} }

View file

@ -280,7 +280,7 @@ func (b *BaseDendrite) CreateAccountsDB() userdb.Database {
&b.Cfg.UserAPI.AccountDatabase, &b.Cfg.UserAPI.AccountDatabase,
b.Cfg.Global.ServerName, b.Cfg.Global.ServerName,
b.Cfg.UserAPI.BCryptCost, b.Cfg.UserAPI.BCryptCost,
b.Cfg.UserAPI.OpenIDTokenLifetimeMS, b.Cfg.UserAPI.OpenIDTokenLifetime,
userapi.DefaultLoginTokenLifetime, userapi.DefaultLoginTokenLifetime,
b.Cfg.Global.ServerNotices.LocalPart, b.Cfg.Global.ServerNotices.LocalPart,
) )

View file

@ -29,7 +29,7 @@ import (
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/crypto/ed25519" "golang.org/x/crypto/ed25519"
yaml "gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
jaegerconfig "github.com/uber/jaeger-client-go/config" jaegerconfig "github.com/uber/jaeger-client-go/config"
jaegermetrics "github.com/uber/jaeger-lib/metrics" jaegermetrics "github.com/uber/jaeger-lib/metrics"
@ -54,7 +54,7 @@ type Dendrite struct {
Version int `yaml:"version"` Version int `yaml:"version"`
Global Global `yaml:"global"` Global Global `yaml:"global"`
AppServiceAPI AppServiceAPI `yaml:"app_service_api"` AppServiceAPI AppServiceAPI `yaml:"appservice_api"`
ClientAPI ClientAPI `yaml:"client_api"` ClientAPI ClientAPI `yaml:"client_api"`
FederationAPI FederationAPI `yaml:"federation_api"` FederationAPI FederationAPI `yaml:"federation_api"`
KeyServer KeyServer `yaml:"key_server"` KeyServer KeyServer `yaml:"key_server"`

View file

@ -50,10 +50,10 @@ func (c *AppServiceAPI) Defaults(generate bool) {
} }
func (c *AppServiceAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *AppServiceAPI) Verify(configErrs *ConfigErrors, isMonolith bool) {
checkURL(configErrs, "app_service_api.internal_api.listen", string(c.InternalAPI.Listen)) checkURL(configErrs, "appservice_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.bind", string(c.InternalAPI.Connect))
setDatabase(c.Matrix.GlobalDatabaseOptions, &c.Database, "appservice.db") 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 // ApplicationServiceNamespace is the namespace that a specific application

View file

@ -1,7 +1,6 @@
package config package config
import ( import (
"fmt"
"time" "time"
) )
@ -64,6 +63,7 @@ func (c *ClientAPI) Defaults(generate bool) {
c.RegistrationDisabled = true c.RegistrationDisabled = true
c.OpenRegistrationWithoutVerificationEnabled = false c.OpenRegistrationWithoutVerificationEnabled = false
c.RateLimiting.Defaults() c.RateLimiting.Defaults()
c.TURN.Defaults()
} }
func (c *ClientAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { func (c *ClientAPI) Verify(configErrs *ConfigErrors, isMonolith bool) {
@ -100,7 +100,7 @@ type TURN struct {
// Whether or not guests can request TURN credentials // Whether or not guests can request TURN credentials
// AllowGuests bool `yaml:"turn_allow_guests"` // AllowGuests bool `yaml:"turn_allow_guests"`
// How long the authorization should last // 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 // The list of TURN URIs to pass to clients
URIs []string `yaml:"turn_uris"` URIs []string `yaml:"turn_uris"`
@ -115,12 +115,11 @@ type TURN struct {
} }
func (c *TURN) Verify(configErrs *ConfigErrors) { func (c *TURN) Verify(configErrs *ConfigErrors) {
value := c.UserLifetime checkPositive(configErrs, "cache_lifetime", int64(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)) func (c *TURN) Defaults() {
} c.UserLifetime = time.Hour * 24
}
} }
type RateLimiting struct { type RateLimiting struct {

View file

@ -63,7 +63,7 @@ global:
display_name: "Server alerts" display_name: "Server alerts"
avatar: "" avatar: ""
room_name: "Server Alerts" room_name: "Server Alerts"
app_service_api: appservice_api:
internal_api: internal_api:
listen: http://localhost:7777 listen: http://localhost:7777
connect: http://localhost:7777 connect: http://localhost:7777
@ -87,20 +87,11 @@ client_api:
recaptcha_bypass_secret: "" recaptcha_bypass_secret: ""
recaptcha_siteverify_api: "" recaptcha_siteverify_api: ""
turn: turn:
turn_user_lifetime: "" turn_user_lifetime: "1h"
turn_uris: [] turn_uris: []
turn_shared_secret: "" turn_shared_secret: ""
turn_username: "" turn_username: ""
turn_password: "" 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: federation_api:
internal_api: internal_api:
listen: http://localhost:7772 listen: http://localhost:7772

View file

@ -1,6 +1,10 @@
package config package config
import "golang.org/x/crypto/bcrypt" import (
"time"
"golang.org/x/crypto/bcrypt"
)
type UserAPI struct { type UserAPI struct {
Matrix *Global `yaml:"-"` Matrix *Global `yaml:"-"`
@ -11,7 +15,7 @@ type UserAPI struct {
BCryptCost int `yaml:"bcrypt_cost"` BCryptCost int `yaml:"bcrypt_cost"`
// The length of time an OpenID token is condidered valid in milliseconds // 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! // Disable TLS validation on HTTPS calls to push gatways. NOT RECOMMENDED!
PushGatewayDisableTLSValidation bool `yaml:"push_gateway_disable_tls_validation"` PushGatewayDisableTLSValidation bool `yaml:"push_gateway_disable_tls_validation"`
@ -21,7 +25,7 @@ type UserAPI struct {
AccountDatabase DatabaseOptions `yaml:"account_database"` AccountDatabase DatabaseOptions `yaml:"account_database"`
} }
const DefaultOpenIDTokenLifetimeMS = 3600000 // 60 minutes var DefaultOpenIDTokenLifetime = time.Hour
func (c *UserAPI) Defaults(generate bool) { func (c *UserAPI) Defaults(generate bool) {
c.InternalAPI.Listen = "http://localhost:7781" c.InternalAPI.Listen = "http://localhost:7781"
@ -31,7 +35,7 @@ func (c *UserAPI) Defaults(generate bool) {
c.AccountDatabase.ConnectionString = "file:userapi_accounts.db" c.AccountDatabase.ConnectionString = "file:userapi_accounts.db"
} }
c.BCryptCost = bcrypt.DefaultCost c.BCryptCost = bcrypt.DefaultCost
c.OpenIDTokenLifetimeMS = DefaultOpenIDTokenLifetimeMS c.OpenIDTokenLifetime = DefaultOpenIDTokenLifetime
} }
func (c *UserAPI) Verify(configErrs *ConfigErrors, isMonolith bool) { 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)) checkURL(configErrs, "user_api.internal_api.connect", string(c.InternalAPI.Connect))
setDatabase(c.Matrix.GlobalDatabaseOptions, &c.AccountDatabase, "userapi.db") setDatabase(c.Matrix.GlobalDatabaseOptions, &c.AccountDatabase, "userapi.db")
checkNotEmpty(configErrs, "user_api.account_database.connection_string", string(c.AccountDatabase.ConnectionString)) 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())
} }

View file

@ -379,7 +379,7 @@ type QueryOpenIDTokenRequest struct {
// QueryOpenIDTokenResponse is the response for QueryOpenIDToken // QueryOpenIDTokenResponse is the response for QueryOpenIDToken
type QueryOpenIDTokenResponse struct { type QueryOpenIDTokenResponse struct {
Sub string // The Matrix User ID that generated the token Sub string // The Matrix User ID that generated the token
ExpiresAtMS int64 ExpiresAt gomatrixserverlib.Timestamp
} }
// Device represents a client's device (mobile, web, etc) // Device represents a client's device (mobile, web, etc)
@ -417,13 +417,13 @@ type Account struct {
type OpenIDToken struct { type OpenIDToken struct {
Token string Token string
UserID string UserID string
ExpiresAtMS int64 ExpiresAt gomatrixserverlib.Timestamp
} }
// OpenIDTokenInfo represents the attributes associated with an issued OpenID token // OpenIDTokenInfo represents the attributes associated with an issued OpenID token
type OpenIDTokenAttributes struct { type OpenIDTokenAttributes struct {
UserID string UserID string
ExpiresAtMS int64 ExpiresAt gomatrixserverlib.Timestamp
} }
// UserInfo is for returning information about the user an OpenID token was issued for // UserInfo is for returning information about the user an OpenID token was issued for

View file

@ -466,7 +466,7 @@ func (a *UserInternalAPI) PerformOpenIDTokenCreation(ctx context.Context, req *a
res.Token = api.OpenIDToken{ res.Token = api.OpenIDToken{
Token: token, Token: token,
UserID: req.UserID, UserID: req.UserID,
ExpiresAtMS: exp, ExpiresAt: exp,
} }
return err return err
@ -480,7 +480,7 @@ func (a *UserInternalAPI) QueryOpenIDToken(ctx context.Context, req *api.QueryOp
} }
res.Sub = openIDTokenAttrs.UserID res.Sub = openIDTokenAttrs.UserID
res.ExpiresAtMS = openIDTokenAttrs.ExpiresAtMS res.ExpiresAt = openIDTokenAttrs.ExpiresAt
return nil return nil
} }

View file

@ -22,6 +22,7 @@ import (
"github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/dendrite/userapi/storage/tables" "github.com/matrix-org/dendrite/userapi/storage/tables"
"github.com/matrix-org/gomatrixserverlib"
) )
type Profile interface { type Profile interface {
@ -97,7 +98,7 @@ type LoginToken interface {
} }
type OpenID 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) GetOpenIDTokenAttributes(ctx context.Context, token string) (*api.OpenIDTokenAttributes, error)
} }

View file

@ -55,7 +55,7 @@ func (s *openIDTokenStatements) InsertOpenIDToken(
ctx context.Context, ctx context.Context,
txn *sql.Tx, txn *sql.Tx,
token, localpart string, token, localpart string,
expiresAtMS int64, expiresAtMS gomatrixserverlib.Timestamp,
) (err error) { ) (err error) {
stmt := sqlutil.TxStmt(txn, s.insertTokenStmt) stmt := sqlutil.TxStmt(txn, s.insertTokenStmt)
_, err = stmt.ExecContext(ctx, token, localpart, expiresAtMS) _, err = stmt.ExecContext(ctx, token, localpart, expiresAtMS)
@ -71,7 +71,7 @@ func (s *openIDTokenStatements) SelectOpenIDTokenAtrributes(
var openIDTokenAttrs api.OpenIDTokenAttributes var openIDTokenAttrs api.OpenIDTokenAttributes
err := s.selectTokenStmt.QueryRowContext(ctx, token).Scan( err := s.selectTokenStmt.QueryRowContext(ctx, token).Scan(
&openIDTokenAttrs.UserID, &openIDTokenAttrs.UserID,
&openIDTokenAttrs.ExpiresAtMS, &openIDTokenAttrs.ExpiresAt,
) )
if err != nil { if err != nil {
if err != sql.ErrNoRows { if err != sql.ErrNoRows {

View file

@ -30,7 +30,7 @@ import (
) )
// NewDatabase creates a new accounts and profiles database // 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) db, err := sqlutil.Open(dbProperties)
if err != nil { if err != nil {
return nil, err return nil, err
@ -110,6 +110,6 @@ func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserver
Writer: sqlutil.NewDummyWriter(), Writer: sqlutil.NewDummyWriter(),
LoginTokenLifetime: loginTokenLifetime, LoginTokenLifetime: loginTokenLifetime,
BcryptCost: bcryptCost, BcryptCost: bcryptCost,
OpenIDTokenLifetimeMS: openIDTokenLifetimeMS, OpenIDTokenLifetime: openIDTokenLifetimeMS,
}, nil }, nil
} }

View file

@ -54,7 +54,7 @@ type Database struct {
LoginTokenLifetime time.Duration LoginTokenLifetime time.Duration
ServerName gomatrixserverlib.ServerName ServerName gomatrixserverlib.ServerName
BcryptCost int BcryptCost int
OpenIDTokenLifetimeMS int64 OpenIDTokenLifetime time.Duration
} }
const ( const (
@ -325,12 +325,12 @@ func (d *Database) DeactivateAccount(ctx context.Context, localpart string) (err
func (d *Database) CreateOpenIDToken( func (d *Database) CreateOpenIDToken(
ctx context.Context, ctx context.Context,
token, localpart string, token, localpart string,
) (int64, error) { ) (gomatrixserverlib.Timestamp, error) {
expiresAtMS := time.Now().UnixNano()/int64(time.Millisecond) + d.OpenIDTokenLifetimeMS expiresAt := gomatrixserverlib.AsTimestamp(time.Now().Add(d.OpenIDTokenLifetime))
err := d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error { 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 // GetOpenIDTokenAttributes gets the attributes of issued an OIDC auth token

View file

@ -57,7 +57,7 @@ func (s *openIDTokenStatements) InsertOpenIDToken(
ctx context.Context, ctx context.Context,
txn *sql.Tx, txn *sql.Tx,
token, localpart string, token, localpart string,
expiresAtMS int64, expiresAtMS gomatrixserverlib.Timestamp,
) (err error) { ) (err error) {
stmt := sqlutil.TxStmt(txn, s.insertTokenStmt) stmt := sqlutil.TxStmt(txn, s.insertTokenStmt)
_, err = stmt.ExecContext(ctx, token, localpart, expiresAtMS) _, err = stmt.ExecContext(ctx, token, localpart, expiresAtMS)
@ -73,7 +73,7 @@ func (s *openIDTokenStatements) SelectOpenIDTokenAtrributes(
var openIDTokenAttrs api.OpenIDTokenAttributes var openIDTokenAttrs api.OpenIDTokenAttributes
err := s.selectTokenStmt.QueryRowContext(ctx, token).Scan( err := s.selectTokenStmt.QueryRowContext(ctx, token).Scan(
&openIDTokenAttrs.UserID, &openIDTokenAttrs.UserID,
&openIDTokenAttrs.ExpiresAtMS, &openIDTokenAttrs.ExpiresAt,
) )
if err != nil { if err != nil {
if err != sql.ErrNoRows { if err != sql.ErrNoRows {

View file

@ -31,7 +31,7 @@ import (
) )
// NewDatabase creates a new accounts and profiles database // 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) db, err := sqlutil.Open(dbProperties)
if err != nil { if err != nil {
return nil, err return nil, err
@ -111,6 +111,6 @@ func NewDatabase(dbProperties *config.DatabaseOptions, serverName gomatrixserver
Writer: sqlutil.NewExclusiveWriter(), Writer: sqlutil.NewExclusiveWriter(),
LoginTokenLifetime: loginTokenLifetime, LoginTokenLifetime: loginTokenLifetime,
BcryptCost: bcryptCost, BcryptCost: bcryptCost,
OpenIDTokenLifetimeMS: openIDTokenLifetimeMS, OpenIDTokenLifetime: openIDTokenLifetimeMS,
}, nil }, nil
} }

View file

@ -30,12 +30,12 @@ import (
// NewUserAPIDatabase opens a new Postgres or Sqlite database (based on dataSourceName scheme) // NewUserAPIDatabase opens a new Postgres or Sqlite database (based on dataSourceName scheme)
// and sets postgres connection parameters // 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 { switch {
case dbProperties.ConnectionString.IsSQLite(): 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(): case dbProperties.ConnectionString.IsPostgres():
return postgres.NewDatabase(dbProperties, serverName, bcryptCost, openIDTokenLifetimeMS, loginTokenLifetime, serverNoticesLocalpart) return postgres.NewDatabase(dbProperties, serverName, bcryptCost, openIDTokenLifetime, loginTokenLifetime, serverNoticesLocalpart)
default: default:
return nil, fmt.Errorf("unexpected database type") return nil, fmt.Errorf("unexpected database type")
} }

View file

@ -20,10 +20,12 @@ import (
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
const loginTokenLifetime = time.Minute const (
loginTokenLifetime = time.Minute
openIDLifetime = time.Minute
)
var ( var (
openIDLifetimeMS = time.Minute.Milliseconds()
ctx = context.Background() ctx = context.Background()
) )
@ -31,7 +33,7 @@ func mustCreateDatabase(t *testing.T, dbType test.DBType) (storage.Database, fun
connStr, close := test.PrepareDBConnectionString(t, dbType) connStr, close := test.PrepareDBConnectionString(t, dbType)
db, err := storage.NewUserAPIDatabase(&config.DatabaseOptions{ db, err := storage.NewUserAPIDatabase(&config.DatabaseOptions{
ConnectionString: config.DataSource(connStr), ConnectionString: config.DataSource(connStr),
}, "localhost", bcrypt.MinCost, openIDLifetimeMS, loginTokenLifetime, "_server") }, "localhost", bcrypt.MinCost, openIDLifetime, loginTokenLifetime, "_server")
if err != nil { if err != nil {
t.Fatalf("NewUserAPIDatabase returned %s", err) t.Fatalf("NewUserAPIDatabase returned %s", err)
} }
@ -328,15 +330,15 @@ func Test_OpenID(t *testing.T) {
db, close := mustCreateDatabase(t, dbType) db, close := mustCreateDatabase(t, dbType)
defer close() 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) expires, err := db.CreateOpenIDToken(ctx, token, alice.ID)
assert.NoError(t, err, "unable to create OpenID token") 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) attributes, err := db.GetOpenIDTokenAttributes(ctx, token)
assert.NoError(t, err, "unable to get OpenID token attributes") assert.NoError(t, err, "unable to get OpenID token attributes")
assert.Equal(t, alice.ID, attributes.UserID) assert.Equal(t, alice.ID, attributes.UserID)
assert.Equal(t, expiresAtMS, attributes.ExpiresAtMS) assert.Equal(t, expiresAt, attributes.ExpiresAt)
}) })
} }

View file

@ -27,13 +27,12 @@ func NewUserAPIDatabase(
dbProperties *config.DatabaseOptions, dbProperties *config.DatabaseOptions,
serverName gomatrixserverlib.ServerName, serverName gomatrixserverlib.ServerName,
bcryptCost int, bcryptCost int,
openIDTokenLifetimeMS int64, openIDTokenLifetime, loginTokenLifetime time.Duration,
loginTokenLifetime time.Duration,
serverNoticesLocalpart string, serverNoticesLocalpart string,
) (Database, error) { ) (Database, error) {
switch { switch {
case dbProperties.ConnectionString.IsSQLite(): 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(): case dbProperties.ConnectionString.IsPostgres():
return nil, fmt.Errorf("can't use Postgres implementation") return nil, fmt.Errorf("can't use Postgres implementation")
default: default:

View file

@ -21,6 +21,7 @@ import (
"github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/userapi/api" "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
) )
type AccountDataTable interface { type AccountDataTable interface {
@ -75,7 +76,7 @@ type LoginTokenTable interface {
} }
type OpenIDTable 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) SelectOpenIDTokenAtrributes(ctx context.Context, token string) (*api.OpenIDTokenAttributes, error)
} }

View file

@ -52,7 +52,7 @@ func MustMakeInternalAPI(t *testing.T, opts apiTestOpts) (api.UserInternalAPI, s
MaxOpenConnections: 1, MaxOpenConnections: 1,
MaxIdleConnections: 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 { if err != nil {
t.Fatalf("failed to create account DB: %s", err) t.Fatalf("failed to create account DB: %s", err)
} }