I'm currently trying to implement a user notification system using Websockets via Crossbar/Autobahn. I have done multiple tests and gone through the documentation, however, I'm not sure if there's a solution to having the following workflow work:
crossbar
instance. com.example.notifications.user.23
or com.example.user.23.notifications'. Where
23` is the user id. For step 3, I can't tell if the current support auth methods have what I need. Ideally, I would like an auth method which I can customize (in order to implement a JWT authenticator within Crossbar) that I can apply to a URI pattern, but NOT give access to the entire pattern to the subscribing user. This is partially solved by the dynamic auth methods, but is missing the latter half:
For example (my ideal workflow):
com.example.user.23.notifications
.com.example.user..notifications
(wildcard pattern in http://crossbar.io/docs/Pattern-Based-Subscriptions/)com.example.user.23.notifications
. Is the above achievable in a simple way? From what I can tell, it may only be possible if I somehow generate a .crossbar/config.json
which contains URI permutations of all user ids...and automatically generate a new config for each new user -- which is completely not a reasonable solution.
Any help is appreciated!
Use authorizer.
See http://crossbar.io/docs/Authorization/#dynamic-authorization
Register a dynamic authorizer for the user role that session was assigned when joining/authenticating:
{
"name": "authorizer",
"permissions": [
{
"uri": "com.example.authorize",
"register": true
}
]
},
{
"name": "authenticator",
"permissions": [
{
"uri": "com.example.authenticate",
"register": true
}
]
},
{
"name": "user",
"authorizer": "com.example.authorize"
},
...
"components": [
{
"type": "class",
"classname": "example.AuthenticatorSession",
"realm": "realm1",
"role": "authenticator",
"extra": {
"backend_base_url": "http://localhost:8080/ws"
}
},
{
"type": "class",
"classname": "example.AuthorizerSession",
"realm": "realm1",
"role": "authorizer"
}
]
Write a class
class AuthorizerSession(ApplicationSession):
@inlineCallbacks
def onJoin(self, details):
print("In AuthorizerSession.onJoin({})".format(details))
try:
yield self.register(self.authorize, 'com.example.authorize')
print("AuthorizerSession: authorizer registered")
except Exception as e:
print("AuthorizerSession: failed to register authorizer procedure ({})".format(e))
def authorize(self, session, uri, action):
print("AuthorizerSession.authorize({}, {}, {})".format(session, uri, action))
if session['authrole'] == u'backend': # backnend can do whatever
return True
[Authorization logic here]
return authorized