This repository has been archived by the owner on Jan 25, 2022. It is now read-only.
/
auth_helper.go
81 lines (72 loc) · 2.07 KB
/
auth_helper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Copyright (c) 2012 VMware, Inc.
package gonatsd
import (
"time"
)
type AuthHelper struct {
conn Conn
users map[string]string
timer *time.Timer
channel <-chan time.Time
authorized bool
}
// Create a new AuthHelper for the connection with the specified user map and auth timeout.
func NewAuthHelper(conn Conn, users map[string]string, timeout time.Duration) *AuthHelper {
h := &AuthHelper{conn: conn, users: users}
if len(users) > 0 {
if timeout > 0 {
h.timer = time.NewTimer(timeout)
h.channel = h.timer.C
}
} else {
h.authorized = true
}
return h
}
// Authenticate and authorize the request.
// Returns true iff the request is authed, otherwise false with an error.
func (h *AuthHelper) Auth(req Request) (bool, *NATSError) {
if !h.authorized {
switch req.(type) {
case *ConnectRequest:
request := req.(*ConnectRequest)
if request.User == nil || request.Password == nil {
Log.Debugf("[client %s] did not send credentials", h.conn.RemoteAddr())
return false, ErrAuthRequired
}
password, ok := h.users[*request.User]
if ok && password == *request.Password {
Log.Debugf("[client %s] authenticated with: %s", h.conn.RemoteAddr(), *request.User)
h.authorized = true
h.Stop()
return true, nil
} else {
Log.Debugf("[client %s] sent wrong credentials", h.conn.RemoteAddr())
return false, ErrAuthFailed
}
default:
Log.Debugf("[client %s] did not send credentials", h.conn.RemoteAddr())
return false, ErrAuthRequired
}
}
return true, nil
}
// Stop the AuthHelper.
// Must be called to cleanup the internal timers.
func (h *AuthHelper) Stop() {
if h.timer != nil {
h.timer.Stop()
h.timer = nil
h.channel = nil
}
}
// Returns the internal timer channel, which should be used to call Timeout().
// It's exposed to avoid an additional goroutine, instead it can be handled
// from a single select statement.
func (h *AuthHelper) Timer() <-chan time.Time {
return h.channel
}
// Initiates auth timeout when the Timer() fires.
func (h *AuthHelper) Timeout() {
h.conn.CloseWithError(ErrAuthRequired)
}