<p>Here are the new constants that Craft 3.2 introduced:</p>

<pre><code>const ALLOW_ANONYMOUS_NEVER = 0;
const ALLOW_ANONYMOUS_LIVE = 1;
const ALLOW_ANONYMOUS_OFFLINE = 2;
</code></pre>

<p>By default every controller will have the following property:</p>

<pre><code>protected $allowAnonymous = self::ALLOW_ANONYMOUS_NEVER;
</code></pre>

<p>And you can override it in your controller in various ways:</p>

<pre><code>// Allow anonymous access to all actions only when the site is live
public $allowAnonymous = true;

// Allow anonymous access to the `preview` action only when the site is live
public $allowAnonymous = ['preview'];

// Allow anonymous access to the `preview` action only when the site is live
public $allowAnonymous = ['preview' =&gt; self::ALLOW_ANONYMOUS_LIVE];

// Allow anonymous access to the `preview` action only when the site is offline
public $allowAnonymous = ['preview' =&gt; self::ALLOW_ANONYMOUS_OFFLINE];

// Allow anonymous access to the `preview` action when the site is live or offline
public $allowAnonymous = ['preview' =&gt; self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE];
</code></pre>

<p>The single pipeline <code>|</code> is a bitwise OR operator. It compares each bit (a binary digit of 0 or 1) in the integers and returns a new integer with a 1 wherever <em>either</em> numbers had a 1, and a 0 anywhere else (similar to how the <code>||</code> operator campares booleans). So the expression <code>self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE</code> is the same as <code>1 | 2</code> and will evaluate to <code>3</code>. Here are some examples of how the <code>|</code> bitwise operator works:</p>

<pre><code>( 0 = 0000) | ( 0 = 0000) =&gt; ( 0 = 0000)
( 0 = 0000) | ( 1 = 0001) =&gt; ( 1 = 0001)
( 0 = 0000) | ( 2 = 0010) =&gt; ( 2 = 0010)
( 1 = 0001) | ( 1 = 0001) =&gt; ( 1 = 0001)
( 1 = 0001) | ( 2 = 0010) =&gt; ( 3 = 0011)
( 2 = 0010) | ( 2 = 0010) =&gt; ( 2 = 0010)
</code></pre>

<p>The <code>init()</code> method of the Craft base controller now normalizes the value as follows:</p>

<pre><code>// Normalize $allowAnonymous
if (is_bool($this-&gt;allowAnonymous)) {
    $this-&gt;allowAnonymous = (int)$this-&gt;allowAnonymous;
} else if (is_array($this-&gt;allowAnonymous)) {
    $normalized = [];
    foreach ($this-&gt;allowAnonymous as $k =&gt; $v) {
        if (
            (is_int($k) &amp;&amp; !is_string($v)) ||
            (is_string($k) &amp;&amp; !is_int($v))
        ) {
            throw new InvalidArgumentException("Invalid \$allowAnonymous value for key \"{$k}\"");
        }
        if (is_int($k)) {
            $normalized[$v] = self::ALLOW_ANONYMOUS_LIVE;
        } else {
            $normalized[$k] = $v;
        }
    }
    $this-&gt;allowAnonymous = $normalized;
} else if (!is_int($this-&gt;allowAnonymous)) {
    throw new InvalidConfigException('Invalid $allowAnonymous value');
}
</code></pre>

<p><em>Source: <a href="https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L75-L96" rel="noreferrer">https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L75-L96</a></em></p>

<p>So if the value is a boolean then <code>false</code> will be normalized to <code>0</code>, whereas <code>true</code> will be normalized to <code>1</code>.</p>

<p>If the value is an array then each key-value pair in the array will be inspected. If the key is an integer then the value is set to <code>1</code>, for example:</p>

<pre><code>public $allowAnonymous = ['preview'];
</code></pre>

<p>equates to</p>

<pre><code>public $allowAnonymous = [0 =&gt; 'preview'];
</code></pre>

<p>and is interpreted as </p>

<pre><code>public $allowAnonymous = ['preview' =&gt; self::ALLOW_ANONYMOUS_LIVE];
</code></pre>

<p>If the key is a not an integer then the key-value pair is left as is.</p>

<p>Here is how <code>$allowAnonymous</code> is enforced:</p>

