From bc4419ccebbb4d9cecc6659264adc3dd1f28e4e0 Mon Sep 17 00:00:00 2001 From: dusktreader Date: Thu, 24 Aug 2023 21:53:55 +0000 Subject: [PATCH] deploy: 212a5eaad14ffa44b585aab562bd62b647a39176 --- index.html | 2 +- search/search_index.json | 2 +- sitemap.xml.gz | Bin 127 -> 127 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 53cae66..6e45871 100644 --- a/index.html +++ b/index.html @@ -430,7 +430,7 @@
-

An Omnivector Solutions initiative

+

An Omnivector initiative

omnivector-logo

Armasec Documentation

diff --git a/search/search_index.json b/search/search_index.json index f15134c..0da7079 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"

An Omnivector Solutions initiative

"},{"location":"#armasec-documentation","title":"Armasec Documentation","text":"

Armasec is a security package that simplifies OIDC security for FastAPI apps.

"},{"location":"#overview","title":"Overview","text":"

Adding a security layer on top of your API can be difficult, especially when working with an OIDC platform. It's hard enough to get your OIDC provider configured correctly. Armasec aims to take the pain out of securing your APIs routes.

Armasec is an opinionated library that attemtps to use the most obvious and commonly used workflows when working with OIDC and making configuration as simple as possible.

When using the Armasec helper class, you only need two configuration settings to get going:

  1. Domain: the domain of your OIDC provider
  2. Audience: An optional setting that restricts tokens to those intended for your API.

That's it! Once you have those settings dialed in, you can just worry about checking the permissions scopes of your endpoints

"},{"location":"#inception","title":"Inception","text":"

Armasec was originally developed as an internal tool to add security in tandem with Auth0. Since its inception, Armasec has been used in production with both Auth0 and Keycloak. It should work with other OIDC providers, assuming they are configured correctly, but the developers of Armasec make no guarantees for other platforms.

"},{"location":"getting_started/","title":"Getting Started","text":""},{"location":"getting_started/#requirements","title":"Requirements","text":""},{"location":"getting_started/#installation","title":"Installation","text":"

The armasec package can be installed like any other python package. It is available on PyPI

"},{"location":"getting_started/#poetry","title":"Poetry","text":"

To install via poetry, simply run:

poetry add armasec\n
"},{"location":"getting_started/#pip","title":"Pip","text":"

To install directly with pip, simply run:

pip install armasec\n
"},{"location":"minimal_example/","title":"Minimal Example","text":"

The following is a minimal example of how to configure your API to enforce security on endpoints using tokens issued by Auth0.

First, create a file named example.py with the following contents:

