---
myst:
  html_meta:
    "description": "Install the pas.plugins.identity backend in a Plone site and verify the result."
    "property=og:description": "Install the pas.plugins.identity backend in a Plone site and verify the result."
    "property=og:title": "How to install the backend"
---

(how-to-install)=

# How to install the backend

Install `pas.plugins.identity` in a Plone site and confirm it works.

This guide covers the backend only.
The frontend is a separate package and a separate guide: {doc}`install-the-frontend`.

```{note}
There are no GenericSetup upgrade steps in this release.
See {doc}`upgrade` before taking a new alpha, and {doc}`/reference/stability` for what that implies.
```

## Requirements

| | |
|---|---|
| Plone | 6.2 |
| Python | 3.12, 3.13, or 3.14 |
| Frontend | Volto, for sign-in. Classic UI is not supported yet—see {doc}`/reference/stability` |

## Install the backend

These steps are for a project generated by
[cookieplone](https://github.com/plone/cookieplone), which is the layout a Plone
6 project has. Paths are relative to `backend/`, and `<yourpackage>` is the
package under `src/`.

1. Declare the dependency in `pyproject.toml`:

   ```toml
   dependencies = [
       "Products.CMFPlone",
       "plone.api",
       "plone.restapi",
       "plone.volto",
       "pas.plugins.identity",
   ]
   ```

   Two extras exist, and neither is needed for ordinary sign-in:

   | Extra | Adds | Also needs |
   |---|---|---|
   | `server` | The authorization server layer, with a GenericSetup profile of its own. | its profile, in step 3 |
   | `sql` | An audit sink writing a row per event to a relational database. | `IDENTITY_AUDIT_DSN`, and `sql` named in `audit_sinks` |

   Ask for one by naming it in the requirement, `"pas.plugins.identity[server]"`.
   See {doc}`/reference/audit-log` for the `sql` sink.

2. Load its ZCML, in `src/<yourpackage>/dependencies.zcml`:

   ```xml
   <configure xmlns="http://namespaces.zope.org/zope">

     <include package="pas.plugins.identity" />

   </configure>
   ```

   Your package's `configure.zcml` already pulls that file in with
   `<include file="dependencies.zcml" />`. Installing the distribution is not
   enough on its own: without the `include`, nothing registers and the add-on
   does not appear in the control panel.

3. Install it with your own package, in
   `src/<yourpackage>/profiles/default/metadata.xml`:

   ```xml
   <?xml version="1.0" encoding="utf-8"?>
   <metadata>
     <version>1000</version>
     <dependencies>
       <dependency>profile-pas.plugins.identity:default</dependency>
     </dependencies>
   </metadata>
   ```

   Naming it here is what makes a fresh site arrive configured, rather than
   waiting for somebody to remember the add-ons control panel.

   For the authorization server, name **both** profiles, in this order:

   ```xml
   <dependencies>
     <dependency>profile-pas.plugins.identity:default</dependency>
     <dependency>profile-pas.plugins.identity.server:default</dependency>
   </dependencies>
   ```

   `pas.plugins.identity:default` installs everything the core layer needs: the
   control panel, both PAS plugins, the `UserProfile` and `UserGroup` content
   types with their workflows, and the catalog they are filed in. It also sets
   the registry records described in {doc}`/reference/user-content` and points
   them at this package's own types.

4. Ship your settings as configuration, in
   `src/<yourpackage>/profiles/default/registry/pas.plugins.identity.xml`:

   ```xml
   <?xml version="1.0" encoding="utf-8"?>
   <registry>
     <records interface="pas.plugins.identity.core.controlpanel.interfaces.IIdentitySettings"
              prefix="pas.plugins.identity"
     >
       <value key="callback_url">/login-identity</value>
       <value key="audit_record_pii">False</value>
     </records>
   </registry>
   ```

   Every record in {doc}`/reference/settings` can be set this way, so a
   deployment's configuration lives in the repository and arrives with the
   profile instead of being typed into a control panel on each environment.

   Provider **secrets** are the exception. They are write-only and a
   GenericSetup export omits them, so keep them out of these files and set them
   per environment. See {doc}`/concepts/secrets`.

5. Restart the Plone instance, then apply your own package's profile.

   This is a ZCML change, so the site does not see the add-on until it restarts.

```{note}
To install into a site that already exists, without touching your package, use
the add-ons control panel or apply `pas.plugins.identity:default` from
`portal_setup`. The server layer is its own entry there, with its own install
and uninstall button; the panel shows no version beside it, because the entry
is named after a package rather than a distribution.
```

## Set the login callback URL

Nothing signs in until this matches what your providers have registered.

1. Open the **Identity providers** control panel.
2. Set **Callback URL** to the frontend route that providers redirect back to.

   The default is `/login-identity`, which is the route the Volto add-on registers.
   Most sites never change it.

The value is a path, and the full redirect URI you give a provider is your frontend's base URL plus that path:

```text
https://www.example.com/login-identity
```

It is a route in the Volto frontend rather than a backend view, so the package cannot derive it from the portal URL.
That is why it is a setting.

## Verify

A working install has all four of these:

- the `identity` plugin in `acl_users`, active for extraction, authentication, and credentials reset
- the `identity_profile` plugin beside it, at the top of `IPropertiesPlugin`
- at least one provider in the control panel, with a title and a driver
- a callback URL that matches what the provider has registered

## Uninstalling

Every profile has a matching uninstall profile, and uninstalling is tested: the test installs, uninstalls, and asserts that the site still works with no plugin, registry key, or tool left behind.

```{note}
Uninstalling removes the catalog, the content types, and the workflows.
It leaves every `UserProfile` object and its data exactly where it is.
Uninstalling an add-on is a configuration change, not an instruction to delete everyone's account data.
```

## Next steps

1. {doc}`install-the-frontend`—the Volto add-on, without which nobody can sign in.
2. {doc}`providers/index`—pick the provider you are adding and follow its recipe.
3. {doc}`troubleshoot`—if sign-in fails, start here rather than in the source.
