Hi Darko,
I think there is few things you can improve here.
You could grab JWT out of HTTP headers and add it to Nameko's worker
context data. Once you do that, when you make rpc calls to any downstream
services context will travel with requests and you won't have to
specifically pass it as method parameters.
Grab Http Authorization Header and add it to context:
from nameko.web.server import WebServer as BaseWebServer
from nameko.web.handlers import HttpRequestHandler as BaseHttpRequestHandler
class WebServer(BaseWebServer):
def context_data_from_headers(self, request):
context_data = super().context_data_from_headers(request)
context_data['authorization'] = self.get_auth_token(request)
return context_data
@staticmethod
def get_auth_token(request):
auth = request.headers.get('Authorization', None)
if not auth:
return
parts = auth.split()
if len(parts) != 2:
raise BadRequest(
'Authorization header must be auth-scheme + \s + auth-param'
)
return {'scheme': parts[0], 'param': parts[1]}
class HttpEntrypoint(BaseHttpRequestHandler):
server = WebServer()
http = HttpEntrypoint.decorator
Use http decorator above as your default @http decorator in your gateway
service
Then you would want to combine it with some sort of auth dependency that
will read and validate JWT. This can be shared dependency that gateway and
all downstream services use:
import jwt
from nameko.extensions import DependencyProvider
class Auth(DependencyProvider):
def get_dependency(self, worker_ctx):
self.secret = 'secretive_secret' # Grab it from config
self.jwt = None
auth = self.worker_ctx.data.get('authorization', None)
if auth and auth['scheme'].lower() == 'bearer':
self.jwt = auth['param']
def decode_jwt(self):
"""Decode a JWT using the given secret and algorithm."""
return jwt.decode(
self.jwt, self.secret, algorithm='HS256', issuer='auth'
)
Then use it in your service:
from . import Auth, http
class MyService:
name = 'my-service'
auth = Auth()
@http('GET', '/')
def get_something(self, request):
jwt_payload = self.auth.decode_jwt()
Now if you make rpc call from within any method in your service it will
carry JWT token to downstream services.
JWT's payload should contain all the authorization info like roles, so
additional calls to auth service should not be required.
Hope this helps.
Jakub
···
On Monday, 27 November 2017 14:23:10 UTC, darko....@gmail.com wrote:
Hello!
I started to play with nameko.
I made one rpc service with sqlite as backend,
one http gateway service (as in nameko-examples)
and one rpc auth service which generates jwt token.
gateway service has auth endpoint which calls auth service authenticate
(username, password) and returns token.
Other gateway endpoint methods call the other rpc service, I send token
in http header and then pass that token to rpc service methods as explicit
method parameter.
rpc service then checks if token is valid and if specified role is granted
for the operation, best by calling auth service.
Is there a better way of doing something like that, token authentication
and authorization?
Darko