<pre><code>// Enforce $allowAnonymous
$isLive = Craft::$app-&gt;getIsLive();
$test = $isLive ? self::ALLOW_ANONYMOUS_LIVE : self::ALLOW_ANONYMOUS_OFFLINE;

if (is_int($this-&gt;allowAnonymous)) {
    $allowAnonymous = $this-&gt;allowAnonymous;
} else {
    $allowAnonymous = $this-&gt;allowAnonymous[$action-&gt;id] ?? self::ALLOW_ANONYMOUS_NEVER;
}

if (!($test &amp; $allowAnonymous)) {
    // Prevent access unless the user is logged in and has the required permissions to view the site
}
</code></pre>

<p><em>Source: <a href="https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L147-L176" rel="noreferrer">https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L147-L176</a></em></p>

<p>The single ampersand <code>&amp;</code> is a bitwise AND operator. It compares each bit in the integers and returns a new integer with a 1 wherever <em>both</em> numbers have a 1, and a 0 anywhere else (similar to how the <code>&amp;&amp;</code> operator campares booleans). Here are some examples of how the <code>&amp;</code> bitwise operator works:</p>

<pre><code>( 0 = 0000) &amp; ( 0 = 0000) =&gt; ( 0 = 0000) =&gt; false
( 0 = 0000) &amp; ( 1 = 0001) =&gt; ( 0 = 0000) =&gt; false
( 0 = 0000) &amp; ( 2 = 0010) =&gt; ( 0 = 0000) =&gt; false
( 1 = 0001) &amp; ( 1 = 0001) =&gt; ( 1 = 0001) =&gt; true
( 1 = 0001) &amp; ( 2 = 0010) =&gt; ( 0 = 0000) =&gt; false
( 2 = 0010) &amp; ( 2 = 0010) =&gt; ( 2 = 0010) =&gt; true
( 3 = 0011) &amp; ( 1 = 0001) =&gt; ( 1 = 0001) =&gt; true
( 3 = 0011) &amp; ( 2 = 0010) =&gt; ( 2 = 0010) =&gt; true
( 3 = 0011) &amp; ( 3 = 0011) =&gt; ( 3 = 0011) =&gt; true
</code></pre>

<p>By enforcing the condition <code>$test &amp; $allowAnonymous</code>, we can check that <code>$test</code> (whether the site is live or offline) and <code>$allowAnonymous</code> (the permissions granted to the specific controller action) overlap.</p>

<p>More on bitwise operators <a href="https://www.php.net/manual/en/language.operators.bitwise.php" rel="noreferrer">here</a>.</p>

<hr>

<p>I'm not sure what the specific issue with your plugin is , but as far as I can tell the only thing that changed in Craft 3.2 was that the <code>ALLOW_ANONYMOUS_OFFLINE</code> constant was added, allowing for (but not requiring) more specific permissions on controller actions.</p>

CC BY-SA 4.0
2019-07-15T15:04:54.787Z
It appears the issue we had in Sprout Forms was because we were not calling `parent::init();` in our init method. Adding that allows us to remove the `self::ALLOW_ANONYMOUS_LIVE` addition and if it was in place to begin with, no change would have been necessary.
Ben Parizek
CC BY-SA 4.0
2019-07-15T15:06:11.210Z
Also, thanks for the break down of how the strings get translated. Nice detail.
Ben Parizek
CC BY-SA 4.0
2019-07-15T15:25:01.150Z
Yeah that must have been it. In Craft and Yii, if you ever override the `init()` method then you should always call the parent method with `parent::init()` :)
Ben Croker
CC BY-SA 4.0
2019-07-15T14:30:49.617Z
2019-07-19T16:00:40.577Z
2019-07-19T16:00:40.577Z
Ben Croker
<p>Craft 3.2 updates how the <code>allowAnonymous</code> behavior works. I have things working in our plugins but I don't understand the different syntaxes needed across our different <code>allowAnonymous</code> use cases.</p>

<p>For example, Sprout Forms fails to submit unless we update the action to use the new <code>self::ALLOW_ANONYMOUS_LIVE</code> setting. However, Sprout SEO XML Sitemaps work fine without any updates. When I look through Craft I see some methods using the conventions (install controller, preview controller) and others not using any new conventions (generate thumb, live preview controller)</p>

