Open goldcode88 opened 6 years ago
This is definitely something I need provide both examples and additional documentation for. Until then, probably the best help is to look at some of the test code.
Client that tests simple CR auth handler: https://github.com/gammazero/nexus/blob/master/aat/auth_test.go#L28
On the server side, a very simple CRAuthenticator is defined, and given a KeyStore
:
https://github.com/gammazero/nexus/blob/master/aat/main_test.go#L105-L108
This is then provided to the server:
https://github.com/gammazero/nexus/blob/master/aat/main_test.go#L127
For a ticket authenticator, you can create your own or use the skeleton TicketAuthenticator
provided with nexus (it is just a type of CRAuthenticator). Create a new TickerAuthenticator: https://github.com/gammazero/nexus/blob/master/router/auth/ticket.go#L23
...and supply a KeyStore
implementation to return the user info from where your application keeps it.
Here is a unit test that provides a ticket authenticator and a CR authenticator: https://github.com/gammazero/nexus/blob/master/router/auth/crauth_test.go#L116
The AuthKey
method of the KeyStore
returns the ticket:
https://github.com/gammazero/nexus/blob/master/router/auth/crauth_test.go#L37
I will provide some examples and docs very soon.
Consider using TLS Generally, due to the need to protect ticket data, TLS is used to secure the client-server connections. If TLS is already in place, then the server can be configured to only trust certain client certificates. Doing that may remove the need to implement CR/Ticket authentication.
In our advanced router (to be open sourced soon) there is dynamic ticket authentication, as well as TLS authentication using a custom PKI, maybe you want to use this...
@martin31821 I would be very interested to see how your authentication system fits with nexus.
I think the current ticket/CR authentication interface could be improved and made much easier to work with. TLS support is provided, but is basically what the golang stdlib provides, so having something that is better integrated into the rest of the auth stuff could be a good improvement.
I'lll see if I can get this into a good shape within the next week :) should work, we have currently docker images which are production ready
@goldcode88 It looks like there is one thing nexus is missing to be able to provide dynamic ticket authentication as described in Crossbar. That is specifically the ability to make the ticket available in the session details after authentication success. If that is done, the the ticket can be used in the authorizer for the authorization of each message. I will fix this!
All of the other information available to Crossbar's dynamic authorization is also available in nexus. If you set EnableRequestCapture
in the WebsocketServer
then the authorizer will have access to all information from the websocket HTTP upgrade request.
@gammazero @martin31821 Thanks! I have implemented wampcra just now. Autobahn js client can connect to nexus server by wampcra authmethods.
"wampcra": {
"type": "static",
"users": {
"authenticator": {
"secret": "******************",
"role": "authenticator"
},
"usermanagement": {
"secret": "****************",
"role": "backend"
}
}
}
I'll try to implement dynamic ticket authentication after your fix.
Just pushed it: https://github.com/EmbeddedEnterprises/autobahnkreuz. However, docs are still lacking, we're working on it. Docker image is available on docker hub, feel free to play with it.
Thanks. wampcra's config is a little complex. I change testKeyStore to CraKeyStore. CraKeyStore is compatible with crossbar's wampcra model.
type testKeyStore struct {
provider string
secret string
ticket string
cookie *http.Cookie
authByCookie bool
}
// new struct
type CraKeyStore struct {
provider string
users map[string]CraUsers
}
type CraUsers struct {
role string
secret string
ticket string
cookie *http.Cookie
authByCookie bool
}
By the way, Crossbar's wampcra model has a problem. It can't support the following request.
"wampcra": [{
"type": "static",
"users": {
"authenticator": {
"secret": "******************",
"role": "authenticator"
},
"usermanagement": {
"secret": "****************",
"role": "backend"
}
}
},
{
"type": "dynamic",
... ...
}
]
Maybe nexus is easy to implement the model
One note of caution... If putting ticket into session details, then it will probably be necessary to enable MetaStrict
in the RealmConfig. At this point I am thinking that making MetaStrict=true
be the default/only behavior and if it is necessary for additional values from the session meta API, then explicitly list these in MetaIncludeSessionDetails
.
@martin31821 The autobahnkreuz
API looks like it will make things simpler for the user. I see that your AnonymousAuth
is providing a list of authroles:
https://github.com/EmbeddedEnterprises/autobahnkreuz/blob/master/auth/anon.go#L15
Is that something new in the WAMP spec or is this specific to your router?
I would like to integrate DynamicTicketAuth
directly into nexus, if that is alright.
I still need a way to return the ticketObj
, as mentioned to @goldcode88, so that it can be put into the session details. I could stash it in the Welcome.Details
, under a special key that gets removed before the Welcome
message is sent to the client, but that seems like a huge hack. I do not want to change the interface and break backward compatibility. I may need to create a place where extra details can be stored and retrieved later by the router, and provide additional API.
For the first part: the spec states that the authrole should be a string, but the session details are specified as dictionary, so any router should tolerate the list (this is what we tested). Basically it allows us to add features to our application with different authroles at runtime and (re-) assign privileges. I'd also like to keep support for list of authroles within nexus, if that's fine for you @gammazero.
All of our authproviders return lists of authroles. You can integrate the dynamic ticket auth into nexus, however our endpoints has not the same signature that is used in the crossbar router (that was changed in order to support keep-me-logged-in tokens).
I also think that crossbar does not store the ticket object anywhere within the router, since its only purpose is to assign authid/authrole to the client. IMHO storing the user passwords (==token) within the router seems like a security issue to me.
Edit: Our primary motivation to write autobahnkreuz was to provide a router which is super easy to use, solves real applications problems (broken binary serialization, keep-me-logged-in, easy setup of TLS between your microservices, integration into any existing authentication providers, feature based procedure access etc.)
@martin31821 Yes, certainly want keep support for list of authroles. My concern was was about what what to return in session meta events: wamp.session.get
specifically calls for authrole to be returned as string. What do you return?
https://wamp-proto.org/static/rfc/draft-oberstet-hybi-crossbar-wamp.html#wampsessionget
The current implementation just returns the list, which is exactly what is desired. Maybe It would be feasible to add this to the spec, but I don't know what the maintainers think of this...
@martin31821 Maybe there is a why to have it both ways? The session details could contain two different items: authrole
and authroles
. The first, authrole
, would be the "effective" authrole and the second would be all the authroles that the client has membership in. This would be similar to the Unix group concept:
> id
uid=1001(ajg) gid=1001(ajg) groups=1001(ajg),0(wheel),20(staff)
An administrative meta procedure (wamp.modify.session_details
perhaps) could be used to set the effective authrole, much like the Unix newgrp
command.
@gammazero What's the advantage of having authrole
and authroles
? An authorizer would need to know both values anyway and it adds more complexity into the router implementation. Or do you think of any difference between the "primary" role and the other roles within the authroles
dict?
For now, I'd just keep the implementation as-is...
@martin31821 Yes, primary vs others is what I had in mind. Anyway, I think the current implementation is best since it does not force the session details to be any particular type, as long as they serialize. This allows whatever flexibility the router implementer needs.
how to implement ticket dynamic? "user.token.authenticate.d10" is provided by client in autobahn.py. In nexus, I think "user.token.authenticate.d10" should be implemented in nexusd router. But no example can be referenced.
crossbar.io config.json partially.
"auth": { "anonymous": { "type": "static", "role": "public" }, "ticket": { "type": "dynamic", "authenticator": "user.token.authenticate.d10" }, "wampcra": { "type": "static", "users": { "authenticator": { "secret": "**", "role": "authenticator" }, "usermanagement": { "secret": "****", "role": "backend" } } } }