APIac: API access control for elixir
APIac is a standard interface for API access control and is composed of:
APIac.Authenticator
: an Elixir behaviour for API authentication plugsAPIac.Filter
: an Elixir behaviour for API filter plugs- Convenience functions for working with APIac plugs and for HTTP APIs
The following APIac plugs are available:
APIac.Authenticator
:- APIacAuthBasic: implementatoin of the Basic HTTP authentication scheme (RFC7617)
- APIacAuthBearer: implementation of the Bearer HTTP authentication scheme (RFC6750) along with the OAuth 2.0 Token Introspection (RFC7662) and JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens (RFC9068) verification methods
- APIacAuthMTLS: implementation of the OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens RFC8705
- APIacAuthClientJWT: implementation of the client authentication part of RFC7523 (JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants)
- APIacAuthClientSecretPost: implementation of the OAuth2 client secret post scheme
APIac.Filter
:- APIacFilterIPWhitelist: IPv4 and IPv6 address whitelisting
- APIacFilterIPBlacklist: IPv4 and IPv6 address blacklisting
- APIacFilterThrottler: throttler that can throttle on IP address, client, subject, URI, etc.
Just use one or more of these aforementioned APIac plugs, this library will be automatically imported.
APIac
interfaces are designed so that you can chain APIac plugs. Example:
my_app/lib/my_app_web/router.ex
pipeline :api_public do
plug APIacAuthBasic,
realm: "Public API",
callback: &MyApp.get_client_secret/2,
set_error_response: APIacAuthBasic.set_WWWauthenticate_header/3,
error_response_verbosity: :debug},
plug APIacAuthBearer,
bearer_validator:
{APIacAuthBearer.Validator.Introspect, [
issuer: "https://example.com/auth"
tesla_middleware:[
{Tesla.Middleware.BasicAuth, [username: "client_id_123", password: "WN2P3Ci+meSLtVipc1EZhbFm2oZyMgWIx/ygQhngFbo"]}
]]},
bearer_extract_methods: [:header, :body],
required_scopes: ["article:write", "comments:moderate"],
forward_bearer: true,
cache: {APIacAuthBearerCacheCachex, []}
plug APIacFilterThrottler,
key: &APIacFilterThrottler.Functions.throttle_by_ip_path/1,
scale: 60_000,
limit: 50,
exec_cond: &APIac.machine_to_machine?/1,
error_response_verbosity: :debug}
end
APIac uses the OAuth2 terminology:
- the client is the server, the machine, accessing the API
- the subject is the pysical user (real life person) on behalf on who the API access is performed. Note even though in most cases the subject has authenticated, but it should not be used as a proof of authentication since:
- this may have be a long time ago (using OAuth2
refresh_token
) - this may not be true at all:
- in case the subject is impersonnated
- when using UMA2 flows
- OAuth2 is an access control protocol, not a federated authentication protocol
- this may have be a long time ago (using OAuth2
APIac plugs are designed for API accesses. Therefore, do not use it for end-user authentication as this may lead to security vulnerabilities. For example, the APIacAuthBasic
authenticator does not handle weak user passwords and using it for browser-based authentication by end-user will result in security flaws.
The following table summarizes the information of the APIac authenticators:
Authenticator | Machine-to-machine | Accesses of subjects (real persons) |
---|---|---|
APIacAuthBasic | ✔ | |
APIacAuthBearer | OAuth2 client credentials flow | OAuth2 authorization code, implicit and password flows OpenID Connect flows |
APIacAuthMTLS | ✔ | |
APIacAuthClientJWT | ✔ | |
APIacAuthClientSecretPost | ✔ |
Machine-to-machine (also known as server-to-server or s2s) refers to access when only machines are involved, without subject.