> For the complete documentation index, see [llms.txt](https://docs.appfarm.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.appfarm.io/how-to/authentication-and-access-control/unauthenticated-access.md).

# Configure unauthenticated access

When you create a new app in Appfarm Create, it is configured by default to require authentication. If a user loads the app and they are not logged in, they will be presented with the login screen. To allow users to access your app without logging in, you need to configure unauthenticated access. The built-in [app variable](/reference/apps/data/app-variables.md#built-in-app-variables) **Is Unauthenticated** will be true if a user is using unauthenticated access.

{% hint style="success" %}
**Best practice**

Separate “authenticated” and “unauthenticated” functionality into different apps.

If you have some functionality which should be open to the public and other functionality (e.g. an admin dashboard) that is restricted to authenticated users, we recommend building these as distinct apps. This way it is easier to maintain data security and you avoid having to write extra logic to handle the authentication status of a given user.
{% endhint %}

{% hint style="warning" %}
**Important**

In the video below, a deprecated option is shown. Previously you were required to select the "Public Access" checkbox in App settings. This option has since been removed and is no longer required.
{% endhint %}

{% embed url="<https://www.loom.com/share/90c2978a907d4b88a3bfb1d04aabc40e>" %}

Follow the checklist below to configure unauthenticated access.

## Checklist

* Under **Roles**, create a new [Role](/reference/security/roles.md) for unauthenticated users. Check the environment(s) for which you want to grant access.
* Under **Permissions**, [grant](/reference/security/permissions.md) the newly created Role:
  * Access to your public app within **Apps**
  * Access (likely read-only) to the necessary **Object Classes**
* Under **Service Accounts** create a new [Account](/reference/security/service-accounts.md) and assign it the new Role. This will be used as the underlying account for all unauthenticated users.
* Under **Environments Config**, within each [Environment](/getting-started/key-concepts.md#environments) that you want to open to the public, check “Unauthenticated Access” under Application Security and then select the Service Account you just created.

Since the changes involve updated permissions you will need to [deploy](/reference/operations/deploy.md) for these changes to take effect.

{% hint style="info" %}
**Example**\
\
An example of an app with unauthenticated access is available in our [Showroom](https://showroom.appfarm.app/ui-components/radio). Check out the setup of the *Sign Up* app in Appfarm Create. Don't have access? [Register](https://showroom.appfarm.app/sign-up).
{% endhint %}

## Best Practices

**Prerequisite:** Make sure you understand how [Object Class Permissions](/reference/security/permissions.md#object-classes) work before continuing, as well as how to [design secure permissions](/reference/security/permissions/designing-secure-permissions.md) in general.

{% hint style="info" %}
This section is written for Services. The same principles apply to Flows.
{% endhint %}

When a solution contains both an unauthenticated app and sensitive data, permission setup and environment configuration are critical. Anyone can obtain the session of your unauthenticated service account, so treat its role as public. Whatever that role can read, the public can read.

### The core principle

Never grant **Read** access to sensitive object classes on an unauthenticated role. Instead, grant read access to a separate internal role, expose the data through a service, and let the unauthenticated app run that [service **as a service account**](/library/action-nodes/run-service.md) with elevated permissions.

### Walkthrough: an application portal

Anyone can submit an application without logging in, and return later via a link containing a secret (the object's random identifier) to continue where they left off. Their own application is not sensitive to them, but everyone else's is. Conditional permissions can't help here, since they require a logged-in user. In the below example, we assume an **Application** object class, and an app **My Application** with an **Application (temp)** data source (cardinality one, runtime-only).

**1. Set up the unauthenticated role**

Create a role `Unauthenticated` and a service account `Unauthenticated User Account` as a member of it. Grant the role access to the My Application app and to the environment(s) it should run in.

**2. Grant only Create and Update on Application**

On the `Application` object class, give `Unauthenticated` **Create** and **Update**, but no Read. Create lets a new application be submitted; Update lets an existing one be saved again.

**3. Build a service that reads the application**

Create a service with an endpoint that takes the application secret as input, reads the `Application` with a matching random identifier, and returns it.

**4. Create an internal role for reading**

Create a role `Application access` with **Read** on `Application`, [access to the service,](/reference/security/permissions.md#services) and [login access](/reference/security/permissions.md#login-access) to the relevant environment(s). Create a service account `Application service account` for it.

**5. Allow the unauthenticated role to elevate**

Under **Permissions -> Accounts and roles**, grant the role `Unauthenticated` the **Act as service account** permission for `Application service account`.

**6. Configure the environments**

Under **Configuration -> Environments**, for each relevant environment, enable **Unauthenticated application access** and **Unauthenticated service access**, both using `Unauthenticated User Account`.

**7. Wire it up in the app**

On app load: if the URL parameter holding the application secret has a value, run the service with **Run as service account** set to `Application service account`, and map the response to `Application (temp)`. If nothing is returned, create a new object in it instead.

**Why this is safe:** the unauthenticated user can open the app and can call services, but has no read access to any data and no access to any service on its own. It can only run this one service, under a specific elevated identity, and that service only ever returns the single application matching the supplied secret. Writing the result into a runtime data source requires no permissions at all.

### Do's and don'ts

**Do**

* Assume the unauthenticated service account's session is public. Design permissions accordingly.
* Keep the unauthenticated role's object class permissions to the absolute minimum, usually Create and Update only.
* Put every read of sensitive data behind a service, and scope the service so it can only return the specific record the caller has proven access to.
* Use a random identifier as the secret, never a sequential one or the raw object ID.
* Separate unauthenticated and authenticated functionality into different apps.
* Verify the setup by inspecting what the unauthenticated session can actually reach, not only by testing the intended flow.

**Don't**

* Don't grant Read on any object class holding data belonging to other users.
* Don't rely on filters in data sources or on UI visibility conditions as a security boundary. Both run client-side and can be bypassed.
* Don't rely on conditional permissions here; they evaluate against a logged-in user and don't apply to unauthenticated access.
* Don't give the unauthenticated role broad **Act as service account** rights. Grant it only for the specific service account it needs.
* Don't reuse the elevated service account's role for anything the unauthenticated app touches directly.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.appfarm.io/how-to/authentication-and-access-control/unauthenticated-access.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