<p>In one case, the Sprout Address Field controller, the prefix action- seems to matter now and removing it alone, gets things updated and working again:</p>

<pre class="lang-php prettyprint-override"><code>// Failure while logged out
protected $allowAnonymous = [
    'action-update-address-form-html'
];

// Success while logged out
protected $allowAnonymous = [
    'update-address-form-html'
];

// Success while logged out
protected $allowAnonymous = [
    'update-address-form-html' =&gt; self::ALLOW_ANONYMOUS_LIVE
];
</code></pre>

<p>The general question is: what has been updated with the <code>allowAnonymous</code> behavior in Craft 3.2 and what scenarios does it require that we use the additional configuration settings such as <code>ALLOW_ANONYMOUS_LIVE</code> and <code>ALLOW_ANONYMOUS_OFFLINE</code>?</p>

<plugin-development><form><controller>
What are the different scenarios to plan for when using $allowAnonymous in a controller?
# What are the different scenarios to plan for when using $allowAnonymous in a controller?

(Asked by: username_0 on 2019-07-09)

Craft 3.2 updates how the allowAnonymous behavior works. I have things working in our plugins but I don't understand the different syntaxes needed across our different allowAnonymous use cases.
For example, Sprout Forms fails to submit unless we update the action to use the new self::ALLOW_ANONYMOUS_LIVE setting. However, Sprout SEO XML Sitemaps work fine without any updates. When I look through Craft I see some methods using the conventions (install controller, preview controller) and others not using any new conventions (generate thumb, live preview controller)
In one case, the Sprout Address Field controller, the prefix action- seems to matter now and removing it alone, gets things updated and working again:
// Failure while logged out
protected $allowAnonymous = [
    'action-update-address-form-html'
];

// Success while logged out
protected $allowAnonymous = [
    'update-address-form-html'
];

// Success while logged out
protected $allowAnonymous = [
    'update-address-form-html' => self::ALLOW_ANONYMOUS_LIVE
];

The general question is: what has been updated with the allowAnonymous behavior in Craft 3.2 and what scenarios does it require that we use the additional configuration settings such as ALLOW_ANONYMOUS_LIVE and ALLOW_ANONYMOUS_OFFLINE?

**Tags:** plugin-development, form, controller

---

## 1 answers

### Answer by username_1 on 2019-07-15. Score: 8 | Accepted answer

Here are the new constants that Craft 3.2 introduced:
const ALLOW_ANONYMOUS_NEVER = 0;
const ALLOW_ANONYMOUS_LIVE = 1;
const ALLOW_ANONYMOUS_OFFLINE = 2;

By default every controller will have the following property:
protected $allowAnonymous = self::ALLOW_ANONYMOUS_NEVER;

And you can override it in your controller in various ways:
// Allow anonymous access to all actions only when the site is live
public $allowAnonymous = true;

// Allow anonymous access to the `preview` action only when the site is live
public $allowAnonymous = ['preview'];

// Allow anonymous access to the `preview` action only when the site is live
public $allowAnonymous = ['preview' => self::ALLOW_ANONYMOUS_LIVE];

// Allow anonymous access to the `preview` action only when the site is offline
public $allowAnonymous = ['preview' => self::ALLOW_ANONYMOUS_OFFLINE];

// Allow anonymous access to the `preview` action when the site is live or offline
public $allowAnonymous = ['preview' => self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE];

The single pipeline | is a bitwise OR operator. It compares each bit (a binary digit of 0 or 1) in the integers and returns a new integer with a 1 wherever either numbers had a 1, and a 0 anywhere else (similar to how the || operator campares booleans). So the expression self::ALLOW_ANONYMOUS_LIVE | self::ALLOW_ANONYMOUS_OFFLINE is the same as 1 | 2 and will evaluate to 3. Here are some examples of how the | bitwise operator works:
( 0 = 0000) | ( 0 = 0000) => ( 0 = 0000)
( 0 = 0000) | ( 1 = 0001) => ( 1 = 0001)
( 0 = 0000) | ( 2 = 0010) => ( 2 = 0010)
( 1 = 0001) | ( 1 = 0001) => ( 1 = 0001)
( 1 = 0001) | ( 2 = 0010) => ( 3 = 0011)
( 2 = 0010) | ( 2 = 0010) => ( 2 = 0010)

