barrel_mcp_auth behaviour (barrel_mcp v3.0.0)
View SourceAuthentication behaviour and utilities for barrel_mcp.
This module defines the barrel_mcp_auth behaviour for implementing pluggable authentication providers. It also provides utility functions for extracting credentials from HTTP headers.
Built-in Providers
barrel_mcp_auth_none- No authentication (default)barrel_mcp_auth_bearer- Bearer tokens (JWT/opaque)barrel_mcp_auth_apikey- API key authenticationbarrel_mcp_auth_basic- HTTP Basic authentication
Implementing a Custom Provider
To create a custom authentication provider, implement the barrel_mcp_auth behaviour:
-module(my_auth_provider).
-behaviour(barrel_mcp_auth).
-export([init/1, authenticate/2, challenge/2]).
init(Opts) ->
{ok, Opts}.
authenticate(Request, State) ->
Headers = maps:get(headers, Request, #{}),
case barrel_mcp_auth:extract_bearer_token(Headers) of
{ok, Token} -> verify_token(Token);
{error, no_token} -> {error, unauthorized}
end.
challenge(Reason, _State) ->
{401, #{<<"www-authenticate">> => <<"Bearer">>}, <<>>}.Configuring Authentication
Pass authentication configuration when starting the HTTP server:
barrel_mcp:start_http(#{
port => 9090,
auth => #{
provider => barrel_mcp_auth_bearer,
provider_opts => #{secret => <<"my-secret">>,
audience => <<"https://mcp.example.com">>},
required_scopes => [<<"read">>]
}
}).
Summary
Functions
Return the list of HTTP request headers (lower-case) the configured provider expects to read credentials from. Used by the HTTP transport to build CORS Access-Control-Allow-Headers and to extract inputs in the request handler. Falls back to a sensible default per built-in provider when the provider does not export auth_headers/1.
Authenticate a request using the configured provider.
Generate a challenge response for failed authentication.
Extract API key from headers.
Extract Basic authentication credentials.
Extract Bearer token from Authorization header.
Get authentication info from a context map.
The identity a task, a sealed request state or an elicitation belongs to.
Types
Callbacks
-callback authenticate(Request :: map(), State :: term()) -> {ok, auth_info()} | {error, auth_error()}.
-callback challenge(Reason :: auth_error(), State :: term()) -> {StatusCode :: integer(), Headers :: map(), Body :: binary()}.
Functions
-spec auth_headers(auth_config()) -> [binary()].
Return the list of HTTP request headers (lower-case) the configured provider expects to read credentials from. Used by the HTTP transport to build CORS Access-Control-Allow-Headers and to extract inputs in the request handler. Falls back to a sensible default per built-in provider when the provider does not export auth_headers/1.
-spec authenticate(auth_config(), map(), term()) -> {ok, auth_info()} | {error, auth_error()}.
Authenticate a request using the configured provider.
Delegates authentication to the configured provider and optionally checks for required scopes after successful authentication.
-spec challenge_response(auth_config(), auth_error()) -> {integer(), map(), binary()}.
Generate a challenge response for failed authentication.
Creates an HTTP response with appropriate status code, headers (including WWW-Authenticate), and error body.
Extract API key from headers.
Looks for API key in the following locations (in order):
- Custom header specified by
header_nameoption - X-API-Key header
- Authorization header with ApiKey scheme
Example
Headers = #{<<"x-api-key">> => <<"my-key">>},
{ok, <<"my-key">>} = barrel_mcp_auth:extract_api_key(Headers, #{}).
-spec extract_basic_auth(Headers :: map()) -> {ok, Username :: binary(), Password :: binary()} | {error, no_credentials}.
Extract Basic authentication credentials.
Parses the Authorization header for Basic authentication scheme and decodes the base64-encoded credentials.
Example
Encoded = base64:encode(<<"user:pass">>),
Headers = #{<<"authorization">> => <<"Basic ", Encoded/binary>>},
{ok, <<"user">>, <<"pass">>} = barrel_mcp_auth:extract_basic_auth(Headers).
Extract Bearer token from Authorization header.
Parses the Authorization header and extracts the token value from a Bearer authentication scheme.
Example
Headers = #{<<"authorization">> => <<"Bearer abc123">>},
{ok, <<"abc123">>} = barrel_mcp_auth:extract_bearer_token(Headers).
Get authentication info from a context map.
Extracts authentication information that was added to the context after successful authentication.
-spec principal(auth_config(), auth_info()) -> {ok, term()} | {error, no_subject}.
The identity a task, a sealed request state or an elicitation belongs to.
Not the auth_info() map: that carries the whole token, so a refreshed credential with a new exp or jti would look like a different caller and orphan the work started under the old one.
Not the subject alone either. Two providers, two issuers or two tenants can each mint the same subject, and the stores these key are node-wide, so the provider and a namespace are part of the identity.