Skip to content

Commit

Permalink
add IP address to rest_auth calls, tinode#576
Browse files Browse the repository at this point in the history
  • Loading branch information
or-else committed Dec 9, 2020
1 parent 3193ee2 commit c9cd224
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 51 deletions.
8 changes: 4 additions & 4 deletions server/auth/anon/auth_anon.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (authenticator) Init(_ json.RawMessage, _ string) error {

// AddRecord checks authLevel and assigns default LevelAnon. Otherwise it
// just reports success.
func (authenticator) AddRecord(rec *auth.Rec, secret []byte) (*auth.Rec, error) {
func (authenticator) AddRecord(rec *auth.Rec, secret []byte, remoteAddr string) (*auth.Rec, error) {
if rec.AuthLevel == auth.LevelNone {
rec.AuthLevel = auth.LevelAnon
}
Expand All @@ -30,12 +30,12 @@ func (authenticator) AddRecord(rec *auth.Rec, secret []byte) (*auth.Rec, error)
}

// UpdateRecord is a noop. Just report success.
func (authenticator) UpdateRecord(rec *auth.Rec, secret []byte) (*auth.Rec, error) {
func (authenticator) UpdateRecord(rec *auth.Rec, secret []byte, remoteAddr string) (*auth.Rec, error) {
return rec, nil
}

// Authenticate is not supported. This authenticator is used only at account creation time.
func (authenticator) Authenticate(secret []byte) (*auth.Rec, []byte, error) {
func (authenticator) Authenticate(secret []byte, remoteAddr string) (*auth.Rec, []byte, error) {
return nil, nil, types.ErrUnsupported
}

Expand All @@ -45,7 +45,7 @@ func (authenticator) AsTag(token string) string {
}

// IsUnique for a noop. Anonymous login does not use secret, any secret is fine.
func (authenticator) IsUnique(secret []byte) (bool, error) {
func (authenticator) IsUnique(secret []byte, remoteAddr string) (bool, error) {
return true, nil
}

Expand Down
10 changes: 6 additions & 4 deletions server/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,26 +233,28 @@ type AuthHandler interface {

// AddRecord adds persistent authentication record to the database.
// Returns: updated auth record, error
AddRecord(rec *Rec, secret []byte) (*Rec, error)
AddRecord(rec *Rec, secret []byte, remoteAddr string) (*Rec, error)

// UpdateRecord updates existing record with new credentials.
// Returns updated auth record, error.
UpdateRecord(rec *Rec, secret []byte) (*Rec, error)
UpdateRecord(rec *Rec, secret []byte, remoteAddr string) (*Rec, error)

// Authenticate: given a user-provided authentication secret (such as "login:password"), either
// return user's record (ID, time when the secret expires, etc), or issue a challenge to
// continue the authentication process to the next step, or return an error code.
// The remoteAddr (i.e. the IP address of the client) can be used by custom authenticators for
// additional validation. The stock authenticators don't use it.
// store.Users.GetAuthRecord("scheme", "unique")
// Returns: user auth record, challenge, error.
Authenticate(secret []byte) (*Rec, []byte, error)
Authenticate(secret []byte, remoteAddr string) (*Rec, []byte, error)

// AsTag converts search token into prefixed tag or an empty string if it
// cannot be represented as a prefixed tag.
AsTag(token string) string

// IsUnique verifies if the provided secret can be considered unique by the auth scheme
// E.g. if login is unique.
IsUnique(secret []byte) (bool, error)
IsUnique(secret []byte, remoteAddr string) (bool, error)

// GenSecret generates a new secret, if appropriate.
GenSecret(rec *Rec) ([]byte, time.Time, error)
Expand Down
8 changes: 4 additions & 4 deletions server/auth/basic/auth_basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (a *authenticator) Init(jsonconf json.RawMessage, name string) error {
}

// AddRecord adds a basic authentication record to DB.
func (a *authenticator) AddRecord(rec *auth.Rec, secret []byte) (*auth.Rec, error) {
func (a *authenticator) AddRecord(rec *auth.Rec, secret []byte, remoteAddr string) (*auth.Rec, error) {
uname, password, err := parseSecret(secret)
if err != nil {
return nil, err
Expand Down Expand Up @@ -147,7 +147,7 @@ func (a *authenticator) AddRecord(rec *auth.Rec, secret []byte) (*auth.Rec, erro
}

// UpdateRecord updates password for basic authentication.
func (a *authenticator) UpdateRecord(rec *auth.Rec, secret []byte) (*auth.Rec, error) {
func (a *authenticator) UpdateRecord(rec *auth.Rec, secret []byte, remoteAddr string) (*auth.Rec, error) {
uname, password, err := parseSecret(secret)
if err != nil {
return nil, err
Expand Down Expand Up @@ -207,7 +207,7 @@ func (a *authenticator) UpdateRecord(rec *auth.Rec, secret []byte) (*auth.Rec, e
}

// Authenticate checks login and password.
func (a *authenticator) Authenticate(secret []byte) (*auth.Rec, []byte, error) {
func (a *authenticator) Authenticate(secret []byte, remoteAddr string) (*auth.Rec, []byte, error) {
uname, password, err := parseSecret(secret)
if err != nil {
return nil, nil, err
Expand Down Expand Up @@ -258,7 +258,7 @@ func (a *authenticator) AsTag(token string) string {
}

// IsUnique checks login uniqueness.
func (a *authenticator) IsUnique(secret []byte) (bool, error) {
func (a *authenticator) IsUnique(secret []byte, remoteAddr string) (bool, error) {
uname, _, err := parseSecret(secret)
if err != nil {
return false, err
Expand Down
19 changes: 13 additions & 6 deletions server/auth/rest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,12 @@ add a logical renaming:

```js
{
"endpoint": "auth", // string, one of the endpoints as described below, optional.
"secret": "Ym9iOmJvYjEyMw==", // authentication secret as provided by the client.
"rec": { // authentication record
"endpoint": "auth", // string, one of the endpoints as described below, optional.
"secret": "Ym9iOmJvYjEyMw==", // authentication secret as provided by the client,
// base64-encoded bytes, optional.
"addr": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", // string, IPv4 or IPv6 address of
// the client making the request, optional.
"rec": { // authentication record, optional.
{
"uid": "LELEQHDWbgY", // user ID, int64 base64-encoded
"authlvl": "auth", // authentication level
Expand Down Expand Up @@ -155,6 +158,7 @@ If accounts are managed externally, it's likely to be unused and should generall
{
"endpoint": "add",
"secret": "Ym9iOmJvYjEyMw==",
"addr": "111.22.33.44",
"rec": {
"uid": "LELEQHDWbgY",
"lifetime": "10000s",
Expand Down Expand Up @@ -188,6 +192,7 @@ be used by client (Tinode) to create the account. The server may optionally retu
{
"endpoint": "auth",
"secret": "Ym9iOmJvYjEyMw==",
"addr": "111.22.33.44"
}
```

Expand Down Expand Up @@ -232,6 +237,7 @@ an error `"unsupported"`.
{
"endpoint": "checkunique",
"secret": "Ym9iOmJvYjEyMw==",
"addr": "111.22.33.44"
}
```

Expand All @@ -252,7 +258,7 @@ If accounts are managed by the server, the server should respond with an error `
"endpoint": "del",
"rec": {
"uid": "LELEQHDWbgY",
},
}
}
```

Expand All @@ -273,7 +279,7 @@ If accounts are managed by the server, the server should respond with an error `
"rec": {
"uid": "LELEQHDWbgY",
"authlvl": "auth",
},
}
}
```

Expand Down Expand Up @@ -318,10 +324,11 @@ If accounts are managed by the server, the server should respond with an error `
{
"endpoint": "upd",
"secret": "Ym9iOmJvYjEyMw==",
"addr": "111.22.33.44",
"rec": {
"uid": "LELEQHDWbgY",
"authlvl": "auth",
},
}
}
```

Expand Down
37 changes: 19 additions & 18 deletions server/auth/rest/auth_rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ type authenticator struct {

// Request to the server.
type request struct {
Endpoint string `json:"endpoint"`
Name string `json:"name"`
Record *auth.Rec `json:"rec,omitempty"`
Secret []byte `json:"secret,omitempty"`
Endpoint string `json:"endpoint"`
Name string `json:"name"`
Record *auth.Rec `json:"rec,omitempty"`
Secret []byte `json:"secret,omitempty"`
RemoteAddr string `json:"addr,omitempty"`
}

// User initialization data when creating a new user.
Expand Down Expand Up @@ -110,9 +111,9 @@ func (a *authenticator) Init(jsonconf json.RawMessage, name string) error {
}

// Execute HTTP POST to the server at the specified endpoint and with the provided payload.
func (a *authenticator) callEndpoint(endpoint string, rec *auth.Rec, secret []byte) (*response, error) {
func (a *authenticator) callEndpoint(endpoint string, rec *auth.Rec, secret []byte, remoteAddr string) (*response, error) {
// Convert payload to json.
req := &request{Endpoint: endpoint, Name: a.name, Record: rec, Secret: secret}
req := &request{Endpoint: endpoint, Name: a.name, Record: rec, Secret: secret, RemoteAddr: remoteAddr}
content, err := json.Marshal(req)
if err != nil {
return nil, err
Expand Down Expand Up @@ -154,8 +155,8 @@ func (a *authenticator) callEndpoint(endpoint string, rec *auth.Rec, secret []by

// AddRecord adds persistent authentication record to the database.
// Returns: updated auth record, error
func (a *authenticator) AddRecord(rec *auth.Rec, secret []byte) (*auth.Rec, error) {
resp, err := a.callEndpoint("add", rec, secret)
func (a *authenticator) AddRecord(rec *auth.Rec, secret []byte, remoteAddr string) (*auth.Rec, error) {
resp, err := a.callEndpoint("add", rec, secret, remoteAddr)
if err != nil {
return nil, err
}
Expand All @@ -164,14 +165,14 @@ func (a *authenticator) AddRecord(rec *auth.Rec, secret []byte) (*auth.Rec, erro
}

// UpdateRecord updates existing record with new credentials.
func (a *authenticator) UpdateRecord(rec *auth.Rec, secret []byte) (*auth.Rec, error) {
_, err := a.callEndpoint("upd", rec, secret)
func (a *authenticator) UpdateRecord(rec *auth.Rec, secret []byte, remoteAddr string) (*auth.Rec, error) {
_, err := a.callEndpoint("upd", rec, secret, remoteAddr)
return rec, err
}

// Authenticate: get user record by provided secret
func (a *authenticator) Authenticate(secret []byte) (*auth.Rec, []byte, error) {
resp, err := a.callEndpoint("auth", nil, secret)
func (a *authenticator) Authenticate(secret []byte, remoteAddr string) (*auth.Rec, []byte, error) {
resp, err := a.callEndpoint("auth", nil, secret, remoteAddr)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -204,7 +205,7 @@ func (a *authenticator) Authenticate(secret []byte) (*auth.Rec, []byte, error) {

// Report the new UID to the server.
resp.Record.Uid = user.Uid()
_, err = a.callEndpoint("link", resp.Record, secret)
_, err = a.callEndpoint("link", resp.Record, secret, "")
if err != nil {
store.Users.Delete(resp.Record.Uid, false)
return nil, nil, err
Expand All @@ -229,8 +230,8 @@ func (a *authenticator) AsTag(token string) string {

// IsUnique verifies if the provided secret can be considered unique by the auth scheme
// E.g. if login is unique.
func (a *authenticator) IsUnique(secret []byte) (bool, error) {
resp, err := a.callEndpoint("checkunique", nil, secret)
func (a *authenticator) IsUnique(secret []byte, remoteAddr string) (bool, error) {
resp, err := a.callEndpoint("checkunique", nil, secret, remoteAddr)
if err != nil {
return false, err
}
Expand All @@ -240,7 +241,7 @@ func (a *authenticator) IsUnique(secret []byte) (bool, error) {

// GenSecret generates a new secret, if appropriate.
func (a *authenticator) GenSecret(rec *auth.Rec) ([]byte, time.Time, error) {
resp, err := a.callEndpoint("gen", rec, nil)
resp, err := a.callEndpoint("gen", rec, nil, "")
if err != nil {
return nil, time.Time{}, err
}
Expand All @@ -250,7 +251,7 @@ func (a *authenticator) GenSecret(rec *auth.Rec) ([]byte, time.Time, error) {

// DelRecords deletes all authentication records for the given user.
func (a *authenticator) DelRecords(uid types.Uid) error {
_, err := a.callEndpoint("del", &auth.Rec{Uid: uid}, nil)
_, err := a.callEndpoint("del", &auth.Rec{Uid: uid}, nil, "")
return err
}

Expand All @@ -265,7 +266,7 @@ func (a *authenticator) RestrictedTags() ([]string, error) {
}

// First time use, fetch prefixes from the server.
resp, err := a.callEndpoint("rtagns", nil, nil)
resp, err := a.callEndpoint("rtagns", nil, nil, "")
if err != nil {
return nil, err
}
Expand Down
8 changes: 4 additions & 4 deletions server/auth/token/auth_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,17 @@ func (ta *authenticator) Init(jsonconf json.RawMessage, name string) error {
}

// AddRecord is not supprted, will produce an error.
func (authenticator) AddRecord(rec *auth.Rec, secret []byte) (*auth.Rec, error) {
func (authenticator) AddRecord(rec *auth.Rec, secret []byte, remoteAddr string) (*auth.Rec, error) {
return nil, types.ErrUnsupported
}

// UpdateRecord is not supported, will produce an error.
func (authenticator) UpdateRecord(rec *auth.Rec, secret []byte) (*auth.Rec, error) {
func (authenticator) UpdateRecord(rec *auth.Rec, secret []byte, remoteAddr string) (*auth.Rec, error) {
return nil, types.ErrUnsupported
}

// Authenticate checks validity of provided token.
func (ta *authenticator) Authenticate(token []byte) (*auth.Rec, []byte, error) {
func (ta *authenticator) Authenticate(token []byte, remoteAddr string) (*auth.Rec, []byte, error) {
var tl tokenLayout
dataSize := binary.Size(&tl)
if len(token) < dataSize+sha256.Size {
Expand Down Expand Up @@ -163,7 +163,7 @@ func (authenticator) AsTag(token string) string {
}

// IsUnique is not supported, will produce an error.
func (authenticator) IsUnique(token []byte) (bool, error) {
func (authenticator) IsUnique(token []byte, remoteAddr string) (bool, error) {
return false, types.ErrUnsupported
}

Expand Down
6 changes: 3 additions & 3 deletions server/hdl_longpoll.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func serveLongPoll(wrt http.ResponseWriter, req *http.Request) {
// New session
var count int
sess, count = globals.sessionStore.NewSession(wrt, "")
sess.remoteAddr = lpRemoteAddr(req)
sess.remoteAddr = getRemoteAddr(req)
log.Println("longPoll: session started", sess.sid, sess.remoteAddr, count)

wrt.WriteHeader(http.StatusCreated)
Expand All @@ -162,7 +162,7 @@ func serveLongPoll(wrt http.ResponseWriter, req *http.Request) {
return
}

addr := lpRemoteAddr(req)
addr := getRemoteAddr(req)
if sess.remoteAddr != addr {
sess.remoteAddr = addr
log.Println("longPoll: remote address changed", sid, addr)
Expand All @@ -187,7 +187,7 @@ func serveLongPoll(wrt http.ResponseWriter, req *http.Request) {
}

// Obtain IP address of the client.
func lpRemoteAddr(req *http.Request) string {
func getRemoteAddr(req *http.Request) string {
var addr string
if globals.useXForwardedFor {
addr = req.Header.Get("X-Forwarded-For")
Expand Down
2 changes: 1 addition & 1 deletion server/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ func authHttpRequest(req *http.Request) (types.Uid, []byte, error) {
}

if authhdl := store.GetLogicalAuthHandler(authMethod); authhdl != nil {
rec, challenge, err := authhdl.Authenticate(decodedSecret[:n])
rec, challenge, err := authhdl.Authenticate(decodedSecret[:n], getRemoteAddr(req))
if err != nil {
return uid, nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions server/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ func (s *Session) acc(msg *ClientComMessage) {
}

var err error
rec, _, err = store.GetLogicalAuthHandler("token").Authenticate(msg.Acc.Token)
rec, _, err = store.GetLogicalAuthHandler("token").Authenticate(msg.Acc.Token, s.remoteAddr)
if err != nil {
s.queueOut(decodeStoreError(err, msg.Acc.Id, "", msg.Timestamp,
map[string]interface{}{"what": "auth"}))
Expand Down Expand Up @@ -829,7 +829,7 @@ func (s *Session) login(msg *ClientComMessage) {
return
}

rec, challenge, err := handler.Authenticate(msg.Login.Secret)
rec, challenge, err := handler.Authenticate(msg.Login.Secret, s.remoteAddr)
if err != nil {
resp := decodeStoreError(err, msg.Id, "", msg.Timestamp, nil)
if resp.Ctrl.Code >= 500 {
Expand Down
Loading

0 comments on commit c9cd224

Please sign in to comment.