The init() method of the Craft base controller now normalizes the value as follows:
// Normalize $allowAnonymous
if (is_bool($this->allowAnonymous)) {
    $this->allowAnonymous = (int)$this->allowAnonymous;
} else if (is_array($this->allowAnonymous)) {
    $normalized = [];
    foreach ($this->allowAnonymous as $k => $v) {
        if (
            (is_int($k) && !is_string($v)) ||
            (is_string($k) && !is_int($v))
        ) {
            throw new InvalidArgumentException("Invalid \$allowAnonymous value for key \"{$k}\"");
        }
        if (is_int($k)) {
            $normalized[$v] = self::ALLOW_ANONYMOUS_LIVE;
        } else {
            $normalized[$k] = $v;
        }
    }
    $this->allowAnonymous = $normalized;
} else if (!is_int($this->allowAnonymous)) {
    throw new InvalidConfigException('Invalid $allowAnonymous value');
}

Source: https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L75-L96
So if the value is a boolean then false will be normalized to 0, whereas true will be normalized to 1.
If the value is an array then each key-value pair in the array will be inspected. If the key is an integer then the value is set to 1, for example:
public $allowAnonymous = ['preview'];

equates to
public $allowAnonymous = [0 => 'preview'];

and is interpreted as 
public $allowAnonymous = ['preview' => self::ALLOW_ANONYMOUS_LIVE];

If the key is a not an integer then the key-value pair is left as is.
Here is how $allowAnonymous is enforced:
// Enforce $allowAnonymous
$isLive = Craft::$app->getIsLive();
$test = $isLive ? self::ALLOW_ANONYMOUS_LIVE : self::ALLOW_ANONYMOUS_OFFLINE;

if (is_int($this->allowAnonymous)) {
    $allowAnonymous = $this->allowAnonymous;
} else {
    $allowAnonymous = $this->allowAnonymous[$action->id] ?? self::ALLOW_ANONYMOUS_NEVER;
}

if (!($test & $allowAnonymous)) {
    // Prevent access unless the user is logged in and has the required permissions to view the site
}

Source: https://github.com/craftcms/cms/blob/3.2.2/src/web/Controller.php#L147-L176
The single ampersand & is a bitwise AND operator. It compares each bit in the integers and returns a new integer with a 1 wherever both numbers have a 1, and a 0 anywhere else (similar to how the && operator campares booleans). Here are some examples of how the & bitwise operator works:
( 0 = 0000) & ( 0 = 0000) => ( 0 = 0000) => false
( 0 = 0000) & ( 1 = 0001) => ( 0 = 0000) => false
( 0 = 0000) & ( 2 = 0010) => ( 0 = 0000) => false
( 1 = 0001) & ( 1 = 0001) => ( 1 = 0001) => true
( 1 = 0001) & ( 2 = 0010) => ( 0 = 0000) => false
( 2 = 0010) & ( 2 = 0010) => ( 2 = 0010) => true
( 3 = 0011) & ( 1 = 0001) => ( 1 = 0001) => true
( 3 = 0011) & ( 2 = 0010) => ( 2 = 0010) => true
( 3 = 0011) & ( 3 = 0011) => ( 3 = 0011) => true

By enforcing the condition $test & $allowAnonymous, we can check that $test (whether the site is live or offline) and $allowAnonymous (the permissions granted to the specific controller action) overlap.
More on bitwise operators here.

I'm not sure what the specific issue with your plugin is , but as far as I can tell the only thing that changed in Craft 3.2 was that the ALLOW_ANONYMOUS_OFFLINE constant was added, allowing for (but not requiring) more specific permissions on controller actions.

> **Comments:**
> **username_0**: It appears the issue we had in Sprout Forms was because we were not calling `parent::init();` in our init method. Adding that allows us to remove the `self::ALLOW_ANONYMOUS_LIVE` addition and if it was in place to begin with, no change would have been necessary.  
> **username_0**: Also, thanks for the break down of how the strings get translated. Nice detail.  
> **username_1**: Yeah that must have been it. In Craft and Yii, if you ever override the `init()` method then you should always call the parent method with `parent::init()` :)  

---