example.py
import os\nfrom armasec import Armasec\nfrom fastapi import FastAPI, Depends\napp = FastAPI()\narmasec = Armasec(\ndomain=os.environ.get(\"ARMASEC_DOMAIN\"),\naudience=os.environ.get(\"ARMASEC_AUDIENCE\"),\n)\n@app.get(\"/stuff\", dependencies=[Depends(armasec.lockdown(\"read:stuff\"))])\nasync def check_access():\nreturn dict(message=\"Successfully authenticated!\")\n

In this example, you would have set two environment variables for your project settings:

When you run your app, access to the /stuff endpoint would be restricted to authenticated users whose access tokens carried the permission scope \"read:stuff\".

For a step-by-step walk-through of how to set up Auth0 for the minimal example, see the \"Getting Started with Auth0\" page.

The above code can be found in examples/basic.py.

"},{"location":"reference/","title":"Reference","text":""},{"location":"reference/#armasec.armasec","title":"armasec.armasec","text":"

This module defines the core Armasec class.

"},{"location":"reference/#armasec.armasec.Armasec","title":"Armasec","text":"

This is a factory class for TokenSecurity. It allows the machinery of armasec to be initialized correctly so that the factory method lockdown can initialize new instances of TokenSecurity to protect routes. It's not essential to use Armasec to secure routes, but it cuts down on the boilerplate necessary to do so.

"},{"location":"reference/#armasec.armasec.Armasec.__init__","title":"__init__","text":"
__init__(\ndomain_configs: Optional[List[DomainConfig]] = None,\ndebug_logger: Optional[Callable[[str], None]] = noop,\ndebug_exceptions: bool = False,\n**kargs: bool\n)\n

Stores initialization values for the TokenSecurity. All are passed through.

Parameters:

Name Type Description Default domain_configs Optional[List[DomainConfig]]

List of domain configuration to authenticate the tokens against.

None debug_logger Optional[Callable[[str], None]]

A callable, that if provided, will allow debug logging. Should be passed as a logger method like logger.debug

noop debug_exceptions bool

If True, raise original exceptions. Should only be used in a testing or debugging context.

False kargs

Arguments compatible to instantiate the DomainConfig model.

{}"},{"location":"reference/#armasec.armasec.Armasec.lockdown","title":"lockdown cached","text":"
lockdown(\n*scopes: str,\npermission_mode: PermissionMode = PermissionMode.ALL\n) -> TokenSecurity\n

Initialize an instance of TokenSecurity to lockdown a route. Uses memoization to minimize the number of TokenSecurity instances initialized. Applies supplied permission_mode when checking token permssions against TokenSecurity scopes.

Parameters:

Name Type Description Default scopes str

A list of scopes needed to access the endpoint.

() permissions_mode

If \"ALL\", all scopes listed are required for access. If \"SOME\", only one of the scopes listed are required for access.

required"},{"location":"reference/#armasec.armasec.Armasec.lockdown_all","title":"lockdown_all","text":"
lockdown_all(*scopes: str) -> TokenSecurity\n

Initialize an instance of TokenSecurity to lockdown a route. Uses memoization to minimize the number of TokenSecurity instances initialized. Requires all the scopes in the TokenSecurity instance to be included in the token permissions. This is just a wrapper around lockdown() with default permission_mode and is only included for symmetry.

Parameters:

Name Type Description Default scopes str

A list of the scopes needed to access the endpoint. All are required.

()"},{"location":"reference/#armasec.armasec.Armasec.lockdown_some","title":"lockdown_some","text":"
lockdown_some(*scopes: str) -> TokenSecurity\n

Initialize an instance of TokenSecurity to lockdown a route. Uses memoization to minimize the number of TokenSecurity instances initialized. Requires at least one permission in the token to match a scope attached to the TokenSecurity instance.

Parameters:

Name Type Description Default scopes str

A list of the scopes needed to access the endpoint. Only one is required.

()"},{"location":"reference/#armasec.exceptions","title":"armasec.exceptions","text":""},{"location":"reference/#armasec.exceptions.ArmasecError","title":"ArmasecError","text":"

Bases: buzz.Buzz

A custom exception class used for checking conditions and handling other exceptions.

Attributes:

Name Type Description status_code int

The HTTP status code indicated by the error. Set to 400.

"},{"location":"reference/#armasec.exceptions.AuthenticationError","title":"AuthenticationError","text":"

Bases: ArmasecError

Indicates a failure to authenticate and decode jwt.

Attributes:

Name Type Description status_code int

The HTTP status code indicated by the error. Set to 401.

"},{"location":"reference/#armasec.exceptions.AuthorizationError","title":"AuthorizationError","text":"

Bases: ArmasecError

Indicates that the provided claims don't match the claims required for a protected endpoint.

Attributes:

Name Type Description status_code int

The HTTP status code indicated by the error. Set to 403.

"},{"location":"reference/#armasec.openid_config_loader","title":"armasec.openid_config_loader","text":"

This module provides the OpenidConfigLoader which is used to load openid-configuration data from an OIDC provider.

"},{"location":"reference/#armasec.openid_config_loader.OpenidConfigLoader","title":"OpenidConfigLoader","text":""},{"location":"reference/#armasec.openid_config_loader.OpenidConfigLoader.config","title":"config property","text":"
config: OpenidConfig\n

Retrive the openid config from an OIDC provider. Lazy loads the config so that API calls are deferred until the coniguration is needed.

"},{"location":"reference/#armasec.openid_config_loader.OpenidConfigLoader.jwks","title":"jwks property","text":"
jwks: JWKs\n

Retrives JWKs public keys from an OIDC provider. Lazy loads the jwks so that API calls are deferred until the jwks are needed.

"},{"location":"reference/#armasec.openid_config_loader.OpenidConfigLoader.__init__","title":"__init__","text":"
__init__(\ndomain: str,\nuse_https: bool = True,\ndebug_logger: Optional[Callable[..., None]] = None,\n)\n

Initializes a base TokenManager.

Parameters:

Name Type Description Default secret

The secret key needed to decode a token

required domain str

The domain of the OIDC provider. This is to construct the openid-configuration url

required use_https bool

If falsey, use http instead of https (the default).

True debug_logger Optional[Callable[..., None]]

A callable, that if provided, will allow debug logging. Should be passed as a logger method like logger.debug

None"},{"location":"reference/#armasec.openid_config_loader.OpenidConfigLoader.build_openid_config_url","title":"build_openid_config_url staticmethod","text":"
build_openid_config_url(\ndomain: str, use_https: bool = True\n)\n

Builds a url for an openid configuration given a domain.

Parameters:

Name Type Description Default domain str

The domain of the OIDC provider for which to build a URL

required use_https bool

Use https for the URL by default. If falsey, use http instead.

True"},{"location":"reference/#armasec.pytest_extension","title":"armasec.pytest_extension","text":"

This module provides a pytest plugin for testing.

"},{"location":"reference/#armasec.pytest_extension.build_mock_openid_server","title":"build_mock_openid_server","text":"
build_mock_openid_server(\ndomain, openid_config, jwk, jwks_uri\n) -> Callable[\n[str, OpenidConfig, JWK, str], _GeneratorContextManager\n]\n

Provide a fixture that returns a context manager that mocks opend-config routes.

Parameters:

Name Type Description Default domain

The domain of the openid server to mock.

required openid_config

The config to return from the mocked config route.

required jwk

The jwk to return from the mocked jwk route.

required jwks_uri

The URL of the jwks route to mock.

required

Returns:

Type Description Callable[[str, OpenidConfig, JWK, str], _GeneratorContextManager]

A context manager that, while active, mocks the openid routes needed by Armasec.

"},{"location":"reference/#armasec.pytest_extension.build_rs256_token","title":"build_rs256_token","text":"
build_rs256_token(\nrs256_private_key, rs256_iss, rs256_sub, rs256_kid\n)\n

Provide a fixture that returns a helper method that can build a JWT.

The JWT is signed with the private key provided by the rs256_private_key.

Parameters:

Name Type Description Default rs256_private_key

An implicit fixture parameter.

required rs256_iss

An implicit fixture parameter.

required rs256_sub

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.mock_openid_server","title":"mock_openid_server","text":"
mock_openid_server(\nrs256_domain,\nrs256_openid_config,\nrs256_jwk,\nrs256_jwks_uri,\n)\n

Provide a fixture that mocks an openid server using the extension fixtures.

Parameters:

Name Type Description Default rs256_domain

An implicit fixture parameter.

required rs256_openid_config

An implicit fixture parameter.

required rs256_jwk

An implicit fixture parameter.

required rs256_jwks_uri

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.rs256_domain","title":"rs256_domain","text":"
rs256_domain()\n

Provide a fixture that returns a domain for use in other fixtures.

The value here doesn't really have anything to do with an actual domain name.

"},{"location":"reference/#armasec.pytest_extension.rs256_domain_config","title":"rs256_domain_config","text":"
rs256_domain_config(rs256_domain)\n

Provide a fixture that returns the DomainConfig model for the default rs256 domain.

Parameters:

Name Type Description Default rs256_domain

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.rs256_iss","title":"rs256_iss","text":"
rs256_iss(rs256_domain)\n

Provide a fixture that returns an issuer claim for use in other fixtures.

Parameters:

Name Type Description Default rs256_domain

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.rs256_jwk","title":"rs256_jwk","text":"
rs256_jwk(rs256_kid)\n

Provide a fixture that returns a JWK for use in other fixtures.

Parameters:

Name Type Description Default rs256_kid

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.rs256_jwks_uri","title":"rs256_jwks_uri","text":"
rs256_jwks_uri(rs256_domain)\n

Provide a fixture that returns a jwks uri for use in other fixtures.

Parameters:

Name Type Description Default rs256_jwks_uri

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.rs256_kid","title":"rs256_kid","text":"
rs256_kid()\n

Provide a fixture that returns a KID header value for use in other fixtures.

"},{"location":"reference/#armasec.pytest_extension.rs256_openid_config","title":"rs256_openid_config","text":"
rs256_openid_config(rs256_iss, rs256_jwks_uri)\n

Provide a fixture that returns an openid configuration for use in other fixtures.

Parameters:

Name Type Description Default rs256_iss

An implicit fixture parameter.

required rs256_jwks_uri

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.rs256_private_key","title":"rs256_private_key","text":"
rs256_private_key()\n

Provide a fixture that returns a pre-generated private key for RS256 hashing in other fixtures.

"},{"location":"reference/#armasec.pytest_extension.rs256_public_key","title":"rs256_public_key","text":"
rs256_public_key()\n

Provide a fixture that returns a pre-generated public key for RS256 hashing in other fixtures.

"},{"location":"reference/#armasec.pytest_extension.rs256_sub","title":"rs256_sub","text":"
rs256_sub()\n

Provide a fixture that returns a sum claim for use in other fixtures.

"},{"location":"reference/#armasec.token_decoder","title":"armasec.token_decoder","text":"

This module provides an abstract base class for algorithmic token decoders

"},{"location":"reference/#armasec.token_decoder.TokenDecoder","title":"TokenDecoder","text":"

Decoder class used to decode tokens given an algorithm and jwks.

"},{"location":"reference/#armasec.token_decoder.TokenDecoder.__init__","title":"__init__","text":"
__init__(\njwks: JWKs,\nalgorithm: str = \"RS256\",\ndebug_logger: Optional[Callable[..., None]] = None,\ndecode_options_override: Optional[dict] = None,\n)\n

Initializes a TokenDecoder.

Parameters:

Name Type Description Default algorithm str

The algorithm to use for decoding. Defaults to RS256.

'RS256' jwks JWKs

JSON web keys object holding the public keys for decoding.

required openid_config

The openid_configuration needed for claims such as 'issuer'.

required debug_logger Optional[Callable[..., None]]

A callable, that if provided, will allow debug logging. Should be passed as a logger method like logger.debug

None decode_options_override Optional[dict]

Options that can override the default behavior of the jwt decode method. For example, one can ignore token expiration by setting this to { \"verify_exp\": False }

None"},{"location":"reference/#armasec.token_decoder.TokenDecoder.decode","title":"decode","text":"
decode(token: str, **claims: str) -> TokenPayload\n

Decode a JWT into a TokenPayload while checking signatures and claims.

Parameters:

Name Type Description Default token str

The token to decode.

required claims

Additional claims to verify in the token.

{}"},{"location":"reference/#armasec.token_decoder.TokenDecoder.get_decode_key","title":"get_decode_key","text":"
get_decode_key(token: str) -> dict\n

Search for a public keys within the JWKs that matches the incoming token.

Compares the token's unverified header against available JWKs. Uses the matching JWK for the decode key. Raise AuthenticationError if matching public key cannot be found.

Parameters:

Name Type Description Default token str

The token to match against available JWKs.

required"},{"location":"reference/#armasec.token_manager","title":"armasec.token_manager","text":"

This module defines a TokenManager that can be used to extract token payloads from request headers.

"},{"location":"reference/#armasec.token_manager.TokenManager","title":"TokenManager","text":"

Handle auth via a TokenDecoder and manage extraction from request headers and serialization into TokenPayload instances.

"},{"location":"reference/#armasec.token_manager.TokenManager.__init__","title":"__init__","text":"
__init__(\nopenid_config: OpenidConfig,\ntoken_decoder: TokenDecoder,\naudience: Optional[str] = None,\ndebug_logger: Optional[Callable[..., None]] = None,\ndecode_options_override: Optional[dict] = None,\n)\n

Initialize a base TokenManager.

Parameters:

Name Type Description Default openid_config OpenidConfig

The openid_configuration needed for claims such as 'issuer'.

required token_decoder TokenDecoder

The decoder used to verify jwts

required audience Optional[str]

An optional audience to check in decoded tokens.

None debug_logger Optional[Callable[..., None]]

A callable, that if provided, will allow debug logging. Should be passed as a logger method like logger.debug

None decode_options_override Optional[dict]

Options that can override the default behavior of the jwt decode method. For example, one can ignore token expiration by setting this to { \"verify_exp\": False }

None"},{"location":"reference/#armasec.token_manager.TokenManager.extract_token_payload","title":"extract_token_payload","text":"
extract_token_payload(\nheaders: Union[Headers, dict]\n) -> TokenPayload\n

Retrieve a token from a request header and decode it into a TokenPayload.

Parameters:

Name Type Description Default headers Union[Headers, dict]

The headers from which to retrieve a JWT.

required"},{"location":"reference/#armasec.token_manager.TokenManager.unpack_token_from_header","title":"unpack_token_from_header","text":"
unpack_token_from_header(\nheaders: Union[Headers, dict]\n) -> str\n

Unpack a JWT from a request header.

Parameters:

Name Type Description Default headers Union[Headers, dict]

The headers from which to unpack a JWT.

required"},{"location":"reference/#armasec.token_payload","title":"armasec.token_payload","text":"

This module defines a pydantic schema for the payload of a jwt.

"},{"location":"reference/#armasec.token_payload.TokenPayload","title":"TokenPayload","text":"

Bases: BaseModel

A convenience class that can be used to access parts of a decoded jwt.

Attributes:

Name Type Description sub str

The \"sub\" claim from a JWT.

permissions List[str]

The permissions claims extracted from a JWT.

expire datetime

The \"exp\" claim extracted from a JWT.

client_id str

The \"azp\" claim extracted from a JWT.

"},{"location":"reference/#armasec.token_payload.TokenPayload.to_dict","title":"to_dict","text":"
to_dict()\n

Convert a TokenPayload to the equivalent dictionary returned by jwt.decode().

"},{"location":"reference/#armasec.token_security","title":"armasec.token_security","text":"

This module defines a TokenSecurity injectable that can be used enforce access on FastAPI routes.

"},{"location":"reference/#armasec.token_security.ManagerConfig","title":"ManagerConfig","text":"

Bases: BaseModel

Model class to represent a TokenManager instance and its domain configuration for easier mapping

Attributes:

Name Type Description manager TokenManager

The TokenManager instance to use for decoding tokens.

domain_config DomainConfig

The DomainConfig for the openid server.

"},{"location":"reference/#armasec.token_security.PermissionMode","title":"PermissionMode","text":"

Bases: AutoNameEnum

Endpoint permissions.

Attributes:

Name Type Description ALL

Require all listed permissions.

SOME

Require at least one of the listed permissions.

"},{"location":"reference/#armasec.token_security.TokenSecurity","title":"TokenSecurity","text":"

Bases: APIKeyBase

An injectable Security class that returns a TokenPayload when used with Depends().

Attributes:

Name Type Description manager Optional[TokenManager]

The TokenManager to use for token validation and extraction.

"},{"location":"reference/#armasec.token_security.TokenSecurity.__call__","title":"__call__ async","text":"
__call__(request: Request) -> TokenPayload\n

This method is called by FastAPI's dependency injection system when a TokenSecurity instance is injected to a route endpoint via the Depends() method. Lazily loads the OIDC config, the TokenDecoder, and the TokenManager if they are not already initialized.

Parameters:

Name Type Description Default request Request

The FastAPI request to check for secure access.

required"},{"location":"reference/#armasec.token_security.TokenSecurity.__init__","title":"__init__","text":"
__init__(\ndomain_configs: List[DomainConfig],\nscopes: Optional[Iterable[str]] = None,\npermission_mode: PermissionMode = PermissionMode.ALL,\ndebug_logger: Optional[Callable[..., None]] = None,\ndebug_exceptions: bool = False,\n)\n

Initializes the TokenSecurity instance.

Parameters:

Name Type Description Default domain_configs List[DomainConfig]

List of domain configuration to authenticate the tokens against.

required scopes Optional[Iterable[str]]

Optional permissions scopes that should be checked

None permission_mode PermissionMode

The PermissionMode to apply in the protected route.

PermissionMode.ALL debug_logger Optional[Callable[..., None]]

A callable, that if provided, will allow debug logging. Should be passed as a logger method like logger.debug

None debug_exceptions bool

If True, raise original exceptions. Should only be used in a testing or debugging context.

False"},{"location":"reference/#armasec.utilities","title":"armasec.utilities","text":"

Provides some utility functions.

"},{"location":"reference/#armasec.utilities.log_error","title":"log_error","text":"
log_error(logger: Callable[..., None], dep: DoExceptParams)\n

Logs an en error with the supplied message, a string representation of the error, and its traceback. If the logger supplied is noop, do nothing. Pass as a partial when using the Buzz handle_errors context manager::

with Buzz.handle_errors(\"Boom!\", do_except=partial(log_error, debug_logger)):\n    do_some_risky_stuff()\n
"},{"location":"reference/#armasec.utilities.noop","title":"noop","text":"
noop(*args, **kwargs)\n

This is a no-op function that...does nothing.

"},{"location":"reference/#armasec.schemas.armasec_config","title":"armasec.schemas.armasec_config","text":"

This module provides a pydantic schema describing Armasec's configuration parameters.

"},{"location":"reference/#armasec.schemas.armasec_config.DomainConfig","title":"DomainConfig","text":"

Bases: BaseModel

This model provides a specification for the input domains to authenticate against. It expects the domain indeed and the audience to refer to.

Attributes:

Name Type Description domain str

The OIDC domain from which resources are loaded.

audience Optional[str]

Optional designation of the token audience.

algorithm str

The Algorithm to use for decoding. Defaults to RS256.

use_https bool

If true, use https for URLs. Otherwise use http

match_keys Dict[str, Union[str, List[Any], Dict[Any, Any], Set[Any], bool, int, float]]

Dictionary of k/v pairs to match in the token when decoding it.

"},{"location":"reference/#armasec.schemas.jwks","title":"armasec.schemas.jwks","text":"

This module provides pydantic schemas for JSON Web Keys.

"},{"location":"reference/#armasec.schemas.jwks.JWK","title":"JWK","text":"

Bases: BaseModel

This Model provides a specification for the objects retrieved from JWK endpoints in OIDC providers. It also assists with validation and item access.

Attributes:

Name Type Description alg str

The algorithm to use for hash validation.

e str

The exponent parameter to use in RS256 hashing

kid str

The \"kid\" claim to uniquely identify the key.

kty str

The \"kty\" claim to identify the type of the key.

n str

The modulus parameter to use in RS256 hashing.

use Optional[str]

The claim that identifies the intended use of the public key.

x5c Optional[List[str]]

The X.509 certificate chain parameter

x5c Optional[List[str]]

The X.509 certificate SHA-1 thumbprint parameter

"},{"location":"reference/#armasec.schemas.jwks.JWKs","title":"JWKs","text":"

Bases: BaseModel

This Model provides a specification for the container object retrieved from JWK endpoints in OIDC providers. It also assists with validation and item access.

Attributes:

Name Type Description keys List[JWK]

The list of JWKs contained within.

"},{"location":"reference/#armasec.schemas.openid_config","title":"armasec.schemas.openid_config","text":"

This module provides a pydantic schema describing openid-configuration data.

"},{"location":"reference/#armasec.schemas.openid_config.OpenidConfig","title":"OpenidConfig","text":"

Bases: BaseModel

Provides a specification for the objects retrieved from openid_configuration endpoint of the OIDC providers. Only includes needed fields for supported Manager instances. Assists with validation and item access.

Attributes:

Name Type Description issuer AnyHttpUrl

The URL of the issuer of the tokens.

jwks_uri AnyHttpUrl

The URI where JWKs can be foun don the OpenID server.

"},{"location":"tutorials/getting_started_with_auth0/","title":"Getting started with Auth0","text":"

This step-by-step walk-through will show you how to get an Auth0 account set up for use with the minimal example.

You will need:

"},{"location":"tutorials/getting_started_with_auth0/#create-auth0-account-tenant","title":"Create Auth0 account tenant","text":"

Navigate to Auth0's homepage, and click Sign Up.

Create a new account (if you don't already have one). It doesn't really matter how you choose to sign up, but I used my google account.

Create a personal account

For this tutorial, just select a \"Personal\" account. You can come back and repeat the process for your company later if you need to.

Select I need advanced settings so that you can choose your tenant name, and click Next to move on to tenant setup.

Select tenant domain

Select your tenant domain. For this tutorial, I will be using \"armasec-tutorial\". Choose your region and click Create Account. The full domain that I will use later is \"armasec-tutorial.us.auth0.com\".

"},{"location":"tutorials/getting_started_with_auth0/#add-your-api-application","title":"Add your API application","text":"

This will set up the Auth0 api endpoints that Auth0 will use to authenticate your users.

Navigate to Applications > APIs

Click Applications -> APIs

Create an API

Click Create API

Fill out API form

Fill out the form. The Name you choose doesn't matter, but for the tutorial, I used \"Armasec Tutorial\". Choose a name for the identifier that makes sense, as this will be the \"Audience\" for your tutorial app. I chose \"https://armasec-tutorial.com\" for this tutorial.

Leave the \"Signing Algorithm\" as \"RS256\". Armasec also supports HS256, but it is not preferred.

Click Create

Enable RBAC Settings

Go to the Settings tab and scroll down to the \"RBAC Settings\"

Activate Enable RBAC and Add Permissions in the Access Token\".

This will include permissions scopes to your users' access tokens.

Click Save

"},{"location":"tutorials/getting_started_with_auth0/#add-your-permissions","title":"Add your permissions","text":"

Next, we will add the permission for the minimal example.

Add a permission

Click on the Permissions tab and add the \"read:stuff\" permission.

"},{"location":"tutorials/getting_started_with_auth0/#grant-your-permission-to-the-test-app","title":"Grant your permission to the test app","text":"

Auth0 provides a \"Machine-to-Machine\" test app for verifying that log in will work. We will grant our \"read:stuff\" permission to tokens provided from this app.

Navigate to Applications

Navigate to Applications -> Applications

Select tutorial test app

Click on Armasec Tutorial (Test Application)

Add permission to test app

Go to the APIs tab and click the drop-down. Select the \"read-stuff\" box in the \"Permissions\" box. Click Update.

"},{"location":"tutorials/getting_started_with_auth0/#start-up-the-example-app","title":"Start up the example app","text":"

Copy the example app to a local source file called \"example.py\".

Start it up with uvicorn:

python -m uvicorn --host 0.0.0.0 example:app\n
"},{"location":"tutorials/getting_started_with_auth0/#try-it-out","title":"Try it out","text":"

Next, we will try to use a test token to call our minimal example's endpoint.

Navigate back to Applications -> APIs, select the Armasec Tutorial, and go to the Test tab.

Copy test access token

Find the \"Response\" box. This contains a token that has been issued by your test application. Click the Copy Token button.

Now, open a browser to \"localhost:8000/docs\"

Swagger page for example

This will show you the auto-generated swagger docs for the example API app. Click on the Authorize button to add the token you copied to the clipboard in the header of requests to the API.

Add access token in Swagger

First, type \"Bearer \" followed by pasting the token from the clipboard into the form and click the Authorize button in the dialog, click Close to dismiss the dialog. Now, all subsequent calls to the API will include a header that looks like:

{\n\"Authorization\": \"Bearer eyJhbGciOi...\"\n}\n

Now, expand the \"GET\" REST operation on the /stuff endpoint and click Try it out.

Try it out

Finally, click Execute to issue the request to the API.

Execute

You should see a response that includes a 200 status code and a response body that includes:

{\n\"message\": \"Successfully authenticated\"\n}\n

Congratulations! You are now using Armasec and Auth0 to authorize requests to your API.

"},{"location":"tutorials/getting_started_with_auth0/#tinker","title":"Tinker","text":"

Now, there are a few things you can do to check out how things work. Try the following things:

"},{"location":"tutorials/getting_started_with_auth0/#send-feedback","title":"Send feedback","text":"

If the above tutorial didn't work as expected, a step needs better clarification, or you have some questions about it, please create an issue on Armasec's GitHub's issues.

"},{"location":"tutorials/getting_started_with_keycloak/","title":"Getting started with Keycloak","text":"

This step-by-step walk-through will show you how to get your Keycloak server set up to work with the minimal example. For this tutorial, I am running Keycloak locally with Docker.

You will need:

"},{"location":"tutorials/getting_started_with_keycloak/#start-your-keycloak-server","title":"Start your Keycloak server","text":"

If you want to try the example locally without an existing Keycloak server, you can start a new one using Docker with the following command:

 docker run keycloak/keycloak:18.0.0 -p 8080:8080 -e KEYCLOAK_ADMIN=\"admin\" -e KEYCLOAK_ADMIN_PASSWORD=\"admin\" start-dev\n

This will start a server who's admin UI is available at localhost:8080.

Open a browser and load the address localhost:8080. Then, click on the \"Administration Console\" to log in.

Log-in to admin console

The sign-in credentials for the admin account are:

Field Value Username admin Password admin

After you log in, you will load the \"Master\" realm.

"},{"location":"tutorials/getting_started_with_keycloak/#set-up-your-master-realm","title":"Set up your \"Master\" realm","text":"

First, we need to change the lifespan for tokens. By default they expire after 1 minute, but that's not so friendly for a tutorial, so we will lengthen the lifespan to 5 minutes.

Go to the \"Tokens\" tab of your \"Master\" realm and set the \"Access Token Lifespan\" to 5 minutes.

Ream settings

Click \"Save\" at the bottom after you change the value. All of the rest of the settings can be left as they are.

"},{"location":"tutorials/getting_started_with_keycloak/#set-up-a-client","title":"Set up a client","text":"

We will need a client that is configured with our permissions. To do this, navigate to the \"Clients\" tab in the nav bar and click the \"Create\" button:

Clients

For this tutorial, we will use the name \"armasec-tutorial\". Click \"Save\" to create the new client.

Create client

Now we need to set the following values for the new client:

Field Value Access Type Confidential Service Accounts Enabled ON Valid Redirect URIs *

The service account produce a token using the client secret over an API request to Keycloak.

Client settings

Next, we need to save the \"Client Secret\" for later when we request a token. Navigate to the \"Credentials\" tab and copy the value found in the \"Secret\" field.

Secrets

Next, we need to create the \"Roles\" that Armasec uses for the \"permissions\" claim inside the tokens. Navigate to the \"Roles\" tab for the client and click the \"Add Role\" button.

Add role

Fill the \"Role Name\" field with \"read:stuff\". There's no need to add a description at this time. Click the \"Save\" button to add the role to the client.

Save role

Next, we need to set up a Mapper that will put the roles inside of the \"permissions\" claim in the issued tokens. Navigate back to the \"armasec-tutorial\" client and open the \"Mappers\" tab. Click the \"Create\" button to add a new mapper.

Mappers

In the form, there's a few things to set:

Field Value Name permissions Mapper Type User Client Role Client ID armasec-tutorial Token Claim Name Permissions Claim JSON Type String

Set the fields as specified above and click the \"Save\" button to create the new mapper

Permissions mapper

Finally, we need to set up an \"Audience\" mapper to set the audience claim in the token that our example app will check for.

Create a new mapper with the following settings:

Field Value Name audience Mapper Type Audience Included Custom Audience http://keycloak.local Add to ID token ON

Click \"Save\" to create the new mapper.

Audience mapper

Now, for the purposes of this tutorial, we will be getting a token via a request with a \"Service Account Role\". We need to add the role we created above to the \"Service Account Role\" so that the token issued later includes the needed permissions.

Navigate to the \"Service Account Roles\" tab. Then, select \"armasec-tutorial\" for the \"Client Roles\" field. Select the \"read:stuff\" role and add it with the \"Add selected >>\" button.

Add role

Now your client should be all set up and ready to go.

"},{"location":"tutorials/getting_started_with_keycloak/#prepare-the-environment","title":"Prepare the environment","text":"

The example FastAPI app requires the \"ARMASEC_DOMAIN\" and \"ARMASEC_AUDIENCE\" environment variables to be set.

We also need to set the \"CLIENT_ID\" and \"CLIENT_SECRET\" for our curl request to Keycloak to get a test token:

export ARMASEC_DOMAIN=localhost:8080/realms/master\nexport ARMASEC_AUDIENCE=http://keycloak.local\nexport CLIENT_ID=armasec-tutorial\nexport CLIENT_SECRET=<your-client-secret>\n
"},{"location":"tutorials/getting_started_with_keycloak/#start-up-the-example-app","title":"Start up the example app","text":"example.py
import os\nfrom armasec import Armasec\nfrom fastapi import FastAPI, Depends\napp = FastAPI()\narmasec = Armasec(\ndomain=os.environ.get(\"ARMASEC_DOMAIN\"),\naudience=os.environ.get(\"ARMASEC_AUDIENCE\"),\nuse_https=False,\n)\n@app.get(\"/stuff\", dependencies=[Depends(armasec.lockdown(\"read:stuff\"))])\nasync def check_access():\nreturn dict(message=\"Successfully authenticated!\")\n

Note in this example that the use_https flag must be set to false to allow a local server using unsecured HTTP.

Copy the example.py app to a local source file called \"example.py\".

Start it up with uvicorn:

python -m uvicorn --host 0.0.0.0 example:app\n
"},{"location":"tutorials/getting_started_with_keycloak/#get-the-test-token","title":"Get the test token","text":"

We will use curl to get an example token to test out our route's security:

curl -d \"client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&grant_type=client_credentials\" -X POST \"http://localhost:8080/realms/master/protocol/openid-connect/token\"\n

If you wish to see metadata about the token (such as its lifespan, you can omit the jq command at the end.

"},{"location":"tutorials/getting_started_with_keycloak/#try-it-out","title":"Try it out","text":"

Open a browser to localhost:8000/docs

Swagger

This will show you the auto-generated swagger docs for the example API app. Click on the Authorize button to add the token you copied to the clipboard in the header of requests to the API.

Authorize

First, type \"Bearer \" followed by pasting the token from the clipboard into the form and click the Authorize button in the dialog, click Close to dismiss the dialog. Now, all subsequent calls to the API will include a header that looks like:

{\n\"Authorization\": \"Bearer eyJhbGciOi...\"\n}\n

Now, expand the \"GET\" REST operation on the /stuff endpoint and click Try it out.

Try it out

Finally, click Execute to issue the request to the API.

Execute

You should see a response that includes a 200 status code and a response body that includes:

{\n\"message\": \"Successfully authenticated\"\n}\n

Congratulations! You are now using Armasec and Auth0 to authorize requests to your API.

"},{"location":"tutorials/getting_started_with_keycloak/#tinker","title":"Tinker","text":"

Now, there are a few things you can do to check out how things work. Try the following things:

"},{"location":"tutorials/getting_started_with_keycloak/#send-feedback","title":"Send feedback","text":"

If the above tutorial didn't work as expected, a step needs better clarification, or you have some questions about it, please create an issue on Armasec's GitHub's issues.

"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"

An Omnivector initiative

"},{"location":"#armasec-documentation","title":"Armasec Documentation","text":"

Armasec is a security package that simplifies OIDC security for FastAPI apps.

"},{"location":"#overview","title":"Overview","text":"

Adding a security layer on top of your API can be difficult, especially when working with an OIDC platform. It's hard enough to get your OIDC provider configured correctly. Armasec aims to take the pain out of securing your APIs routes.

Armasec is an opinionated library that attemtps to use the most obvious and commonly used workflows when working with OIDC and making configuration as simple as possible.

When using the Armasec helper class, you only need two configuration settings to get going:

  1. Domain: the domain of your OIDC provider
  2. Audience: An optional setting that restricts tokens to those intended for your API.

That's it! Once you have those settings dialed in, you can just worry about checking the permissions scopes of your endpoints

"},{"location":"#inception","title":"Inception","text":"

Armasec was originally developed as an internal tool to add security in tandem with Auth0. Since its inception, Armasec has been used in production with both Auth0 and Keycloak. It should work with other OIDC providers, assuming they are configured correctly, but the developers of Armasec make no guarantees for other platforms.

"},{"location":"getting_started/","title":"Getting Started","text":""},{"location":"getting_started/#requirements","title":"Requirements","text":""},{"location":"getting_started/#installation","title":"Installation","text":"

The armasec package can be installed like any other python package. It is available on PyPI

"},{"location":"getting_started/#poetry","title":"Poetry","text":"

To install via poetry, simply run:

poetry add armasec\n
"},{"location":"getting_started/#pip","title":"Pip","text":"

To install directly with pip, simply run:

pip install armasec\n
"},{"location":"minimal_example/","title":"Minimal Example","text":"

The following is a minimal example of how to configure your API to enforce security on endpoints using tokens issued by Auth0.

First, create a file named example.py with the following contents:

example.py
import os\nfrom armasec import Armasec\nfrom fastapi import FastAPI, Depends\napp = FastAPI()\narmasec = Armasec(\ndomain=os.environ.get(\"ARMASEC_DOMAIN\"),\naudience=os.environ.get(\"ARMASEC_AUDIENCE\"),\n)\n@app.get(\"/stuff\", dependencies=[Depends(armasec.lockdown(\"read:stuff\"))])\nasync def check_access():\nreturn dict(message=\"Successfully authenticated!\")\n

In this example, you would have set two environment variables for your project settings:

When you run your app, access to the /stuff endpoint would be restricted to authenticated users whose access tokens carried the permission scope \"read:stuff\".

For a step-by-step walk-through of how to set up Auth0 for the minimal example, see the \"Getting Started with Auth0\" page.

The above code can be found in examples/basic.py.

"},{"location":"reference/","title":"Reference","text":""},{"location":"reference/#armasec.armasec","title":"armasec.armasec","text":"

This module defines the core Armasec class.

"},{"location":"reference/#armasec.armasec.Armasec","title":"Armasec","text":"

This is a factory class for TokenSecurity. It allows the machinery of armasec to be initialized correctly so that the factory method lockdown can initialize new instances of TokenSecurity to protect routes. It's not essential to use Armasec to secure routes, but it cuts down on the boilerplate necessary to do so.

"},{"location":"reference/#armasec.armasec.Armasec.__init__","title":"__init__","text":"
__init__(\ndomain_configs: Optional[List[DomainConfig]] = None,\ndebug_logger: Optional[Callable[[str], None]] = noop,\ndebug_exceptions: bool = False,\n**kargs: bool\n)\n

Stores initialization values for the TokenSecurity. All are passed through.

Parameters:

Name Type Description Default domain_configs Optional[List[DomainConfig]]

List of domain configuration to authenticate the tokens against.

None debug_logger Optional[Callable[[str], None]]

A callable, that if provided, will allow debug logging. Should be passed as a logger method like logger.debug

noop debug_exceptions bool

If True, raise original exceptions. Should only be used in a testing or debugging context.

False kargs

Arguments compatible to instantiate the DomainConfig model.

{}"},{"location":"reference/#armasec.armasec.Armasec.lockdown","title":"lockdown cached","text":"
lockdown(\n*scopes: str,\npermission_mode: PermissionMode = PermissionMode.ALL\n) -> TokenSecurity\n

Initialize an instance of TokenSecurity to lockdown a route. Uses memoization to minimize the number of TokenSecurity instances initialized. Applies supplied permission_mode when checking token permssions against TokenSecurity scopes.

Parameters:

Name Type Description Default scopes str

A list of scopes needed to access the endpoint.

() permissions_mode

If \"ALL\", all scopes listed are required for access. If \"SOME\", only one of the scopes listed are required for access.

required"},{"location":"reference/#armasec.armasec.Armasec.lockdown_all","title":"lockdown_all","text":"
lockdown_all(*scopes: str) -> TokenSecurity\n

Initialize an instance of TokenSecurity to lockdown a route. Uses memoization to minimize the number of TokenSecurity instances initialized. Requires all the scopes in the TokenSecurity instance to be included in the token permissions. This is just a wrapper around lockdown() with default permission_mode and is only included for symmetry.

Parameters:

Name Type Description Default scopes str

A list of the scopes needed to access the endpoint. All are required.

()"},{"location":"reference/#armasec.armasec.Armasec.lockdown_some","title":"lockdown_some","text":"
lockdown_some(*scopes: str) -> TokenSecurity\n

Initialize an instance of TokenSecurity to lockdown a route. Uses memoization to minimize the number of TokenSecurity instances initialized. Requires at least one permission in the token to match a scope attached to the TokenSecurity instance.

Parameters:

Name Type Description Default scopes str

A list of the scopes needed to access the endpoint. Only one is required.

()"},{"location":"reference/#armasec.exceptions","title":"armasec.exceptions","text":""},{"location":"reference/#armasec.exceptions.ArmasecError","title":"ArmasecError","text":"

Bases: buzz.Buzz

A custom exception class used for checking conditions and handling other exceptions.

Attributes:

Name Type Description status_code int

The HTTP status code indicated by the error. Set to 400.

"},{"location":"reference/#armasec.exceptions.AuthenticationError","title":"AuthenticationError","text":"

Bases: ArmasecError

Indicates a failure to authenticate and decode jwt.

Attributes:

Name Type Description status_code int

The HTTP status code indicated by the error. Set to 401.

"},{"location":"reference/#armasec.exceptions.AuthorizationError","title":"AuthorizationError","text":"

Bases: ArmasecError

Indicates that the provided claims don't match the claims required for a protected endpoint.

Attributes:

Name Type Description status_code int

The HTTP status code indicated by the error. Set to 403.

"},{"location":"reference/#armasec.openid_config_loader","title":"armasec.openid_config_loader","text":"

This module provides the OpenidConfigLoader which is used to load openid-configuration data from an OIDC provider.

"},{"location":"reference/#armasec.openid_config_loader.OpenidConfigLoader","title":"OpenidConfigLoader","text":""},{"location":"reference/#armasec.openid_config_loader.OpenidConfigLoader.config","title":"config property","text":"
config: OpenidConfig\n

Retrive the openid config from an OIDC provider. Lazy loads the config so that API calls are deferred until the coniguration is needed.

"},{"location":"reference/#armasec.openid_config_loader.OpenidConfigLoader.jwks","title":"jwks property","text":"
jwks: JWKs\n

Retrives JWKs public keys from an OIDC provider. Lazy loads the jwks so that API calls are deferred until the jwks are needed.

"},{"location":"reference/#armasec.openid_config_loader.OpenidConfigLoader.__init__","title":"__init__","text":"
__init__(\ndomain: str,\nuse_https: bool = True,\ndebug_logger: Optional[Callable[..., None]] = None,\n)\n

Initializes a base TokenManager.

Parameters:

Name Type Description Default secret

The secret key needed to decode a token

required domain str

The domain of the OIDC provider. This is to construct the openid-configuration url

required use_https bool

If falsey, use http instead of https (the default).

True debug_logger Optional[Callable[..., None]]

A callable, that if provided, will allow debug logging. Should be passed as a logger method like logger.debug

None"},{"location":"reference/#armasec.openid_config_loader.OpenidConfigLoader.build_openid_config_url","title":"build_openid_config_url staticmethod","text":"
build_openid_config_url(\ndomain: str, use_https: bool = True\n)\n

Builds a url for an openid configuration given a domain.

Parameters:

Name Type Description Default domain str

The domain of the OIDC provider for which to build a URL

required use_https bool

Use https for the URL by default. If falsey, use http instead.

True"},{"location":"reference/#armasec.pytest_extension","title":"armasec.pytest_extension","text":"

This module provides a pytest plugin for testing.

"},{"location":"reference/#armasec.pytest_extension.build_mock_openid_server","title":"build_mock_openid_server","text":"
build_mock_openid_server(\ndomain, openid_config, jwk, jwks_uri\n) -> Callable[\n[str, OpenidConfig, JWK, str], _GeneratorContextManager\n]\n

Provide a fixture that returns a context manager that mocks opend-config routes.

Parameters:

Name Type Description Default domain

The domain of the openid server to mock.

required openid_config

The config to return from the mocked config route.

required jwk

The jwk to return from the mocked jwk route.

required jwks_uri

The URL of the jwks route to mock.

required

Returns:

Type Description Callable[[str, OpenidConfig, JWK, str], _GeneratorContextManager]

A context manager that, while active, mocks the openid routes needed by Armasec.

"},{"location":"reference/#armasec.pytest_extension.build_rs256_token","title":"build_rs256_token","text":"
build_rs256_token(\nrs256_private_key, rs256_iss, rs256_sub, rs256_kid\n)\n

Provide a fixture that returns a helper method that can build a JWT.

The JWT is signed with the private key provided by the rs256_private_key.

Parameters:

Name Type Description Default rs256_private_key

An implicit fixture parameter.

required rs256_iss

An implicit fixture parameter.

required rs256_sub

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.mock_openid_server","title":"mock_openid_server","text":"
mock_openid_server(\nrs256_domain,\nrs256_openid_config,\nrs256_jwk,\nrs256_jwks_uri,\n)\n

Provide a fixture that mocks an openid server using the extension fixtures.

Parameters:

Name Type Description Default rs256_domain

An implicit fixture parameter.

required rs256_openid_config

An implicit fixture parameter.

required rs256_jwk

An implicit fixture parameter.

required rs256_jwks_uri

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.rs256_domain","title":"rs256_domain","text":"
rs256_domain()\n

Provide a fixture that returns a domain for use in other fixtures.

The value here doesn't really have anything to do with an actual domain name.

"},{"location":"reference/#armasec.pytest_extension.rs256_domain_config","title":"rs256_domain_config","text":"
rs256_domain_config(rs256_domain)\n

Provide a fixture that returns the DomainConfig model for the default rs256 domain.

Parameters:

Name Type Description Default rs256_domain

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.rs256_iss","title":"rs256_iss","text":"
rs256_iss(rs256_domain)\n

Provide a fixture that returns an issuer claim for use in other fixtures.

Parameters:

Name Type Description Default rs256_domain

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.rs256_jwk","title":"rs256_jwk","text":"
rs256_jwk(rs256_kid)\n

Provide a fixture that returns a JWK for use in other fixtures.

Parameters:

Name Type Description Default rs256_kid

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.rs256_jwks_uri","title":"rs256_jwks_uri","text":"
rs256_jwks_uri(rs256_domain)\n

Provide a fixture that returns a jwks uri for use in other fixtures.

Parameters:

Name Type Description Default rs256_jwks_uri

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.rs256_kid","title":"rs256_kid","text":"
rs256_kid()\n

Provide a fixture that returns a KID header value for use in other fixtures.

"},{"location":"reference/#armasec.pytest_extension.rs256_openid_config","title":"rs256_openid_config","text":"
rs256_openid_config(rs256_iss, rs256_jwks_uri)\n

Provide a fixture that returns an openid configuration for use in other fixtures.

Parameters:

Name Type Description Default rs256_iss

An implicit fixture parameter.

required rs256_jwks_uri

An implicit fixture parameter.

required"},{"location":"reference/#armasec.pytest_extension.rs256_private_key","title":"rs256_private_key","text":"
rs256_private_key()\n

Provide a fixture that returns a pre-generated private key for RS256 hashing in other fixtures.

"},{"location":"reference/#armasec.pytest_extension.rs256_public_key","title":"rs256_public_key","text":"
rs256_public_key()\n

Provide a fixture that returns a pre-generated public key for RS256 hashing in other fixtures.

"},{"location":"reference/#armasec.pytest_extension.rs256_sub","title":"rs256_sub","text":"
rs256_sub()\n

Provide a fixture that returns a sum claim for use in other fixtures.

"},{"location":"reference/#armasec.token_decoder","title":"armasec.token_decoder","text":"

This module provides an abstract base class for algorithmic token decoders

"},{"location":"reference/#armasec.token_decoder.TokenDecoder","title":"TokenDecoder","text":"

Decoder class used to decode tokens given an algorithm and jwks.

"},{"location":"reference/#armasec.token_decoder.TokenDecoder.__init__","title":"__init__","text":"
__init__(\njwks: JWKs,\nalgorithm: str = \"RS256\",\ndebug_logger: Optional[Callable[..., None]] = None,\ndecode_options_override: Optional[dict] = None,\n)\n

Initializes a TokenDecoder.

Parameters:

Name Type Description Default algorithm str

The algorithm to use for decoding. Defaults to RS256.

'RS256' jwks JWKs

JSON web keys object holding the public keys for decoding.

required openid_config

The openid_configuration needed for claims such as 'issuer'.

required debug_logger Optional[Callable[..., None]]

A callable, that if provided, will allow debug logging. Should be passed as a logger method like logger.debug

None decode_options_override Optional[dict]

Options that can override the default behavior of the jwt decode method. For example, one can ignore token expiration by setting this to { \"verify_exp\": False }

None"},{"location":"reference/#armasec.token_decoder.TokenDecoder.decode","title":"decode","text":"
decode(token: str, **claims: str) -> TokenPayload\n

Decode a JWT into a TokenPayload while checking signatures and claims.

Parameters:

Name Type Description Default token str

The token to decode.

required claims

Additional claims to verify in the token.

{}"},{"location":"reference/#armasec.token_decoder.TokenDecoder.get_decode_key","title":"get_decode_key","text":"
get_decode_key(token: str) -> dict\n

Search for a public keys within the JWKs that matches the incoming token.

Compares the token's unverified header against available JWKs. Uses the matching JWK for the decode key. Raise AuthenticationError if matching public key cannot be found.

Parameters:

Name Type Description Default token str

The token to match against available JWKs.

required"},{"location":"reference/#armasec.token_manager","title":"armasec.token_manager","text":"

This module defines a TokenManager that can be used to extract token payloads from request headers.

"},{"location":"reference/#armasec.token_manager.TokenManager","title":"TokenManager","text":"

Handle auth via a TokenDecoder and manage extraction from request headers and serialization into TokenPayload instances.

"},{"location":"reference/#armasec.token_manager.TokenManager.__init__","title":"__init__","text":"
__init__(\nopenid_config: OpenidConfig,\ntoken_decoder: TokenDecoder,\naudience: Optional[str] = None,\ndebug_logger: Optional[Callable[..., None]] = None,\ndecode_options_override: Optional[dict] = None,\n)\n

Initialize a base TokenManager.

Parameters:

Name Type Description Default openid_config OpenidConfig

The openid_configuration needed for claims such as 'issuer'.

required token_decoder TokenDecoder

The decoder used to verify jwts

required audience Optional[str]

An optional audience to check in decoded tokens.

None debug_logger Optional[Callable[..., None]]

A callable, that if provided, will allow debug logging. Should be passed as a logger method like logger.debug

None decode_options_override Optional[dict]

Options that can override the default behavior of the jwt decode method. For example, one can ignore token expiration by setting this to { \"verify_exp\": False }

None"},{"location":"reference/#armasec.token_manager.TokenManager.extract_token_payload","title":"extract_token_payload","text":"
extract_token_payload(\nheaders: Union[Headers, dict]\n) -> TokenPayload\n

Retrieve a token from a request header and decode it into a TokenPayload.

Parameters:

Name Type Description Default headers Union[Headers, dict]

The headers from which to retrieve a JWT.

required"},{"location":"reference/#armasec.token_manager.TokenManager.unpack_token_from_header","title":"unpack_token_from_header","text":"
unpack_token_from_header(\nheaders: Union[Headers, dict]\n) -> str\n

Unpack a JWT from a request header.

Parameters:

Name Type Description Default headers Union[Headers, dict]

The headers from which to unpack a JWT.

required"},{"location":"reference/#armasec.token_payload","title":"armasec.token_payload","text":"

This module defines a pydantic schema for the payload of a jwt.

"},{"location":"reference/#armasec.token_payload.TokenPayload","title":"TokenPayload","text":"

Bases: BaseModel

A convenience class that can be used to access parts of a decoded jwt.

Attributes:

Name Type Description sub str

The \"sub\" claim from a JWT.

permissions List[str]

The permissions claims extracted from a JWT.

expire datetime

The \"exp\" claim extracted from a JWT.

client_id str

The \"azp\" claim extracted from a JWT.

"},{"location":"reference/#armasec.token_payload.TokenPayload.to_dict","title":"to_dict","text":"
to_dict()\n

Convert a TokenPayload to the equivalent dictionary returned by jwt.decode().

"},{"location":"reference/#armasec.token_security","title":"armasec.token_security","text":"

This module defines a TokenSecurity injectable that can be used enforce access on FastAPI routes.

"},{"location":"reference/#armasec.token_security.ManagerConfig","title":"ManagerConfig","text":"

Bases: BaseModel

Model class to represent a TokenManager instance and its domain configuration for easier mapping

Attributes:

Name Type Description manager TokenManager

The TokenManager instance to use for decoding tokens.

domain_config DomainConfig

The DomainConfig for the openid server.

"},{"location":"reference/#armasec.token_security.PermissionMode","title":"PermissionMode","text":"

Bases: AutoNameEnum

Endpoint permissions.

Attributes:

Name Type Description ALL

Require all listed permissions.

SOME

Require at least one of the listed permissions.

"},{"location":"reference/#armasec.token_security.TokenSecurity","title":"TokenSecurity","text":"

Bases: APIKeyBase

An injectable Security class that returns a TokenPayload when used with Depends().

Attributes:

Name Type Description manager Optional[TokenManager]

The TokenManager to use for token validation and extraction.

"},{"location":"reference/#armasec.token_security.TokenSecurity.__call__","title":"__call__ async","text":"
__call__(request: Request) -> TokenPayload\n

This method is called by FastAPI's dependency injection system when a TokenSecurity instance is injected to a route endpoint via the Depends() method. Lazily loads the OIDC config, the TokenDecoder, and the TokenManager if they are not already initialized.

Parameters:

Name Type Description Default request Request

The FastAPI request to check for secure access.

required"},{"location":"reference/#armasec.token_security.TokenSecurity.__init__","title":"__init__","text":"
__init__(\ndomain_configs: List[DomainConfig],\nscopes: Optional[Iterable[str]] = None,\npermission_mode: PermissionMode = PermissionMode.ALL,\ndebug_logger: Optional[Callable[..., None]] = None,\ndebug_exceptions: bool = False,\n)\n

Initializes the TokenSecurity instance.

Parameters:

Name Type Description Default domain_configs List[DomainConfig]

List of domain configuration to authenticate the tokens against.

required scopes Optional[Iterable[str]]

Optional permissions scopes that should be checked

None permission_mode PermissionMode

The PermissionMode to apply in the protected route.

PermissionMode.ALL debug_logger Optional[Callable[..., None]]

A callable, that if provided, will allow debug logging. Should be passed as a logger method like logger.debug

None debug_exceptions bool

If True, raise original exceptions. Should only be used in a testing or debugging context.

False"},{"location":"reference/#armasec.utilities","title":"armasec.utilities","text":"

Provides some utility functions.

"},{"location":"reference/#armasec.utilities.log_error","title":"log_error","text":"
log_error(logger: Callable[..., None], dep: DoExceptParams)\n

Logs an en error with the supplied message, a string representation of the error, and its traceback. If the logger supplied is noop, do nothing. Pass as a partial when using the Buzz handle_errors context manager::

with Buzz.handle_errors(\"Boom!\", do_except=partial(log_error, debug_logger)):\n    do_some_risky_stuff()\n
"},{"location":"reference/#armasec.utilities.noop","title":"noop","text":"
noop(*args, **kwargs)\n

This is a no-op function that...does nothing.

"},{"location":"reference/#armasec.schemas.armasec_config","title":"armasec.schemas.armasec_config","text":"

This module provides a pydantic schema describing Armasec's configuration parameters.

"},{"location":"reference/#armasec.schemas.armasec_config.DomainConfig","title":"DomainConfig","text":"

Bases: BaseModel

This model provides a specification for the input domains to authenticate against. It expects the domain indeed and the audience to refer to.

Attributes:

Name Type Description domain str

The OIDC domain from which resources are loaded.

audience Optional[str]

Optional designation of the token audience.

algorithm str

The Algorithm to use for decoding. Defaults to RS256.

use_https bool

If true, use https for URLs. Otherwise use http

match_keys Dict[str, Union[str, List[Any], Dict[Any, Any], Set[Any], bool, int, float]]

Dictionary of k/v pairs to match in the token when decoding it.

"},{"location":"reference/#armasec.schemas.jwks","title":"armasec.schemas.jwks","text":"

This module provides pydantic schemas for JSON Web Keys.

"},{"location":"reference/#armasec.schemas.jwks.JWK","title":"JWK","text":"

Bases: BaseModel

This Model provides a specification for the objects retrieved from JWK endpoints in OIDC providers. It also assists with validation and item access.

Attributes:

Name Type Description alg str

The algorithm to use for hash validation.

e str

The exponent parameter to use in RS256 hashing

kid str

The \"kid\" claim to uniquely identify the key.

kty str

The \"kty\" claim to identify the type of the key.

n str

The modulus parameter to use in RS256 hashing.

use Optional[str]

The claim that identifies the intended use of the public key.

x5c Optional[List[str]]

The X.509 certificate chain parameter

x5c Optional[List[str]]

The X.509 certificate SHA-1 thumbprint parameter

"},{"location":"reference/#armasec.schemas.jwks.JWKs","title":"JWKs","text":"

Bases: BaseModel

This Model provides a specification for the container object retrieved from JWK endpoints in OIDC providers. It also assists with validation and item access.

Attributes:

Name Type Description keys List[JWK]

The list of JWKs contained within.

"},{"location":"reference/#armasec.schemas.openid_config","title":"armasec.schemas.openid_config","text":"

This module provides a pydantic schema describing openid-configuration data.

"},{"location":"reference/#armasec.schemas.openid_config.OpenidConfig","title":"OpenidConfig","text":"

Bases: BaseModel

Provides a specification for the objects retrieved from openid_configuration endpoint of the OIDC providers. Only includes needed fields for supported Manager instances. Assists with validation and item access.

Attributes:

Name Type Description issuer AnyHttpUrl

The URL of the issuer of the tokens.

jwks_uri AnyHttpUrl

The URI where JWKs can be foun don the OpenID server.

"},{"location":"tutorials/getting_started_with_auth0/","title":"Getting started with Auth0","text":"

This step-by-step walk-through will show you how to get an Auth0 account set up for use with the minimal example.

You will need:

"},{"location":"tutorials/getting_started_with_auth0/#create-auth0-account-tenant","title":"Create Auth0 account tenant","text":"

Navigate to Auth0's homepage, and click Sign Up.

Create a new account (if you don't already have one). It doesn't really matter how you choose to sign up, but I used my google account.

Create a personal account

For this tutorial, just select a \"Personal\" account. You can come back and repeat the process for your company later if you need to.

Select I need advanced settings so that you can choose your tenant name, and click Next to move on to tenant setup.

Select tenant domain

Select your tenant domain. For this tutorial, I will be using \"armasec-tutorial\". Choose your region and click Create Account. The full domain that I will use later is \"armasec-tutorial.us.auth0.com\".

"},{"location":"tutorials/getting_started_with_auth0/#add-your-api-application","title":"Add your API application","text":"

This will set up the Auth0 api endpoints that Auth0 will use to authenticate your users.

Navigate to Applications > APIs

Click Applications -> APIs

Create an API

Click Create API

Fill out API form

Fill out the form. The Name you choose doesn't matter, but for the tutorial, I used \"Armasec Tutorial\". Choose a name for the identifier that makes sense, as this will be the \"Audience\" for your tutorial app. I chose \"https://armasec-tutorial.com\" for this tutorial.

Leave the \"Signing Algorithm\" as \"RS256\". Armasec also supports HS256, but it is not preferred.

Click Create

Enable RBAC Settings

Go to the Settings tab and scroll down to the \"RBAC Settings\"

Activate Enable RBAC and Add Permissions in the Access Token\".

This will include permissions scopes to your users' access tokens.

Click Save

"},{"location":"tutorials/getting_started_with_auth0/#add-your-permissions","title":"Add your permissions","text":"

Next, we will add the permission for the minimal example.

Add a permission

Click on the Permissions tab and add the \"read:stuff\" permission.

"},{"location":"tutorials/getting_started_with_auth0/#grant-your-permission-to-the-test-app","title":"Grant your permission to the test app","text":"

Auth0 provides a \"Machine-to-Machine\" test app for verifying that log in will work. We will grant our \"read:stuff\" permission to tokens provided from this app.

Navigate to Applications

Navigate to Applications -> Applications

Select tutorial test app

Click on Armasec Tutorial (Test Application)

Add permission to test app

Go to the APIs tab and click the drop-down. Select the \"read-stuff\" box in the \"Permissions\" box. Click Update.

"},{"location":"tutorials/getting_started_with_auth0/#start-up-the-example-app","title":"Start up the example app","text":"

Copy the example app to a local source file called \"example.py\".

Start it up with uvicorn:

python -m uvicorn --host 0.0.0.0 example:app\n
"},{"location":"tutorials/getting_started_with_auth0/#try-it-out","title":"Try it out","text":"

Next, we will try to use a test token to call our minimal example's endpoint.

Navigate back to Applications -> APIs, select the Armasec Tutorial, and go to the Test tab.

Copy test access token

Find the \"Response\" box. This contains a token that has been issued by your test application. Click the Copy Token button.

Now, open a browser to \"localhost:8000/docs\"

Swagger page for example

This will show you the auto-generated swagger docs for the example API app. Click on the Authorize button to add the token you copied to the clipboard in the header of requests to the API.

Add access token in Swagger

First, type \"Bearer \" followed by pasting the token from the clipboard into the form and click the Authorize button in the dialog, click Close to dismiss the dialog. Now, all subsequent calls to the API will include a header that looks like:

{\n\"Authorization\": \"Bearer eyJhbGciOi...\"\n}\n

Now, expand the \"GET\" REST operation on the /stuff endpoint and click Try it out.

Try it out

Finally, click Execute to issue the request to the API.

Execute

You should see a response that includes a 200 status code and a response body that includes:

{\n\"message\": \"Successfully authenticated\"\n}\n

Congratulations! You are now using Armasec and Auth0 to authorize requests to your API.

"},{"location":"tutorials/getting_started_with_auth0/#tinker","title":"Tinker","text":"

Now, there are a few things you can do to check out how things work. Try the following things:

"},{"location":"tutorials/getting_started_with_auth0/#send-feedback","title":"Send feedback","text":"

If the above tutorial didn't work as expected, a step needs better clarification, or you have some questions about it, please create an issue on Armasec's GitHub's issues.

"},{"location":"tutorials/getting_started_with_keycloak/","title":"Getting started with Keycloak","text":"

This step-by-step walk-through will show you how to get your Keycloak server set up to work with the minimal example. For this tutorial, I am running Keycloak locally with Docker.

You will need:

"},{"location":"tutorials/getting_started_with_keycloak/#start-your-keycloak-server","title":"Start your Keycloak server","text":"

If you want to try the example locally without an existing Keycloak server, you can start a new one using Docker with the following command:

 docker run keycloak/keycloak:18.0.0 -p 8080:8080 -e KEYCLOAK_ADMIN=\"admin\" -e KEYCLOAK_ADMIN_PASSWORD=\"admin\" start-dev\n

This will start a server who's admin UI is available at localhost:8080.

Open a browser and load the address localhost:8080. Then, click on the \"Administration Console\" to log in.

Log-in to admin console

The sign-in credentials for the admin account are:

Field Value Username admin Password admin

After you log in, you will load the \"Master\" realm.

"},{"location":"tutorials/getting_started_with_keycloak/#set-up-your-master-realm","title":"Set up your \"Master\" realm","text":"

First, we need to change the lifespan for tokens. By default they expire after 1 minute, but that's not so friendly for a tutorial, so we will lengthen the lifespan to 5 minutes.

Go to the \"Tokens\" tab of your \"Master\" realm and set the \"Access Token Lifespan\" to 5 minutes.

Ream settings

Click \"Save\" at the bottom after you change the value. All of the rest of the settings can be left as they are.

"},{"location":"tutorials/getting_started_with_keycloak/#set-up-a-client","title":"Set up a client","text":"

We will need a client that is configured with our permissions. To do this, navigate to the \"Clients\" tab in the nav bar and click the \"Create\" button:

Clients

For this tutorial, we will use the name \"armasec-tutorial\". Click \"Save\" to create the new client.

Create client

Now we need to set the following values for the new client:

Field Value Access Type Confidential Service Accounts Enabled ON Valid Redirect URIs *

The service account produce a token using the client secret over an API request to Keycloak.

Client settings

Next, we need to save the \"Client Secret\" for later when we request a token. Navigate to the \"Credentials\" tab and copy the value found in the \"Secret\" field.

Secrets

Next, we need to create the \"Roles\" that Armasec uses for the \"permissions\" claim inside the tokens. Navigate to the \"Roles\" tab for the client and click the \"Add Role\" button.

Add role

Fill the \"Role Name\" field with \"read:stuff\". There's no need to add a description at this time. Click the \"Save\" button to add the role to the client.

Save role

Next, we need to set up a Mapper that will put the roles inside of the \"permissions\" claim in the issued tokens. Navigate back to the \"armasec-tutorial\" client and open the \"Mappers\" tab. Click the \"Create\" button to add a new mapper.

Mappers

In the form, there's a few things to set:

Field Value Name permissions Mapper Type User Client Role Client ID armasec-tutorial Token Claim Name Permissions Claim JSON Type String

Set the fields as specified above and click the \"Save\" button to create the new mapper

Permissions mapper

Finally, we need to set up an \"Audience\" mapper to set the audience claim in the token that our example app will check for.

Create a new mapper with the following settings:

Field Value Name audience Mapper Type Audience Included Custom Audience http://keycloak.local Add to ID token ON

Click \"Save\" to create the new mapper.

Audience mapper

Now, for the purposes of this tutorial, we will be getting a token via a request with a \"Service Account Role\". We need to add the role we created above to the \"Service Account Role\" so that the token issued later includes the needed permissions.

Navigate to the \"Service Account Roles\" tab. Then, select \"armasec-tutorial\" for the \"Client Roles\" field. Select the \"read:stuff\" role and add it with the \"Add selected >>\" button.

Add role

Now your client should be all set up and ready to go.

"},{"location":"tutorials/getting_started_with_keycloak/#prepare-the-environment","title":"Prepare the environment","text":"

The example FastAPI app requires the \"ARMASEC_DOMAIN\" and \"ARMASEC_AUDIENCE\" environment variables to be set.

We also need to set the \"CLIENT_ID\" and \"CLIENT_SECRET\" for our curl request to Keycloak to get a test token:

export ARMASEC_DOMAIN=localhost:8080/realms/master\nexport ARMASEC_AUDIENCE=http://keycloak.local\nexport CLIENT_ID=armasec-tutorial\nexport CLIENT_SECRET=<your-client-secret>\n
"},{"location":"tutorials/getting_started_with_keycloak/#start-up-the-example-app","title":"Start up the example app","text":"example.py
import os\nfrom armasec import Armasec\nfrom fastapi import FastAPI, Depends\napp = FastAPI()\narmasec = Armasec(\ndomain=os.environ.get(\"ARMASEC_DOMAIN\"),\naudience=os.environ.get(\"ARMASEC_AUDIENCE\"),\nuse_https=False,\n)\n@app.get(\"/stuff\", dependencies=[Depends(armasec.lockdown(\"read:stuff\"))])\nasync def check_access():\nreturn dict(message=\"Successfully authenticated!\")\n

Note in this example that the use_https flag must be set to false to allow a local server using unsecured HTTP.

Copy the example.py app to a local source file called \"example.py\".

Start it up with uvicorn:

python -m uvicorn --host 0.0.0.0 example:app\n
"},{"location":"tutorials/getting_started_with_keycloak/#get-the-test-token","title":"Get the test token","text":"

We will use curl to get an example token to test out our route's security:

curl -d \"client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&grant_type=client_credentials\" -X POST \"http://localhost:8080/realms/master/protocol/openid-connect/token\"\n

If you wish to see metadata about the token (such as its lifespan, you can omit the jq command at the end.

"},{"location":"tutorials/getting_started_with_keycloak/#try-it-out","title":"Try it out","text":"

Open a browser to localhost:8000/docs

Swagger

This will show you the auto-generated swagger docs for the example API app. Click on the Authorize button to add the token you copied to the clipboard in the header of requests to the API.

Authorize

First, type \"Bearer \" followed by pasting the token from the clipboard into the form and click the Authorize button in the dialog, click Close to dismiss the dialog. Now, all subsequent calls to the API will include a header that looks like:

{\n\"Authorization\": \"Bearer eyJhbGciOi...\"\n}\n

Now, expand the \"GET\" REST operation on the /stuff endpoint and click Try it out.

Try it out

Finally, click Execute to issue the request to the API.

Execute

You should see a response that includes a 200 status code and a response body that includes:

{\n\"message\": \"Successfully authenticated\"\n}\n

Congratulations! You are now using Armasec and Auth0 to authorize requests to your API.

"},{"location":"tutorials/getting_started_with_keycloak/#tinker","title":"Tinker","text":"

Now, there are a few things you can do to check out how things work. Try the following things:

"},{"location":"tutorials/getting_started_with_keycloak/#send-feedback","title":"Send feedback","text":"

If the above tutorial didn't work as expected, a step needs better clarification, or you have some questions about it, please create an issue on Armasec's GitHub's issues.

"}]} \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 7aafe1625f1a6585525534da48228b322ec3822d..f05cf8ce4678d56d89c4cec32f76a73e5facb104 100644 GIT binary patch delta 13 Ucmb=gXP58h;3&HId?I@V03YZC`Tzg` delta 13 Ucmb=gXP58h;1JBeHIcmn02_n^DgXcg