As expected by the HTTP specification, token is extracted from Authorization
header and must be prefixed with Bearer
.
Token will then be validated and in case it is valid, you will be able to access the raw token (as string) and the decoded token body (as dictionary).
Provides a Starlette authentication backend: layabauth.starlette.OAuth2IdTokenBackend
.
3 arguments are required:
- The JWKs URI as defined in .well-known.
- Azure Active Directory:
https://sts.windows.net/common/discovery/keys
- Microsoft Identity Platform:
https://sts.windows.net/common/discovery/keys
- A callable to create the authenticated user based on received token.
- A callable to returns authenticated user scopes based on received token.
Below is a sample Starlette
application with an endpoint requesting a Microsoft issued OAuth2 token.
import starlette.applications
from starlette.authentication import SimpleUser, requires
from starlette.middleware import Middleware
from starlette.middleware.authentication import AuthenticationMiddleware
from starlette.responses import PlainTextResponse
import layabauth.starlette
backend = layabauth.starlette.OAuth2IdTokenBackend(
jwks_uri="https://sts.windows.net/common/discovery/keys",
create_user=lambda token, token_body: SimpleUser(token_body["name"]),
scopes=lambda token, token_body: token_body["scopes"]
)
app = starlette.applications.Starlette(middleware=[Middleware(AuthenticationMiddleware, backend=backend)])
@app.route("/my_endpoint")
@requires('my_scope')
async def my_endpoint(request):
return PlainTextResponse(request.user.display_name)
Provides a decorator layabauth.flask.requires_authentication
to ensure that, in a context of a Flask
application, a valid OAuth2 token was received.
The JWKs URI as defined in .well-known is the only required argument.
- Azure Active Directory:
https://sts.windows.net/common/discovery/keys
- Microsoft Identity Platform:
https://sts.windows.net/common/discovery/keys
If validation fails, an werkzeug.exceptions.Unauthorized
exception is raised.
Otherwise token is stored in flask.g.token
and decoded token body is stored in flask.g.token_body
.
Decorator works fine on flask-restplus
methods as well.
Below is a sample Flask
application with an endpoint requesting a Microsoft issued OAuth2 token.
import flask
import layabauth.flask
app = flask.Flask(__name__)
@app.route("/my_endpoint")
@layabauth.flask.requires_authentication("https://sts.windows.net/common/discovery/keys")
def my_endpoint():
# Optional, ensure that the appropriates scopes are provided
layabauth.flask.requires_scopes(lambda token, token_body: token_body["scopes"], "my_scope")
# Return the content of the name entry within the decoded token body.
return flask.Response(flask.g.token_body["name"])
app.run()
You can generate OpenAPI 2.0 security
definition thanks to layabauth.authorizations
.
You can generate OpenAPI 2.0 method security
thanks to layabauth.method_authorizations
Authentication can be mocked using layabauth.testing.auth_mock
pytest
fixture.
token_body
pytest
fixture returning the decoded token body used in tests must be provided.
jwks_uri
pytest
fixture returning the jwks_uri used in tests must be provided.
from layabauth.testing import *
@pytest.fixture
def jwks_uri():
return "https://sts.windows.net/common/discovery/keys"
@pytest.fixture
def token_body():
return {"name": "TEST@email.com", "scopes": ["my_scope"]}
def test_authentication(auth_mock, client):
response = client.get("/my_endpoint", headers={"Authentication": "Bearer mocked_token"})
assert response.text == "TEST@email.com"
- python 3.7+ must be installed
- Use pip to install module:
python -m pip install layabauth