<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>authentication Archives | Clever Cloud</title>
	<atom:link href="https://www.clever.cloud/blog/tag/authentication/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.clever.cloud/blog/tag/authentication/</link>
	<description>From Code to Product</description>
	<lastBuildDate>Thu, 15 Apr 2021 11:25:00 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://cdn.clever-cloud.com/uploads/2023/03/cropped-cropped-favicon-32x32.png</url>
	<title>authentication Archives | Clever Cloud</title>
	<link>https://www.clever.cloud/blog/tag/authentication/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Biscuit tutorial</title>
		<link>https://www.clever.cloud/blog/engineering/2021/04/15/biscuit-tutorial/</link>
		
		<dc:creator><![CDATA[Geoffroy Couprie]]></dc:creator>
		<pubDate>Thu, 15 Apr 2021 11:25:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[authorization]]></category>
		<category><![CDATA[biscuit]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2021/04/15/biscuit-tutorial/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="biscuit tutorial 1" decoding="async" fetchpriority="high" srcset="https://cdn.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>In the <a href="https://www.clever.cloud/blog/engineering/2021/04/12/introduction-to-biscuit/">previous article</a>, I introduced Biscuit, our authentication and authorization token, and mentioned its Datalog based language for authorization policies. Let&#39;s see how it works!</p>
<span id="more-2833"></span>

<h2 id="from-a-personal-blog-to-an-entire-newspaper">From a personal blog to an entire newspaper</h2>
<p>As an example, we will build up authorization policies, going from a small, personal blog, to a professional journal with multiple teams, editors, etc.</p>
<p>Since those policies will be written in Datalog, let&#39;s take a short look at that language first.</p>
<h3 id="side-note-introduction-to-datalog">Side note: introduction to Datalog</h3>
<p>Datalog is a declarative logic language that is a subset of Prolog. A Datalog program contains &quot;facts&quot;, which represent data, and &quot;rules&quot;, which can generate new facts from existing ones.</p>
<p>As an example, we could define the following facts, describing some relationships:</p>
<pre><code class="language-prolog">parent(&quot;Alice&quot;, &quot;Bob&quot;);
parent(&quot;Bob&quot;, &quot;Charles&quot;);
parent(&quot;Charles&quot;, &quot;Denise&quot;);
</code></pre>
<p>This means that Alice is Bob&#39;s parent, and so on.</p>
<p>This could be seen as a table in a relational database:</p>
<table class="table">
<thead>
<tr>
<th>parent</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td>Alice</td>
<td>Bob</td>
</tr>
<tr>
<td></td>
<td>Bob</td>
<td>Charles</td>
</tr>
<tr>
<td></td>
<td>Charles</td>
<td>Denise</td>
</tr>
</tbody></table>
<p>We can then define rules to query our data:</p>
<pre><code class="language-prolog">parent_of_charles($name) &lt;-
  parent($name, &quot;Charles&quot;);
</code></pre>
<p>This could be written in SQL as:</p>
<pre><code class="language-sql">SELECT DISTINCT name from parent where child = &quot;Charles&quot;;
</code></pre>
<p>(we use <code>DISTINCT</code> because Datalog will always remove redundant results)</p>
<p>We can also use rules to create new facts, like this one: (variables are introduced with the <code>$</code> sign)</p>
<pre><code class="language-prolog">grandparent($grandparent, $child) &lt;-
  parent($grandparent, $parent),
  parent($parent, $child);
</code></pre>
<p>You can read it as follows:</p>
<pre><code class="language-text">create the fact grandparent($grandparent, $child)
  IF
    there is a fact parent($grandparent, $parent)
    AND there is a fact parent($parent, $child)
    with matching $parent variable
</code></pre>
<p>or in SQL:</p>
<pre><code class="language-sql">INSERT INTO grandparent( name, grandchild )
  SELECT A.name as name, B.child as grandchild
  FROM parent A, parent B
  WHERE A.child = B.name;
</code></pre>
<p>Applying this rule will look at combinations of the <code>parent</code> facts as defined on the right side of the arrow (the &quot;body&quot; of the rule), and try to match them to the variables (<code>$grandparent</code>, <code>$parent</code>, <code>$child</code>):</p>
<ul>
<li><code>parent(&quot;Alice&quot;, &quot;Bob&quot;), parent(&quot;Bob&quot;, &quot;Charles&quot;)</code> matches because we can
replace <code>$grandparent</code> with <code>&quot;Alice&quot;</code>, <code>$parent</code> with <code>&quot;Bob&quot;</code>, <code>$child</code> with <code>&quot;Charles&quot;</code></li>
<li><code>parent(&quot;Alice&quot;, &quot;Bob&quot;), parent(&quot;Charles&quot;, &quot;Denise&quot;)</code> does not match because
we would get different values for the <code>$parent</code> variable</li>
</ul>
<p>For each matching combination of facts in the body, we will then generate a fact, as defined on the left side of the arrow, the <em>head</em> of the rule. For <code>parent(&quot;Alice&quot;, &quot;Bob&quot;), parent(&quot;Bob&quot;, &quot;Charles&quot;)</code>, we would generate <code>grandparent(&quot;Alice&quot;, &quot;Charles&quot;)</code>. A fact can be generated from multiple rules, but we will get only one instance of it.</p>
<p>Going through all the combinations, we will generate:</p>
<pre><code class="language-prolog">grandparent(&quot;Alice&quot;, &quot;Charles&quot;);
grandparent(&quot;Bob&quot;, &quot;Denise&quot;);
</code></pre>
<p>which can be seen as:</p>
<table class="table">
<thead>
<tr>
<th>grandparent</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td>Alice</td>
<td>Charles</td>
</tr>
<tr>
<td></td>
<td>Bob</td>
<td>Denise</td>
</tr>
</tbody></table>
<p>Interactions with a Datalog program are done through queries: <strong>a query contains a rule</strong> that we apply over the system, and <strong>it returns the generated facts</strong>.</p>
<h3 id="first-steps-personal-blog">First steps: personal blog</h3>
<p>*note: you can follow along the various steps of this tutorial in the <a href="https://play-with-biscuit.cleverapps.io/blog.html">online playground</a>.</p>
<p>When we are the only user of that blog, we do not need much (honestly we could get away with just a random string in a cookie, but bear with me). We only need a way to identify ourselves to the blog engine&#39;s admin panel. So we could just consider the Biscuit token as a fancy JWT, that will only contain data (so, in Datalog, facts).</p>
<p>Our token will contain this fact: <code>user(#authority, &quot;user_1234&quot;)</code>.</p>
<p>Here, <code>&quot;user_1234&quot;</code> is our user id, and <code>#authority</code> is a special symbol that can only be added to facts in the first block of a token (or added by the verifier). A block contains facts (data), rules (to generate facts) and checks (queries used to validate the facts). Attenuation is done by adding more blocks. Since <code>#authority</code> facts are about the basic rights of a token, adding <code>#authority</code> facts would increase the number of rights. So we forbid adding <code>#authority</code> facts in additional blocks. Symbols, as indicated by the <code>#</code> prefix, are special strings that are internally replaced with integers, to compress tokens and accelerate evaluation.</p>
<p>The token can be serialized to a byte array (encoded with Protobuf) and then to base64 if we want to carry it in a cookie.</p>
<p>On the blog engine&#39;s side, we will only have this single line:</p>
<pre><code class="language-prolog">allow if user(#authority, &quot;user_1234&quot;);
</code></pre>
<p>Biscuit can enforce authorization in 2 ways:</p>
<ul>
<li>checks, starting with <code>check if</code></li>
<li>allow/deny policies, starting with <code>allow if</code> or <code>deny if</code></li>
</ul>
<p>They work a bit like rules: if there&#39;s at least one combination of fact in the body (after the <code>if</code>) that fits, then it matches. They will not produce any fact.</p>
<p>To validate a token:</p>
<ul>
<li>all of the checks must match. If one does not, fail</li>
<li>allow/deny policies are tried in order until one matches<ul>
<li>if allow matches, succeed</li>
<li>if deny matches, fail</li>
</ul>
</li>
<li>if none match, fail</li>
</ul>
<p>Here the allow test will succeed if the token contains the fact <code>user(#authority, &quot;user_1234&quot;)</code></p>
<p>It is not very useful yet, but maybe we can add more features?</p>
<h3 id="next-multi-blog-platform">Next: multi-blog platform</h3>
<p>After a few friends have seen your marvelous website, they ask if you could host their blogs on the same platform. So now you need more flexible authorization rules. We could keep the small tokens with the user id, but add more intelligence on the server&#39;s side.</p>
<p>First we need to indicate who owns which blog, with the format <code>owner(#authority, $user_id, $blog_id)</code>. You can load this data when creating the verifier, from your database, from static files, etc.</p>
<pre><code class="language-prolog">owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;);
owner(#authority, &quot;user_5678&quot;, &quot;blog2&quot;);
owner(#authority, &quot;user_1234&quot;, &quot;blog3&quot;);
</code></pre>
<p>Here we own <code>&quot;blog1&quot;</code> and <code>&quot;blog3&quot;</code>, and <code>&quot;user_5678&quot;</code> owns <code>&quot;blog2&quot;</code>.</p>
<p>Now we need to actually validate the request, to see who has access to what. The request is represented through the <code>#ambient</code> facts, added to the verifier: you indicate to the verifier facts representing the current request like which resource is accessed, which operation (read, write, etc), the current time, the source IP address, etc. As an example, a <code>PUT /blog1/article1</code> to modify an article could be translated as:</p>
<pre><code class="language-prolog">blog(#ambient, &quot;blog1&quot;);
article(#ambient, &quot;blog1&quot;, &quot;article1&quot;);
operation(#ambient, #update);
</code></pre>
<p>In the verifier, we add a rule to indicate that the owner of a blog has full rights on it:</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, $operation) &lt;-
    article(#ambient, $blog_id, $article_id),
    operation(#ambient, $operation),
    user(#authority, $user_id),
    owner(#authority, $user_id, $blog_id);
</code></pre>
<p>If this rules finds a matching set of facts, it will produce a <code>right(...)</code> fact.</p>
<p>The verifier will also use an allow policy for the presence of that <code>right</code> (you will see why we separate them in the next section):</p>
<pre><code class="language-prolog">allow if
  blog(#ambient, $blog_id),
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  right(#authority, $blog_id, $article_id, $operation);

// unauthenticated users have read access
allow if
  operation(#ambient, #read);

// catch all rule in case the allow did not match
deny if true;
</code></pre>
<p>So if we tried to do a <code>PUT /blog1/article1</code> with the token containing <code>user(#authority, &quot;user_1234&quot;)</code>, we would end up with the following facts:</p>
<pre><code class="language-prolog">user(#authority, &quot;user_1234&quot;);
blog(#ambient, &quot;blog1&quot;);
article(#ambient, &quot;blog1&quot;, &quot;article1&quot;);
operation(#ambient, #update);
owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;);
owner(#authority, &quot;user_5678&quot;, &quot;blog2&quot;);
owner(#authority, &quot;user_1234&quot;, &quot;blog3&quot;);
</code></pre>
<p>If we applied the verifier&#39;s rule, we would end up with:</p>
<pre><code class="language-prolog">right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #update) &lt;-
    owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;),
    article(#ambient, &quot;blog1&quot;, &quot;article1&quot;),
    user(#authority, &quot;user_1234&quot;),
    operation(#ambient, #update);
</code></pre>
<p>So we end up with the new fact <code>right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #update)</code>.</p>
<p>Now the verifier applies the check:</p>
<pre><code class="language-prolog">allow if
  blog(#ambient, &quot;blog1&quot;),
  article(#ambient, &quot;blog1&quot;, &quot;article1&quot;),
  operation(#ambient, #update),
  right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #update);
</code></pre>
<p>And the test succeeds! If we had tried the request with a token containing <code>user(#authority, &quot;user_5678&quot;)</code>, the rule would not have produced the <code>right()</code> fact, and it would have failed.</p>
<p>Now if we did a <code>GET /blog1/article1</code> request, without being the owner of the blog, we would have matched <code>allow if operation(#ambient, #read)</code>.</p>
<p>But maybe we don&#39;t want to have all articles available by default, maybe some of them are still in writing, so let&#39;s remove that allow policy. We want to mark an article as publicly readable by creating the fact <code>readable(#authority, $blog_id, $article_id)</code>. We can do that with this test:</p>
<pre><code class="language-prolog">allow if
  operation(#ambient, #read),
  article(#ambient, $blog_id, $article_id),
  readable(#authority, $blog_id, $article_id);
</code></pre>
<p>So if we did a <code>GET /blog1/article1</code> request with that article marked as readable, we would get the facts:</p>
<pre><code class="language-prolog">blog(#ambient, &quot;blog1&quot;);
article(#ambient, &quot;blog1&quot;, &quot;article1&quot;);
operation(#ambient, #read);
owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;);
owner(#authority, &quot;user_5678&quot;, &quot;blog2&quot;);
owner(#authority, &quot;user_1234&quot;, &quot;blog3&quot;);
readable(#authority, &quot;blog1&quot;, &quot;article1&quot;);
</code></pre>
<p>The test would apply as follows:</p>
<pre><code class="language-prolog">allow if
  operation(#ambient, #read),
  article(#ambient, &quot;blog1&quot;, &quot;article1&quot;),
  readable(#authority, &quot;blog1&quot;, &quot;article1&quot;);
</code></pre>
<p>And we got access. In a few lines, we created basic rules to protect our blog platform. But users need more features!</p>
<h3 id="add-reviewers">add reviewers</h3>
<p>Often, we&#39;d like to ask friends and colleagues to review articles before they are published. In our system, it could be done in two ways:</p>
<ul>
<li>mint a token containing only <code>right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #read)</code></li>
<li>derive the user&#39;s token, adding a check restricting to the article</li>
</ul>
<p>In the second case, the token would look like this:</p>
<pre><code class="language-text">Block 0 (authority):
  facts: [ user(#authority, &quot;user_1234&quot;) ]
  rules: []
  checks: []

Block 1:
  facts: []
  rules: []
  check: [
    check if article(#ambient, &quot;blog1&quot;, &quot;article1&quot;), operation(#ambient, #read)
  ]
</code></pre>
<p>if we tried to do a <code>PUT /blog1/article1</code>, the verifier&#39;s checks would succeed, but the token&#39;s check would fail, because it does not find the <code>operation(#ambient, #read)</code> fact. But for a <code>GET /blog1/article1</code>, all checks would succeed. The reviewer will not be able to remove the block while keeping a valid signature, so any alteration will result in a failed request.</p>
<h3 id="premium-accounts">premium accounts</h3>
<p>Now some of the blog authors want to make living out of it (come on, it&#39;s 2021, do a newsletter instead) and mark some articles as &quot;premium&quot;, so that only some users can access them.</p>
<p>We can do that by having <code>premium_user(#authority, $user_id, $blog_id)</code> facts and adding a rule on the verifier&#39;s side:</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, #read) &lt;-
  article(#ambient, $blog_id, $article_id),
  premium_readable(#authority, $blog_id, $article_id),
  user(#authority, $user_id),
  premium_user(#authority, $user_id, $blog_id);
</code></pre>
<p>We could even add a feature like <a href="https://lwn.net/">LWN.net</a> where a paying user can share a premium article, by deriving their tokens to only accept that article.</p>
<h3 id="were-a-big-newspaper-now-we-want-roles-and-teams">We&#39;re a big newspaper now, we want roles and teams</h3>
<p>Againt all odds, our blog platform is a smashing success. We need to recruit journalists, editors, copywriters... So now we might need more flexible rights management, maybe some teams and roles?</p>
<p>Let&#39;s define more facts and rules to encode that. As an example, let&#39;s define a &quot;contributor&quot; role that can only read or write articles, while owners are the only ones who can create or delete.</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  contributor(#authority, $user_id, $blog_id),
  [#read, #update].contains($operation);
</code></pre>
<p>What you can see on the last line is an <em>expression</em>: Biscuit&#39;s Datalog implementation can require additional conditions on some values, like a string matching a regular expression, or a date being lower than an expiration date, or here, presence in a set. This rule will only produce if the operation is <code>#read</code> or <code>#update</code>.</p>
<p>Now, we want to define contributor teams to manage them more easily. So we will introduce the <code>team(#authority, $team_id)</code>, <code>member(#authority, $user_id, $team_id)</code> and <code>team_role(#authority, $team_id, $blog_id, #contributor)</code> facts.</p>
<p>Additionally, we insert this rule in the verifier:</p>
<pre><code class="language-prolog">contributor(#authority, $user_id, $blog_id) &lt;-
  user(#authority, $user_id),
  member(#authority, $user_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor);
</code></pre>
<p>This rule will generate the <code>contributor</code> fact for a blog if we are member of a team that has the &quot;contributor&quot; team role.</p>
<p>We could also fold the two precedent rules in one:</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  member(#authority, $user_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor),
  [#read, #write].contains($operation);
</code></pre>
<p>And that&#39;s it! With a few rules, we can model more and more complex authorization patterns, some of them relying on user provided policies, without compromising the previous features. Rules are additive, so there&#39;s no need for a long chain of if/else and special cases hardcoded in some endpoints. Everything can be managed in one place.</p>
<p>To sum up the rules of our system:</p>
<pre><code class="language-prolog">// the owner has all rights
right(#authority, $blog_id, $article_id, $operation) &lt;-
    article(#ambient, $blog_id, $article_id),
    operation(#ambient, $operation),
    user(#authority, $user_id),
    owner(#authority, $user_id, $blog_id);

// premium users can access some restricted articles
right(#authority, $blog_id, $article_id, #read) &lt;-
  article(#ambient, $blog_id, $article_id),
  premium_readable(#authority, $blog_id, $article_id),
  user(#authority, $user_id),
  premium_user(#authority, $user_id, $blog_id);

// define teams and roles
right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  member(#authority, $user_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor),
  [#read, #write].contains($operation);

// unauthenticated users have read access on published articles
allow if
  operation(#ambient, #read),
  article(#ambient, $blog_id, $article_id),
  readable(#authority, $blog_id, $article_id);

// authorize if got the rights on this blog and article
allow if
  blog(#ambient, $blog_id),
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  right(#authority, $blog_id, $article_id, $operation);


// catch all rule in case the allow did not match
deny if true;
</code></pre>
<p>And here is an example Rust program reproducing this authorization system:</p>
<pre><code class="language-rust">use biscuit::{crypto::KeyPair, error, token::Biscuit, parser::parse_source};
use biscuit_auth as biscuit;

fn main() -&gt; Result&lt;(), error::Token&gt; {
    let start = std::time::Instant::now();

    // First, let&#39;s create the root key for the system
    // its public part will be used to verify the token
    let mut rng = rand::thread_rng();
    let root = KeyPair::new();

    // Token creation
    // we will add a single fact indicating identity
    let mut builder = Biscuit::builder(&amp;root);
    builder.add_authority_fact(&quot;user(#authority, \&quot;user_1234\&quot;)&quot;)?;

    let token = builder.build()?;
    println!(&quot;{}&quot;, token.print());
    let token_bytes = token.to_vec()?;
    let serialized = base64::encode_config(&amp;token_bytes, base64::URL_SAFE);
    println!(&quot;serialized ({} bytes): {}&quot;, token_bytes.len(), serialized);

    let deserialized_token = Biscuit::from(&amp;token_bytes)?;
    // Token verification
    // first, we validate the signature with the root public key
    let mut verifier = deserialized_token.verify(root.public())?;

    // simulate verification for PUT /blog1/article1
    verifier.add_fact(&quot;blog(#ambient, \&quot;blog1\&quot;)&quot;)?;
    verifier.add_fact(&quot;article(#ambient, \&quot;blog1\&quot;, \&quot;article1\&quot;)&quot;)?;
    verifier.add_fact(&quot;operation(#ambient, #update)&quot;)?;

    // add ownership information
    // we only need to load facts related to the blog and article we&#39;re accessing
    verifier.add_fact(&quot;owner(#authority, \&quot;user_1234\&quot;, \&quot;blog1\&quot;)&quot;)?;
    //verifier.add_fact(&quot;owner(#authority, \&quot;user_5678\&quot;, \&quot;blog2\&quot;)&quot;)?;
    //verifier.add_fact(&quot;owner(#authority, \&quot;user_1234\&quot;, \&quot;blog3\&quot;)&quot;)?;

    let (_remaining_input, mut policies) = parse_source(&quot;
// the owner has all rights
right(#authority, $blog_id, $article_id, $operation) &lt;-
    article(#ambient, $blog_id, $article_id),
    operation(#ambient, $operation),
    user(#authority, $user_id),
    owner(#authority, $user_id, $blog_id);

// premium users can access some restricted articles
right(#authority, $blog_id, $article_id, #read) &lt;-
  article(#ambient, $blog_id, $article_id),
  premium_readable(#authority, $blog_id, $article_id),
  user(#authority, $user_id),
  premium_user(#authority, $user_id, $blog_id);

// define teams and roles
right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  member(#authority, $usr_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor),
  [#read, #write].contains($operation);

// unauthenticated users have read access on published articles
allow if
  operation(#ambient, #read),
  article(#ambient, $blog_id, $article_id),
  readable(#authority, $blog_id, $article_id);

// authorize if got the rights on this blog and article
allow if
  blog(#ambient, $blog_id),
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  right(#authority, $blog_id, $article_id, $operation);


// catch all rule in case the allow did not match
deny if true;
    &quot;).unwrap();

    for (_span, fact) in policies.facts.drain(..) {
        verifier.add_fact(fact)?;
    }

    for (_span, rule) in policies.rules.drain(..) {
        verifier.add_rule(rule)?;
    }

    for (_span, check) in policies.checks.drain(..) {
        verifier.add_check(check)?;
    }

    for (_span, policy) in policies.policies.drain(..) {
        verifier.add_policy(policy)?;
    }

    let res = verifier.verify()?;
    let dur = std::time::Instant::now() - start;
    //println!(&quot;res: {:?}&quot;, res);
    println!(&quot;{}&quot;, verifier.print_world());

    println!(&quot;ran in {:?}&quot;, dur);
    Ok(())
}
</code></pre>
<p>The entire program (key generation, token creation, serialization, deserialization, signature validation and facts verification) <strong>runs in 0.5 ms</strong>. So even with all of these features, Biscuit is fast enough to get out of your way.</p>
<h2 id="whats-next">What&#39;s next</h2>
<p>You can already start using Biscuit in <a href="https://github.com/clevercloud/biscuit-rust">Rust</a>, <a href="https://github.com/clevercloud/biscuit-java">Java</a> and <a href="https://github.com/flynn/biscuit-go">Go</a>.</p>
<p>The Rust version can also generate C bindings, currently used to develop a <a href="https://github.com/divarvel/biscuit-haskell">Haskell version</a>, and there is a <a href="https://github.com/clevercloud/biscuit-wasm">WebAssembly wrapper</a>.</p>
<p>As an example integration, you can check out a <a href="https://github.com/clevercloud/biscuit-pulsar">Biscuit based authorization plugin</a> for <a href="https://pulsar.apache.org/">Apache Pulsar</a>.</p>
<p>The <a href="https://github.com/clevercloud/biscuit">specification</a> is developed in the open, you can contribute.</p>
<script>
$("table").addClass("table-bordered");
</script>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="biscuit tutorial 1" decoding="async" srcset="https://cdn.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-tutorial-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>In the <a href="https://www.clever.cloud/blog/engineering/2021/04/12/introduction-to-biscuit/">previous article</a>, I introduced Biscuit, our authentication and authorization token, and mentioned its Datalog based language for authorization policies. Let&#39;s see how it works!</p>
<span id="more-2833"></span>

<h2 id="from-a-personal-blog-to-an-entire-newspaper">From a personal blog to an entire newspaper</h2>
<p>As an example, we will build up authorization policies, going from a small, personal blog, to a professional journal with multiple teams, editors, etc.</p>
<p>Since those policies will be written in Datalog, let&#39;s take a short look at that language first.</p>
<h3 id="side-note-introduction-to-datalog">Side note: introduction to Datalog</h3>
<p>Datalog is a declarative logic language that is a subset of Prolog. A Datalog program contains &quot;facts&quot;, which represent data, and &quot;rules&quot;, which can generate new facts from existing ones.</p>
<p>As an example, we could define the following facts, describing some relationships:</p>
<pre><code class="language-prolog">parent(&quot;Alice&quot;, &quot;Bob&quot;);
parent(&quot;Bob&quot;, &quot;Charles&quot;);
parent(&quot;Charles&quot;, &quot;Denise&quot;);
</code></pre>
<p>This means that Alice is Bob&#39;s parent, and so on.</p>
<p>This could be seen as a table in a relational database:</p>
<table class="table">
<thead>
<tr>
<th>parent</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td>Alice</td>
<td>Bob</td>
</tr>
<tr>
<td></td>
<td>Bob</td>
<td>Charles</td>
</tr>
<tr>
<td></td>
<td>Charles</td>
<td>Denise</td>
</tr>
</tbody></table>
<p>We can then define rules to query our data:</p>
<pre><code class="language-prolog">parent_of_charles($name) &lt;-
  parent($name, &quot;Charles&quot;);
</code></pre>
<p>This could be written in SQL as:</p>
<pre><code class="language-sql">SELECT DISTINCT name from parent where child = &quot;Charles&quot;;
</code></pre>
<p>(we use <code>DISTINCT</code> because Datalog will always remove redundant results)</p>
<p>We can also use rules to create new facts, like this one: (variables are introduced with the <code>$</code> sign)</p>
<pre><code class="language-prolog">grandparent($grandparent, $child) &lt;-
  parent($grandparent, $parent),
  parent($parent, $child);
</code></pre>
<p>You can read it as follows:</p>
<pre><code class="language-text">create the fact grandparent($grandparent, $child)
  IF
    there is a fact parent($grandparent, $parent)
    AND there is a fact parent($parent, $child)
    with matching $parent variable
</code></pre>
<p>or in SQL:</p>
<pre><code class="language-sql">INSERT INTO grandparent( name, grandchild )
  SELECT A.name as name, B.child as grandchild
  FROM parent A, parent B
  WHERE A.child = B.name;
</code></pre>
<p>Applying this rule will look at combinations of the <code>parent</code> facts as defined on the right side of the arrow (the &quot;body&quot; of the rule), and try to match them to the variables (<code>$grandparent</code>, <code>$parent</code>, <code>$child</code>):</p>
<ul>
<li><code>parent(&quot;Alice&quot;, &quot;Bob&quot;), parent(&quot;Bob&quot;, &quot;Charles&quot;)</code> matches because we can
replace <code>$grandparent</code> with <code>&quot;Alice&quot;</code>, <code>$parent</code> with <code>&quot;Bob&quot;</code>, <code>$child</code> with <code>&quot;Charles&quot;</code></li>
<li><code>parent(&quot;Alice&quot;, &quot;Bob&quot;), parent(&quot;Charles&quot;, &quot;Denise&quot;)</code> does not match because
we would get different values for the <code>$parent</code> variable</li>
</ul>
<p>For each matching combination of facts in the body, we will then generate a fact, as defined on the left side of the arrow, the <em>head</em> of the rule. For <code>parent(&quot;Alice&quot;, &quot;Bob&quot;), parent(&quot;Bob&quot;, &quot;Charles&quot;)</code>, we would generate <code>grandparent(&quot;Alice&quot;, &quot;Charles&quot;)</code>. A fact can be generated from multiple rules, but we will get only one instance of it.</p>
<p>Going through all the combinations, we will generate:</p>
<pre><code class="language-prolog">grandparent(&quot;Alice&quot;, &quot;Charles&quot;);
grandparent(&quot;Bob&quot;, &quot;Denise&quot;);
</code></pre>
<p>which can be seen as:</p>
<table class="table">
<thead>
<tr>
<th>grandparent</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td>Alice</td>
<td>Charles</td>
</tr>
<tr>
<td></td>
<td>Bob</td>
<td>Denise</td>
</tr>
</tbody></table>
<p>Interactions with a Datalog program are done through queries: <strong>a query contains a rule</strong> that we apply over the system, and <strong>it returns the generated facts</strong>.</p>
<h3 id="first-steps-personal-blog">First steps: personal blog</h3>
<p>*note: you can follow along the various steps of this tutorial in the <a href="https://play-with-biscuit.cleverapps.io/blog.html">online playground</a>.</p>
<p>When we are the only user of that blog, we do not need much (honestly we could get away with just a random string in a cookie, but bear with me). We only need a way to identify ourselves to the blog engine&#39;s admin panel. So we could just consider the Biscuit token as a fancy JWT, that will only contain data (so, in Datalog, facts).</p>
<p>Our token will contain this fact: <code>user(#authority, &quot;user_1234&quot;)</code>.</p>
<p>Here, <code>&quot;user_1234&quot;</code> is our user id, and <code>#authority</code> is a special symbol that can only be added to facts in the first block of a token (or added by the verifier). A block contains facts (data), rules (to generate facts) and checks (queries used to validate the facts). Attenuation is done by adding more blocks. Since <code>#authority</code> facts are about the basic rights of a token, adding <code>#authority</code> facts would increase the number of rights. So we forbid adding <code>#authority</code> facts in additional blocks. Symbols, as indicated by the <code>#</code> prefix, are special strings that are internally replaced with integers, to compress tokens and accelerate evaluation.</p>
<p>The token can be serialized to a byte array (encoded with Protobuf) and then to base64 if we want to carry it in a cookie.</p>
<p>On the blog engine&#39;s side, we will only have this single line:</p>
<pre><code class="language-prolog">allow if user(#authority, &quot;user_1234&quot;);
</code></pre>
<p>Biscuit can enforce authorization in 2 ways:</p>
<ul>
<li>checks, starting with <code>check if</code></li>
<li>allow/deny policies, starting with <code>allow if</code> or <code>deny if</code></li>
</ul>
<p>They work a bit like rules: if there&#39;s at least one combination of fact in the body (after the <code>if</code>) that fits, then it matches. They will not produce any fact.</p>
<p>To validate a token:</p>
<ul>
<li>all of the checks must match. If one does not, fail</li>
<li>allow/deny policies are tried in order until one matches<ul>
<li>if allow matches, succeed</li>
<li>if deny matches, fail</li>
</ul>
</li>
<li>if none match, fail</li>
</ul>
<p>Here the allow test will succeed if the token contains the fact <code>user(#authority, &quot;user_1234&quot;)</code></p>
<p>It is not very useful yet, but maybe we can add more features?</p>
<h3 id="next-multi-blog-platform">Next: multi-blog platform</h3>
<p>After a few friends have seen your marvelous website, they ask if you could host their blogs on the same platform. So now you need more flexible authorization rules. We could keep the small tokens with the user id, but add more intelligence on the server&#39;s side.</p>
<p>First we need to indicate who owns which blog, with the format <code>owner(#authority, $user_id, $blog_id)</code>. You can load this data when creating the verifier, from your database, from static files, etc.</p>
<pre><code class="language-prolog">owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;);
owner(#authority, &quot;user_5678&quot;, &quot;blog2&quot;);
owner(#authority, &quot;user_1234&quot;, &quot;blog3&quot;);
</code></pre>
<p>Here we own <code>&quot;blog1&quot;</code> and <code>&quot;blog3&quot;</code>, and <code>&quot;user_5678&quot;</code> owns <code>&quot;blog2&quot;</code>.</p>
<p>Now we need to actually validate the request, to see who has access to what. The request is represented through the <code>#ambient</code> facts, added to the verifier: you indicate to the verifier facts representing the current request like which resource is accessed, which operation (read, write, etc), the current time, the source IP address, etc. As an example, a <code>PUT /blog1/article1</code> to modify an article could be translated as:</p>
<pre><code class="language-prolog">blog(#ambient, &quot;blog1&quot;);
article(#ambient, &quot;blog1&quot;, &quot;article1&quot;);
operation(#ambient, #update);
</code></pre>
<p>In the verifier, we add a rule to indicate that the owner of a blog has full rights on it:</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, $operation) &lt;-
    article(#ambient, $blog_id, $article_id),
    operation(#ambient, $operation),
    user(#authority, $user_id),
    owner(#authority, $user_id, $blog_id);
</code></pre>
<p>If this rules finds a matching set of facts, it will produce a <code>right(...)</code> fact.</p>
<p>The verifier will also use an allow policy for the presence of that <code>right</code> (you will see why we separate them in the next section):</p>
<pre><code class="language-prolog">allow if
  blog(#ambient, $blog_id),
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  right(#authority, $blog_id, $article_id, $operation);

// unauthenticated users have read access
allow if
  operation(#ambient, #read);

// catch all rule in case the allow did not match
deny if true;
</code></pre>
<p>So if we tried to do a <code>PUT /blog1/article1</code> with the token containing <code>user(#authority, &quot;user_1234&quot;)</code>, we would end up with the following facts:</p>
<pre><code class="language-prolog">user(#authority, &quot;user_1234&quot;);
blog(#ambient, &quot;blog1&quot;);
article(#ambient, &quot;blog1&quot;, &quot;article1&quot;);
operation(#ambient, #update);
owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;);
owner(#authority, &quot;user_5678&quot;, &quot;blog2&quot;);
owner(#authority, &quot;user_1234&quot;, &quot;blog3&quot;);
</code></pre>
<p>If we applied the verifier&#39;s rule, we would end up with:</p>
<pre><code class="language-prolog">right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #update) &lt;-
    owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;),
    article(#ambient, &quot;blog1&quot;, &quot;article1&quot;),
    user(#authority, &quot;user_1234&quot;),
    operation(#ambient, #update);
</code></pre>
<p>So we end up with the new fact <code>right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #update)</code>.</p>
<p>Now the verifier applies the check:</p>
<pre><code class="language-prolog">allow if
  blog(#ambient, &quot;blog1&quot;),
  article(#ambient, &quot;blog1&quot;, &quot;article1&quot;),
  operation(#ambient, #update),
  right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #update);
</code></pre>
<p>And the test succeeds! If we had tried the request with a token containing <code>user(#authority, &quot;user_5678&quot;)</code>, the rule would not have produced the <code>right()</code> fact, and it would have failed.</p>
<p>Now if we did a <code>GET /blog1/article1</code> request, without being the owner of the blog, we would have matched <code>allow if operation(#ambient, #read)</code>.</p>
<p>But maybe we don&#39;t want to have all articles available by default, maybe some of them are still in writing, so let&#39;s remove that allow policy. We want to mark an article as publicly readable by creating the fact <code>readable(#authority, $blog_id, $article_id)</code>. We can do that with this test:</p>
<pre><code class="language-prolog">allow if
  operation(#ambient, #read),
  article(#ambient, $blog_id, $article_id),
  readable(#authority, $blog_id, $article_id);
</code></pre>
<p>So if we did a <code>GET /blog1/article1</code> request with that article marked as readable, we would get the facts:</p>
<pre><code class="language-prolog">blog(#ambient, &quot;blog1&quot;);
article(#ambient, &quot;blog1&quot;, &quot;article1&quot;);
operation(#ambient, #read);
owner(#authority, &quot;user_1234&quot;, &quot;blog1&quot;);
owner(#authority, &quot;user_5678&quot;, &quot;blog2&quot;);
owner(#authority, &quot;user_1234&quot;, &quot;blog3&quot;);
readable(#authority, &quot;blog1&quot;, &quot;article1&quot;);
</code></pre>
<p>The test would apply as follows:</p>
<pre><code class="language-prolog">allow if
  operation(#ambient, #read),
  article(#ambient, &quot;blog1&quot;, &quot;article1&quot;),
  readable(#authority, &quot;blog1&quot;, &quot;article1&quot;);
</code></pre>
<p>And we got access. In a few lines, we created basic rules to protect our blog platform. But users need more features!</p>
<h3 id="add-reviewers">add reviewers</h3>
<p>Often, we&#39;d like to ask friends and colleagues to review articles before they are published. In our system, it could be done in two ways:</p>
<ul>
<li>mint a token containing only <code>right(#authority, &quot;blog1&quot;, &quot;article1&quot;, #read)</code></li>
<li>derive the user&#39;s token, adding a check restricting to the article</li>
</ul>
<p>In the second case, the token would look like this:</p>
<pre><code class="language-text">Block 0 (authority):
  facts: [ user(#authority, &quot;user_1234&quot;) ]
  rules: []
  checks: []

Block 1:
  facts: []
  rules: []
  check: [
    check if article(#ambient, &quot;blog1&quot;, &quot;article1&quot;), operation(#ambient, #read)
  ]
</code></pre>
<p>if we tried to do a <code>PUT /blog1/article1</code>, the verifier&#39;s checks would succeed, but the token&#39;s check would fail, because it does not find the <code>operation(#ambient, #read)</code> fact. But for a <code>GET /blog1/article1</code>, all checks would succeed. The reviewer will not be able to remove the block while keeping a valid signature, so any alteration will result in a failed request.</p>
<h3 id="premium-accounts">premium accounts</h3>
<p>Now some of the blog authors want to make living out of it (come on, it&#39;s 2021, do a newsletter instead) and mark some articles as &quot;premium&quot;, so that only some users can access them.</p>
<p>We can do that by having <code>premium_user(#authority, $user_id, $blog_id)</code> facts and adding a rule on the verifier&#39;s side:</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, #read) &lt;-
  article(#ambient, $blog_id, $article_id),
  premium_readable(#authority, $blog_id, $article_id),
  user(#authority, $user_id),
  premium_user(#authority, $user_id, $blog_id);
</code></pre>
<p>We could even add a feature like <a href="https://lwn.net/">LWN.net</a> where a paying user can share a premium article, by deriving their tokens to only accept that article.</p>
<h3 id="were-a-big-newspaper-now-we-want-roles-and-teams">We&#39;re a big newspaper now, we want roles and teams</h3>
<p>Againt all odds, our blog platform is a smashing success. We need to recruit journalists, editors, copywriters... So now we might need more flexible rights management, maybe some teams and roles?</p>
<p>Let&#39;s define more facts and rules to encode that. As an example, let&#39;s define a &quot;contributor&quot; role that can only read or write articles, while owners are the only ones who can create or delete.</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  contributor(#authority, $user_id, $blog_id),
  [#read, #update].contains($operation);
</code></pre>
<p>What you can see on the last line is an <em>expression</em>: Biscuit&#39;s Datalog implementation can require additional conditions on some values, like a string matching a regular expression, or a date being lower than an expiration date, or here, presence in a set. This rule will only produce if the operation is <code>#read</code> or <code>#update</code>.</p>
<p>Now, we want to define contributor teams to manage them more easily. So we will introduce the <code>team(#authority, $team_id)</code>, <code>member(#authority, $user_id, $team_id)</code> and <code>team_role(#authority, $team_id, $blog_id, #contributor)</code> facts.</p>
<p>Additionally, we insert this rule in the verifier:</p>
<pre><code class="language-prolog">contributor(#authority, $user_id, $blog_id) &lt;-
  user(#authority, $user_id),
  member(#authority, $user_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor);
</code></pre>
<p>This rule will generate the <code>contributor</code> fact for a blog if we are member of a team that has the &quot;contributor&quot; team role.</p>
<p>We could also fold the two precedent rules in one:</p>
<pre><code class="language-prolog">right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  member(#authority, $user_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor),
  [#read, #write].contains($operation);
</code></pre>
<p>And that&#39;s it! With a few rules, we can model more and more complex authorization patterns, some of them relying on user provided policies, without compromising the previous features. Rules are additive, so there&#39;s no need for a long chain of if/else and special cases hardcoded in some endpoints. Everything can be managed in one place.</p>
<p>To sum up the rules of our system:</p>
<pre><code class="language-prolog">// the owner has all rights
right(#authority, $blog_id, $article_id, $operation) &lt;-
    article(#ambient, $blog_id, $article_id),
    operation(#ambient, $operation),
    user(#authority, $user_id),
    owner(#authority, $user_id, $blog_id);

// premium users can access some restricted articles
right(#authority, $blog_id, $article_id, #read) &lt;-
  article(#ambient, $blog_id, $article_id),
  premium_readable(#authority, $blog_id, $article_id),
  user(#authority, $user_id),
  premium_user(#authority, $user_id, $blog_id);

// define teams and roles
right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  member(#authority, $user_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor),
  [#read, #write].contains($operation);

// unauthenticated users have read access on published articles
allow if
  operation(#ambient, #read),
  article(#ambient, $blog_id, $article_id),
  readable(#authority, $blog_id, $article_id);

// authorize if got the rights on this blog and article
allow if
  blog(#ambient, $blog_id),
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  right(#authority, $blog_id, $article_id, $operation);


// catch all rule in case the allow did not match
deny if true;
</code></pre>
<p>And here is an example Rust program reproducing this authorization system:</p>
<pre><code class="language-rust">use biscuit::{crypto::KeyPair, error, token::Biscuit, parser::parse_source};
use biscuit_auth as biscuit;

fn main() -&gt; Result&lt;(), error::Token&gt; {
    let start = std::time::Instant::now();

    // First, let&#39;s create the root key for the system
    // its public part will be used to verify the token
    let mut rng = rand::thread_rng();
    let root = KeyPair::new();

    // Token creation
    // we will add a single fact indicating identity
    let mut builder = Biscuit::builder(&amp;root);
    builder.add_authority_fact(&quot;user(#authority, \&quot;user_1234\&quot;)&quot;)?;

    let token = builder.build()?;
    println!(&quot;{}&quot;, token.print());
    let token_bytes = token.to_vec()?;
    let serialized = base64::encode_config(&amp;token_bytes, base64::URL_SAFE);
    println!(&quot;serialized ({} bytes): {}&quot;, token_bytes.len(), serialized);

    let deserialized_token = Biscuit::from(&amp;token_bytes)?;
    // Token verification
    // first, we validate the signature with the root public key
    let mut verifier = deserialized_token.verify(root.public())?;

    // simulate verification for PUT /blog1/article1
    verifier.add_fact(&quot;blog(#ambient, \&quot;blog1\&quot;)&quot;)?;
    verifier.add_fact(&quot;article(#ambient, \&quot;blog1\&quot;, \&quot;article1\&quot;)&quot;)?;
    verifier.add_fact(&quot;operation(#ambient, #update)&quot;)?;

    // add ownership information
    // we only need to load facts related to the blog and article we&#39;re accessing
    verifier.add_fact(&quot;owner(#authority, \&quot;user_1234\&quot;, \&quot;blog1\&quot;)&quot;)?;
    //verifier.add_fact(&quot;owner(#authority, \&quot;user_5678\&quot;, \&quot;blog2\&quot;)&quot;)?;
    //verifier.add_fact(&quot;owner(#authority, \&quot;user_1234\&quot;, \&quot;blog3\&quot;)&quot;)?;

    let (_remaining_input, mut policies) = parse_source(&quot;
// the owner has all rights
right(#authority, $blog_id, $article_id, $operation) &lt;-
    article(#ambient, $blog_id, $article_id),
    operation(#ambient, $operation),
    user(#authority, $user_id),
    owner(#authority, $user_id, $blog_id);

// premium users can access some restricted articles
right(#authority, $blog_id, $article_id, #read) &lt;-
  article(#ambient, $blog_id, $article_id),
  premium_readable(#authority, $blog_id, $article_id),
  user(#authority, $user_id),
  premium_user(#authority, $user_id, $blog_id);

// define teams and roles
right(#authority, $blog_id, $article_id, $operation) &lt;-
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  user(#authority, $user_id),
  member(#authority, $usr_id, $team_id),
  team_role(#authority, $team_id, $blog_id, #contributor),
  [#read, #write].contains($operation);

// unauthenticated users have read access on published articles
allow if
  operation(#ambient, #read),
  article(#ambient, $blog_id, $article_id),
  readable(#authority, $blog_id, $article_id);

// authorize if got the rights on this blog and article
allow if
  blog(#ambient, $blog_id),
  article(#ambient, $blog_id, $article_id),
  operation(#ambient, $operation),
  right(#authority, $blog_id, $article_id, $operation);


// catch all rule in case the allow did not match
deny if true;
    &quot;).unwrap();

    for (_span, fact) in policies.facts.drain(..) {
        verifier.add_fact(fact)?;
    }

    for (_span, rule) in policies.rules.drain(..) {
        verifier.add_rule(rule)?;
    }

    for (_span, check) in policies.checks.drain(..) {
        verifier.add_check(check)?;
    }

    for (_span, policy) in policies.policies.drain(..) {
        verifier.add_policy(policy)?;
    }

    let res = verifier.verify()?;
    let dur = std::time::Instant::now() - start;
    //println!(&quot;res: {:?}&quot;, res);
    println!(&quot;{}&quot;, verifier.print_world());

    println!(&quot;ran in {:?}&quot;, dur);
    Ok(())
}
</code></pre>
<p>The entire program (key generation, token creation, serialization, deserialization, signature validation and facts verification) <strong>runs in 0.5 ms</strong>. So even with all of these features, Biscuit is fast enough to get out of your way.</p>
<h2 id="whats-next">What&#39;s next</h2>
<p>You can already start using Biscuit in <a href="https://github.com/clevercloud/biscuit-rust">Rust</a>, <a href="https://github.com/clevercloud/biscuit-java">Java</a> and <a href="https://github.com/flynn/biscuit-go">Go</a>.</p>
<p>The Rust version can also generate C bindings, currently used to develop a <a href="https://github.com/divarvel/biscuit-haskell">Haskell version</a>, and there is a <a href="https://github.com/clevercloud/biscuit-wasm">WebAssembly wrapper</a>.</p>
<p>As an example integration, you can check out a <a href="https://github.com/clevercloud/biscuit-pulsar">Biscuit based authorization plugin</a> for <a href="https://pulsar.apache.org/">Apache Pulsar</a>.</p>
<p>The <a href="https://github.com/clevercloud/biscuit">specification</a> is developed in the open, you can contribute.</p>
<script>
$("table").addClass("table-bordered");
</script>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Biscuit, the foundation for your authorization systems</title>
		<link>https://www.clever.cloud/blog/engineering/2021/04/12/introduction-to-biscuit/</link>
		
		<dc:creator><![CDATA[Geoffroy Couprie]]></dc:creator>
		<pubDate>Mon, 12 Apr 2021 09:45:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[authorization]]></category>
		<category><![CDATA[biscuit]]></category>
		<category><![CDATA[cryptography]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2021/04/12/introduction-to-biscuit/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/biscuit-introduction-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="biscuit introduction 1" decoding="async" srcset="https://cdn.clever-cloud.com/uploads/2021/08/biscuit-introduction-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-1368x528.png 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>After 2 years of development, I am proud to share with you the official release of Biscuit, the authentication and authorization token we develop to manage access to our systems.</p>
<span id="more-2832"></span>

<p>Where does it fit in the current authentication projects landscape (and why all of those cake themed names)?</p>
<ul>
<li>Cookies are a storage area in browsers, which can contain a session identifier
(the session data is then in a database, indexed by those identifiers), or
authentication tokens. They&#39;re good with lots of chocolate chips.</li>
<li><a href="https://jwt.io/">JSON Web Tokens</a> or JWT
(<a href="https://tools.ietf.org/html/rfc7519#section-1">pronounced &quot;jot&quot;</a>) contain
cryptographically signed data. Since the signature guarantees it has not been
modified, a web application could store session data in a JWT and send it in
a cookie, and read it from HTTP requests. The signature can be done with
secret key cryptography (HMAC algorithm), or public key cryptography (RSA,
ECDSA). They can even be encrypted, and stored in a cookie, but they cannot be
eaten.</li>
<li><a href="https://research.google/pubs/pub41892/">Macaroons</a> are cryptographically
signed (HMAC) tokens focused on authorization. They embed <em>caveats</em>, conditions
that the request must fit. They support attenuation: the holder of a token can
create a new valid token by adding a caveat, further restricting the token. A
macaroon can be stored in a cookie. It is also an Italian almond or coconut-based cake (do not confuse it with the French <em>macaron</em> which is also an almond
based cake)</li>
<li><a href="https://www.openpolicyagent.org/">Open Policy Agent</a> is a server-side logic
language used to encode authorization policies</li>
</ul>
<p>Biscuit unifies these various approaches:</p>
<ul>
<li>it can be signed with public key or secret key cryptography like JWT</li>
<li>it can be attenuated like Macaroons</li>
<li>it comes with a powerful logic language to write authorization policies, like OPA, but those policies can also be carried by the token</li>
</ul>
<p>By assembling those techniques, it opens up an array of authorization patterns that were not possible before.</p>
<p><img src="https://cdn.clever-cloud.com/uploads/2021/08/token_disambiguation.jpg" alt=""></p>
<p>When we started working on Biscuit, we were battling common issues in modern web applications:</p>
<ul>
<li>In a microservices system, how do you handle authorization from an initial
request, as it goes from service to service?</li>
<li>How do you reconcile an application&#39;s authorization policies (often some basic
roles and groups) with a client&#39;s organization chart?</li>
</ul>
<p>The microservices case is tricky: the initial request may come from a user for which we can look up a list of rights, but some services in the request tree may not even have a concept of user: at Clever Cloud, the service that launches virtual machines never hears about who requested a new deployment. With JWT, you could generate a temporary token in the user-facing API, and carry that from service to service. But then, any service holding that token has the entire set of rights for that request. Also, we need to make sure the authorization policies are evaluated in the same way in all services. With Macaroons, a service can attenuate the token before sending it to the next service, by adding a <em>caveat</em>, a condition over the current request (expiration date, limiting to read operations, restricting file paths to a prefix...). Unfortunately, Macaroon validation requires knowing the secret key used to generate the initial token.</p>
<p>Macaroons use a design based on chaining HMAC calculations: start from the initial secret, sign the first caveat, then for each new caveat, sign it using the previous signature as key. If you know the initial secret key, you can reconstruct the entire chain and verify that you obtain the same initial signature. But distributing that key in every service is a security risk: if someone gets access to this key, they can create a token with any authorization level they want. On the other side, JWT only requires verifiers to know a public key, and the private key can be kept in the service creating the token.</p>
<p>That was one of the motivating goals for Biscuit: <strong>what if we could attenuate the token, but still be able to verify it with public key cryptography?</strong></p>
<p>As it turns out, a cryptographic concept called <em>aggregated signatures</em> can help us: we take multiple messages, each individually signed with a different public key, and we aggregate all of those signatures into one main signature. From that aggregated signature, it is impossible to remove one of the messages and keep a valid signature, but we can always add more signed messages. We can verify the aggregated signatures if we know the public keys for each message. From this, we reproduce the Macaroon design, with public key cryptography.</p>
<p>To provide attenuation, we could have reused the Macaroons approach with caveats, but its user experience was challenging: a caveat is basically a byte array for which you must design your own system to encode and test conditions.</p>
<p>For Biscuit, we chose a more general approach. We provide a logic language based on Datalog to write authorization policies. It can store data, like JWT, or small conditions like Macaroons, but it is also able to represent more complex rules like role-based access control, delegation, hierarchies. Those authorization policies can be carried by the token or provided on the verification side. They are encoded in a small binary format for transport. Additionally, it is fast to evaluate: generally, the entire process of checking the signature, deserializing the token and testing the authorization policies is done under 1 ms.</p>
<figure>
<img alt="Example Datalog rule" src="https://cdn.clever-cloud.com/uploads/2021/08/biscuit-datalog-example.png"/>
  <figcaption>Example Datalog rule</figcaption>
</figure>

<p>With this language (that can be learned in minutes), you get a unified way of representing complex business rules, in a testable and portable format. You can explore how policies work in a simulate environment, even write unit tests for them, then deploy them as dry-run tests and see how they would react on real world requests. Instead of a binary allow/deny result, you can gain fine-grained info, and query structured data. As an example, a request to list files would be accepted if we have the rights for it, and we can also get the filtered list of files we can access, even taking into account the attenuation rules carried by the token.</p>
<p>Multiple rule systems can be combined, which is useful for the second problem, about the mismatch between an application&#39;s policies and its user&#39;s needs:</p>
<ul>
<li>an application using GitHub or Twitter OAuth and requesting too many rights
because to get a subset of rights like read access to a repository, you get
it for all repositories</li>
<li>a SaaS application or hosting company for which all users from one client
share one account</li>
<li>or roles and groups that do not match work segmentation for users</li>
</ul>
<p>Traditionally, this is solved in two ways:</p>
<ul>
<li>the service includes more and more complicated authorization policies and the
user management panel becomes a complicated mess</li>
<li>it connects itself to external authorization systems, like Active Directory
or Keycloak, and let the user manage them</li>
</ul>
<p>With Biscuit, there&#39;s another way. Authorization policies can be provided by the verification service, but they can also be carried by the token. The service can specify its policies, and the user can attenuate tokens with their own policies. And they will all be evaluated in the same way, while guaranteeing that the token cannot get more rights with user policies. So from an initial token, an entire parallel authorization design can be developed that will still be compatible with the original one.</p>
<p>You can also take an existing token, and restrict its access to a minimal set of resources, like you would need for your CI/CD systems. There&#39;s a lot of new patterns that will become possible with Biscuit, and we&#39;ll have to explore it more in the future. Right now, let&#39;s look at an existing use case.</p>
<h2 id="example">Example</h2>
<p>At Clever Cloud, we are heavy users of <a href="https://pulsar.apache.org/">Apache Pulsar</a>. To provide this service to our users, we needed a flexible way to make it multitenant. By integrating Biscuit as an authorization plugin, using the Java implementation of Biscuit, we can provide a separate namespace for each user, but that token has full rights on that namespace. From there, the token can be attenuated to new tokens with various policies:</p>
<ul>
<li>limiting access to a topic name prefix</li>
<li>allowing subscription on only one topic</li>
<li>allowing message production on only one topic</li>
<li>adding an expiration time</li>
</ul>
<p>The authorization plugin only needs to check the token&#39;s initial rights to the namespace, and verify that the request matches the various checks added in attenuation.</p>
<p>As an example, we use that internally for a remote administration agent. Each new instance of the agent gets a new token derived from the original one, restricted to listening on its own topic (the topic name is a UUID). Then, when it receives a message, it also gets a short-lived token that can be used to send answers to a single temporary topic.</p>
<h2 id="whats-next">What&#39;s next</h2>
<p>The next article will dive into how to write policies and how to integrate it into your application. You can already test that language in the <a href="https://play-with-biscuit.cleverapps.io/">online playground</a>.</p>
<p>You can start using Biscuit right now in <a href="https://github.com/clevercloud/biscuit-rust">Rust</a>, <a href="https://github.com/clevercloud/biscuit-java">Java</a> and <a href="https://github.com/flynn/biscuit-go">Go</a>.</p>
<p>The Rust version can also generate C bindings, currently used to develop a <a href="https://github.com/divarvel/biscuit-haskell">Haskell version</a>, and there is a <a href="https://github.com/clevercloud/biscuit-wasm">WebAssembly wrapper</a>.</p>
<p>As an example integration, you can check out a <a href="https://github.com/clevercloud/biscuit-pulsar">Biscuit based authorization plugin</a> for <a href="https://pulsar.apache.org/">Apache Pulsar</a>.</p>
<p>The <a href="https://github.com/clevercloud/biscuit">specification</a> is developed in the open, you can contribute.</p>
<p>We are just at the beginning of this exciting new technology, so we are still learning how to use it, exploring new design and authorization patterns. I can&#39;t wait to see the fun applications you will come up with Biscuit!</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/biscuit-introduction-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="biscuit introduction 1" decoding="async" loading="lazy" srcset="https://cdn.clever-cloud.com/uploads/2021/08/biscuit-introduction-1.png 1400w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-300x116.png 300w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-1024x395.png 1024w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-768x296.png 768w, https://cdn.clever-cloud.com/uploads/2021/08/biscuit-introduction-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>After 2 years of development, I am proud to share with you the official release of Biscuit, the authentication and authorization token we develop to manage access to our systems.</p>
<span id="more-2832"></span>

<p>Where does it fit in the current authentication projects landscape (and why all of those cake themed names)?</p>
<ul>
<li>Cookies are a storage area in browsers, which can contain a session identifier
(the session data is then in a database, indexed by those identifiers), or
authentication tokens. They&#39;re good with lots of chocolate chips.</li>
<li><a href="https://jwt.io/">JSON Web Tokens</a> or JWT
(<a href="https://tools.ietf.org/html/rfc7519#section-1">pronounced &quot;jot&quot;</a>) contain
cryptographically signed data. Since the signature guarantees it has not been
modified, a web application could store session data in a JWT and send it in
a cookie, and read it from HTTP requests. The signature can be done with
secret key cryptography (HMAC algorithm), or public key cryptography (RSA,
ECDSA). They can even be encrypted, and stored in a cookie, but they cannot be
eaten.</li>
<li><a href="https://research.google/pubs/pub41892/">Macaroons</a> are cryptographically
signed (HMAC) tokens focused on authorization. They embed <em>caveats</em>, conditions
that the request must fit. They support attenuation: the holder of a token can
create a new valid token by adding a caveat, further restricting the token. A
macaroon can be stored in a cookie. It is also an Italian almond or coconut-based cake (do not confuse it with the French <em>macaron</em> which is also an almond
based cake)</li>
<li><a href="https://www.openpolicyagent.org/">Open Policy Agent</a> is a server-side logic
language used to encode authorization policies</li>
</ul>
<p>Biscuit unifies these various approaches:</p>
<ul>
<li>it can be signed with public key or secret key cryptography like JWT</li>
<li>it can be attenuated like Macaroons</li>
<li>it comes with a powerful logic language to write authorization policies, like OPA, but those policies can also be carried by the token</li>
</ul>
<p>By assembling those techniques, it opens up an array of authorization patterns that were not possible before.</p>
<p><img src="https://cdn.clever-cloud.com/uploads/2021/08/token_disambiguation.jpg" alt=""></p>
<p>When we started working on Biscuit, we were battling common issues in modern web applications:</p>
<ul>
<li>In a microservices system, how do you handle authorization from an initial
request, as it goes from service to service?</li>
<li>How do you reconcile an application&#39;s authorization policies (often some basic
roles and groups) with a client&#39;s organization chart?</li>
</ul>
<p>The microservices case is tricky: the initial request may come from a user for which we can look up a list of rights, but some services in the request tree may not even have a concept of user: at Clever Cloud, the service that launches virtual machines never hears about who requested a new deployment. With JWT, you could generate a temporary token in the user-facing API, and carry that from service to service. But then, any service holding that token has the entire set of rights for that request. Also, we need to make sure the authorization policies are evaluated in the same way in all services. With Macaroons, a service can attenuate the token before sending it to the next service, by adding a <em>caveat</em>, a condition over the current request (expiration date, limiting to read operations, restricting file paths to a prefix...). Unfortunately, Macaroon validation requires knowing the secret key used to generate the initial token.</p>
<p>Macaroons use a design based on chaining HMAC calculations: start from the initial secret, sign the first caveat, then for each new caveat, sign it using the previous signature as key. If you know the initial secret key, you can reconstruct the entire chain and verify that you obtain the same initial signature. But distributing that key in every service is a security risk: if someone gets access to this key, they can create a token with any authorization level they want. On the other side, JWT only requires verifiers to know a public key, and the private key can be kept in the service creating the token.</p>
<p>That was one of the motivating goals for Biscuit: <strong>what if we could attenuate the token, but still be able to verify it with public key cryptography?</strong></p>
<p>As it turns out, a cryptographic concept called <em>aggregated signatures</em> can help us: we take multiple messages, each individually signed with a different public key, and we aggregate all of those signatures into one main signature. From that aggregated signature, it is impossible to remove one of the messages and keep a valid signature, but we can always add more signed messages. We can verify the aggregated signatures if we know the public keys for each message. From this, we reproduce the Macaroon design, with public key cryptography.</p>
<p>To provide attenuation, we could have reused the Macaroons approach with caveats, but its user experience was challenging: a caveat is basically a byte array for which you must design your own system to encode and test conditions.</p>
<p>For Biscuit, we chose a more general approach. We provide a logic language based on Datalog to write authorization policies. It can store data, like JWT, or small conditions like Macaroons, but it is also able to represent more complex rules like role-based access control, delegation, hierarchies. Those authorization policies can be carried by the token or provided on the verification side. They are encoded in a small binary format for transport. Additionally, it is fast to evaluate: generally, the entire process of checking the signature, deserializing the token and testing the authorization policies is done under 1 ms.</p>
<figure>
<img alt="Example Datalog rule" src="https://cdn.clever-cloud.com/uploads/2021/08/biscuit-datalog-example.png"/>
  <figcaption>Example Datalog rule</figcaption>
</figure>

<p>With this language (that can be learned in minutes), you get a unified way of representing complex business rules, in a testable and portable format. You can explore how policies work in a simulate environment, even write unit tests for them, then deploy them as dry-run tests and see how they would react on real world requests. Instead of a binary allow/deny result, you can gain fine-grained info, and query structured data. As an example, a request to list files would be accepted if we have the rights for it, and we can also get the filtered list of files we can access, even taking into account the attenuation rules carried by the token.</p>
<p>Multiple rule systems can be combined, which is useful for the second problem, about the mismatch between an application&#39;s policies and its user&#39;s needs:</p>
<ul>
<li>an application using GitHub or Twitter OAuth and requesting too many rights
because to get a subset of rights like read access to a repository, you get
it for all repositories</li>
<li>a SaaS application or hosting company for which all users from one client
share one account</li>
<li>or roles and groups that do not match work segmentation for users</li>
</ul>
<p>Traditionally, this is solved in two ways:</p>
<ul>
<li>the service includes more and more complicated authorization policies and the
user management panel becomes a complicated mess</li>
<li>it connects itself to external authorization systems, like Active Directory
or Keycloak, and let the user manage them</li>
</ul>
<p>With Biscuit, there&#39;s another way. Authorization policies can be provided by the verification service, but they can also be carried by the token. The service can specify its policies, and the user can attenuate tokens with their own policies. And they will all be evaluated in the same way, while guaranteeing that the token cannot get more rights with user policies. So from an initial token, an entire parallel authorization design can be developed that will still be compatible with the original one.</p>
<p>You can also take an existing token, and restrict its access to a minimal set of resources, like you would need for your CI/CD systems. There&#39;s a lot of new patterns that will become possible with Biscuit, and we&#39;ll have to explore it more in the future. Right now, let&#39;s look at an existing use case.</p>
<h2 id="example">Example</h2>
<p>At Clever Cloud, we are heavy users of <a href="https://pulsar.apache.org/">Apache Pulsar</a>. To provide this service to our users, we needed a flexible way to make it multitenant. By integrating Biscuit as an authorization plugin, using the Java implementation of Biscuit, we can provide a separate namespace for each user, but that token has full rights on that namespace. From there, the token can be attenuated to new tokens with various policies:</p>
<ul>
<li>limiting access to a topic name prefix</li>
<li>allowing subscription on only one topic</li>
<li>allowing message production on only one topic</li>
<li>adding an expiration time</li>
</ul>
<p>The authorization plugin only needs to check the token&#39;s initial rights to the namespace, and verify that the request matches the various checks added in attenuation.</p>
<p>As an example, we use that internally for a remote administration agent. Each new instance of the agent gets a new token derived from the original one, restricted to listening on its own topic (the topic name is a UUID). Then, when it receives a message, it also gets a short-lived token that can be used to send answers to a single temporary topic.</p>
<h2 id="whats-next">What&#39;s next</h2>
<p>The next article will dive into how to write policies and how to integrate it into your application. You can already test that language in the <a href="https://play-with-biscuit.cleverapps.io/">online playground</a>.</p>
<p>You can start using Biscuit right now in <a href="https://github.com/clevercloud/biscuit-rust">Rust</a>, <a href="https://github.com/clevercloud/biscuit-java">Java</a> and <a href="https://github.com/flynn/biscuit-go">Go</a>.</p>
<p>The Rust version can also generate C bindings, currently used to develop a <a href="https://github.com/divarvel/biscuit-haskell">Haskell version</a>, and there is a <a href="https://github.com/clevercloud/biscuit-wasm">WebAssembly wrapper</a>.</p>
<p>As an example integration, you can check out a <a href="https://github.com/clevercloud/biscuit-pulsar">Biscuit based authorization plugin</a> for <a href="https://pulsar.apache.org/">Apache Pulsar</a>.</p>
<p>The <a href="https://github.com/clevercloud/biscuit">specification</a> is developed in the open, you can contribute.</p>
<p>We are just at the beginning of this exciting new technology, so we are still learning how to use it, exploring new design and authorization patterns. I can&#39;t wait to see the fun applications you will come up with Biscuit!</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
