Attenuator plugin
When attenuating a Biscuit token from sources such as headers, cookies, or query parameters, the process begins by extracting and validating the original token.
After validation, a new block is appended to enforce additional restrictions, such as limiting time, access rights, or endpoints.
Once the token is attenuated, the request can be "cleaned" by removing the original token from its initial location.
The newly attenuated token can then be injected into the desired location, whether headers, cookies, or query parameters.
This approach ensures secure, context-aware token usage while maintaining flexibility across various layers of your application.
Attenuator Plugin configuration
Here is a demo configuration :
{
"ref": "YOUR_BISCUIT_ATTENUATOR_REF",
"extractor_type": "header",
"extractor_name": "Authorization",
"token_replace_loc": "query",
"token_replace_name": "auth"
}
Explanation of Fields
ref
: Identifier of the attenuator entity. It may looks likebiscuit-attenuator_1d6e9abd-0c39-41ad-97ef-5f6e666736cc
extractor_type
: Type of the Token extractor (could beheader
,query
orcookie
). Default type is set toheader
.extractor_name
: The name of the field where the token will be extracted from.token_replace_loc
: The location where the token will be inserted (could beheader
,query
orcookie
)token_replace_name
: The name of the field where the token will be inserted to.
Example
Request Before Attenuation
Original Request (Token in Header)
GET /api/resource HTTP/1.1
Host: example.com
Authorization: Biscuit BISCUIT_TOKEN...originalTokenData
Process of Attenuation
- Extract Token: The
Authorization
header contains the original Biscuit token. - Append Restrictions: Add a new block to the token, restricting it (e.g., limit to
GET /api/resource
and expire in 30 minutes). - Generate New Token: The new attenuated Biscuit token is created.
Request After Attenuation
Attenuated Request (Token in Query Parameter)
GET /api/resource?auth=biscuit:NEW_ATTENUATED_BISCUIT_TOKEN...attenuatedTokenData HTTP/1.1
Host: example.com
Alternatively:
Attenuated Request (Token in Cookie)
GET /api/resource HTTP/1.1
Host: example.com
Cookie: auth=biscuit:NEW_ATTENUATED_BISCUIT_TOKEN...attenuatedTokenData
Explanation of Changes
- Original Location: The token was in the
Authorization
header. - New Location: The attenuated token was moved to either the query parameter (
auth
) or a cookie. - Token Content: The attenuated token now includes additional constraints, such as time-bound access or endpoint-specific restrictions.
This flexibility allows secure propagation of tokens while adapting to different application needs.
Demo
curl -X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Basic xxxx' \
"http://otoroshi-api.oto.tools:8080/apis/biscuit.extensions.cloud-apim.com/v1/biscuit-keypairs" \
-d '{
"id" : "biscuit-keypair_dev_d25612c6-b4d0-43ed-a711-16b6c09a5155",
"name" : "New Biscuit Key Pair",
"description" : "New biscuit KeyPair",
"metadata" : { },
"pubKey" : "771F9E7FE62784502FE34CE862220586D3DB637D6A5ABAD254F7330369D3B357",
"privKey" : "4379BE5B9AFA1A84F59D2417C20020EF1E47E0805945535B45616209D8867E50",
"tags" : [ ]
}'
then let's create a forge
curl -X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Basic xxxx' \
"http://otoroshi-api.oto.tools:8080/apis/biscuit.extensions.cloud-apim.com/v1/biscuit-forges" \
-d '{
"id" : "biscuit-forge_dev_7580094c-47e0-495e-80fc-b9c9e8fb8129",
"name" : "New biscuit token",
"description" : "New biscuit token",
"metadata" : { },
"keypair_ref" : "biscuit-keypair_dev_d25612c6-b4d0-43ed-a711-16b6c09a5155",
"config" : {
"checks" : [ ],
"facts" : [ ],
"resources" : [ ],
"rules" : [ ]
},
"tags" : [ ],
"remoteFactsLoaderRef" : null
}'
and finally let's create a route that uses the client_credentials
plugin
curl -X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Basic xxxx' \
"http://otoroshi-api.oto.tools:8080/apis/proxy.otoroshi.io/v1/routes" \
-d '{
"_loc" : {
"tenant" : "default",
"teams" : [ "default" ]
},
"id" : "4874704c-56a2-4460-9a21-ff8055a19c75",
"name" : "test route",
"description" : "test route",
"tags" : [ ],
"metadata" : { },
"enabled" : true,
"groups" : [ "default" ],
"bound_listeners" : [ ],
"frontend" : {
"domains" : [ "test.oto.tools/token" ],
"strip_path" : true,
"exact" : false,
"headers" : { },
"query" : { },
"methods" : [ ]
},
"backend" : {
"targets" : [ {
"id" : "www.otoroshi.io",
"hostname" : "www.otoroshi.io",
"port" : 443,
"tls" : true,
"weight" : 1,
"predicate" : {
"type" : "AlwaysMatch"
},
"protocol" : "HTTP/1.1",
"ip_address" : null,
"tls_config" : {
"certs" : [ ],
"trusted_certs" : [ ],
"enabled" : false,
"loose" : false,
"trust_all" : false
}
} ],
"root" : "/",
"rewrite" : false,
"load_balancing" : {
"type" : "RoundRobin"
}
},
"backend_ref" : null,
"plugins" : [ {
"enabled" : true,
"debug" : false,
"plugin" : "cp:otoroshi_plugins.com.cloud.apim.otoroshi.extensions.biscuit.plugins.ClientCredentialBiscuitTokenEndpoint",
"include" : [ ],
"exclude" : [ ],
"config" : {
"expiration" : 21600000,
"forge_ref" : "biscuit-forge_dev_7580094c-47e0-495e-80fc-b9c9e8fb8129"
},
"bound_listeners" : [ ]
} ]
}'