-
Notifications
You must be signed in to change notification settings - Fork 58
Auth Library
The nexus router implementation provides an authentication package that allows implementors to supply authenticator implementations. Included in this package is a challenge-response authenticator and ticket authenticator, which only need a KeyStore implementation for looking up authentication keys.
The authenticators have access to HTTP request and tracking/auth cookies when these are enabled in the router configuration. This allowing a router implementation to use cookie-based authentication, client tracking (generally for remembering previously authenticated clients), and information from websocket requests for making authentication decisions.
To enable the use of websocket request data and client tracking cookies, see the documentation for Cookie and Request Auth/Authz.
By supplying an implementation of the Authenticator
interface, any authentication logic can be defined for a router.
Nexus provides two implementations: CRAuthenticator
for challenge-response authentication and TicketAuthenticator
for ticket authentication.
To implement a wampcra authenticator, the biggest part is to define a KeyStore
. Here is a simple example that holds key information for one user:
type serverKeyStore struct {
provider string
role string
pbkdf2Key []byte
keylen int
iterations int
ticket string
}
func (ks *serverKeyStore) AuthKey(authid, authmethod string) ([]byte, error) {
if authid != "jdoe" {
return nil, errors.New("no such user: " + authid)
}
switch authmethod {
case "wampcra":
// Lookup the user's PBKDF2-derived key.
return ks.pbkdf2Key, nil
case "ticket":
// Lookup the user's key.
return ks.ticket, nil
}
return nil, errors.New("unsupported authmethod")
}
func (ks *serverKeyStore) PasswordInfo(authid string) (string, int, int) {
if authid != "jdoe" {
return "", 0, 0
}
return ks.salt, ks.keylen, ks.iterations
}
func (ks *serverKeyStore) Provider() string { return ks.provider }
func (ks *serverKeyStore) AuthRole(authid string) (string, error) {
if authid != "jdoe" {
return "", errors.New("no such user: " + authid)
}
return ks.role, nil
}
Then configure the router:
crAuth := auth.NewCRAuthenticator(&serverKeyStore{"static"}, time.Second)
config := &router.RouterConfig{
RealmConfigs: []*router.RealmConfig{
{
URI: wamp.URI("nexus.test.auth"),
Authenticators: []auth.Authenticator{crAuth},
},
}
nxr, err = router.NewRouter(routerConfig, nil)
The new authenticator takes care of all the rest: Creates challenge string, composes CHALLENGE message and sends to client, gets key from KeyStore, computes HMAC-SH265 over challenge string with user's key, compares computed sig to sig sent in challenge response.
A ticket authenticator is basically the same, and can use the same KeyStore
instance. The KeyStore.AuthKey()
can look at the authid
and authmethod
to determine what key to return. So that same method can return CR keys or tickets depending on authmethod
.
The nexus client library contains logic for working with challenge-response authentication. This includes any challenge-response authentication, and is not limited to the particular implementation that is included with the router auth package.
To implement a nexus client that uses WAMP CR authentication, define a function that is called when a CHALLENGE is received:
func clientAuthFunc(c *wamp.Challenge) (string, wamp.Dict) {
// Get user password and return signature.
password := AskUserPassoword()
// Sign challenge with key made using password with PBKDF2.
return crsign.RespondChallenge(password, c, nil), wamp.Dict{}
}
The function crsign.RespondChallenge
is used by clients to sign the challenge string contained in the CHALLENGE message using the given password. This handles computing a derived key from the password using PBKDF2.
After defining the auth handler function, configure a client to use it:
cfg := ClientConfig{
Realm: "nexus.test.auth",
HelloDetails: wamp.Dict{
"authid": "jdoe",
},
AuthHandlers: map[string]AuthFunc{
"wampcra": clientAuthFunc,
},
Logger: logger,
}
client, err := ConnectNet(routerAddress, cfg)
- Home
- Introduction
- Developer Reference Guide
- Operational Information
- System Design
- Additional Information