Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
A cloud first service for key to JWT authentication library and server written in Python 3.
A cloud first service for key to JWT authentication library and server written in Python 3.
JWThenticator was written for client authentication in micro-services architectures with usage of API gateways in mind.
Although there are multiple open-source projects for authenticating users in exchange for JWT (json web token), we couldn't find any project that fit our need for a key based authentication for our clients. This is beneficial for any client authentication and more specifically for IoT.
The service is stateless, Docker first service for cloud authentication, but can generally be used for any key to JWT authentication and in multiple different architectures (see example below).
pip install jwthenticator
To run as a server you can run: python3 -m jwthenticator.server
.
Make sure to configure the proper database to be used via the environment variables exposed in jwthenticator/consts.py file.
By default PostgreSQL is used and a basic local config setup is:
export DB_USER="my-postgres-user"
export DB_PASS="my-postgres-pass"
Note - if RSA keys are not provided (via the environment variables RSA_PUBLIC_KEY
+ RSA_PRIVATE_KEY
or RSA_PUBLIC_KEY_PATH
+ RSA_PRIVATE_KEY_PATH
), a new RSA pair will be generated every time the systems goes up.
docker pull clarotyltd/jwthenticator
docker run -p 8080:8080 clarotyltd/jwthenticator
A database is needed to be linked or configured to the image.
See examples/docker-compose.yml for a full example, run it using:
cd examples
docker-compose up
The project uses poetry for dependency management and packaging.
To run from source clone project and:
pip install poetry
poetry install
For full examples see the examples folder.
To make it easier to work agains a JWThenticator protected server (either directly or via API gateway), a client class is provided.
The Client
class handles auth state management against JWThenticator. It handles JWthenticator responses for you, performs authentication for you, and JWT refresh when needed.
It exposes a request_with_auth
function (and the simpler get_with_auth
and post_with_auth
) that manages all interactions against the secured service and the JWThenticator itself for you.
Example usage:
from uuid import uuid4
from jwthenticator.client import Client
identifier = uuid4()
client = Client("https://my-jwthenticator-host/", identifier, key="my-awesome-key")
response = await client.get_with_auth("https://my-secure-server/")
Although JWThenticator was designed with an API gateway in mind, it can be used to authenticate server endpoints directly.
For easy usage with an aiohttp Python server you can do the following:
from aiohttp import web
from jwthenticator.server_utils import authenticate
app = web.Application()
@authenticate("https://my-jwthenticator-host/")
async def secure_index(request: web.Request) -> web.Response:
return "Secure hello world!"
app.add_routes([web.get("/", secure_index)])
web.run_app(app)
A visual example on how JWThenticator is and can be used.
Additional ones can be found in docs folder.
Generated from docs/api_gateway_architecture_diagram.py
Generated from docs/api_gateway_flow.diag
There are 3 key components to JWThenticator:
Keys that are registered against the service and can then be used for authentication.
All keys are registered to the database, have an expiration time (change default of 30 minutes using the env var KEY_EXPIRY
in seconds), identifier of the registrant and some other metadata stored about them.
The identifier is usefull if a key needs to be linked later to a specific server or route.
Since JWTs are short lived and keys should be kept safe, an intermediate method is needed so we don't have a long lived JWTs or use our secret key every 30 minutes (by default). This is where refresh token come into play.
Refresh tokens are received from a successfull authentication and are used for receiving a new JWTs after they expire.
They are recoreded in the database, have an expiration time (change default of 60 days using the env var REFRESH_TOKEN_EXPIRY
in seconds) and some other metadata stored about them.
You can check out jwthenticator/models.py to see what data is stored in the database.
The industry standard JWT (RFC 7519). The JWT is used for verification against an API gateway, JWThenticator itself, or any service / code you use for you auth verification.
The JWTs are short lived (as they should be) with a configurable lease time via JWT_LEASE_TIME
env var.
Additionaly, similarly to the keys we use a UUID identifier in the authentication process and store it in the JWT's payload. This is useful for better client identification or smarter k8s routing.
DISABLE_EXTERNAL_API
or DISABLE_INTERNAL_API
env vars. This is very important when running the service in production environments, you don't want to expose the key registration to the general public :)./jwks
API call./validate_request
API call.dataclass
es and validated using marshmallow_dataclass, see schemas.py.FAQs
A cloud first service for key to JWT authentication library and server written in Python 3.
We found that jwthenticator demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.