# Connect a SAML application

Set up single sign-on to a SAML 2.0 application, with your AuthFI project as the identity provider.

Your project is a SAML 2.0 identity provider. Connect an application to it, and people sign in to that application with their AuthFI account instead of a separate password. This is single sign-on (SSO).

Use this guide for any application that supports SAML 2.0. For an application that supports OpenID Connect, see [Add sign-in to an app](/quickstart/sign-in).

## Before you begin

You need:

- A plan that includes SAML single sign-on. Without it, the endpoints on this page return `403`.
- Permission to add applications in the AuthFI console.
- Administrator access to the application's SAML or SSO settings.

In SAML terms, your project is the _identity provider_ (IdP) and the application is the _service provider_ (SP).

<Steps>

### Collect the application's SAML details

In the application's SSO settings, find these values. Applications name them differently, so common alternatives are listed.

| You need            | Also called                                 | Required |
| ------------------- | ------------------------------------------- | -------- |
| Entity ID           | SP entity ID, audience URI, identifier      | Yes      |
| ACS URL             | Assertion consumer service URL, reply URL   | Yes      |
| Signing certificate | SP certificate, request signing certificate | No       |

You need the signing certificate only if the application signs its sign-in requests. You add it [after registering](#require-signed-sign-in-requests).

### Register the application in AuthFI

1. In the console, open **Integrations > Applications** and select **Register**.
2. Under **What are you connecting?**, choose **SAML**.
3. Under **Which direction does trust flow?**, choose **We sign them in**. AuthFI is the identity provider, and your people sign in to the application. This choice cannot be changed later.
4. Enter the values you collected.

| Field              | Enter                                                                                                                       |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------- |
| Handle             | A short name in lower-case letters, digits and hyphens, for example `salesforce`. It is used in URLs and cannot be changed. |
| Their entity ID    | The application's entity ID                                                                                                 |
| Their ACS URL      | The application's ACS URL. It must be `https`.                                                                              |
| Their metadata URL | Optional. Lets AuthFI read the application's certificate and endpoints.                                                     |

5. Review the summary and select **Register**.

The last step shows the **Metadata**, **SSO** and **IdP-initiated** URLs for this application.

### Configure the application

Open the application's page in the console and go to the **Connect** section. It shows everything the application needs from your project. These values are the same for every SAML application in the project.

If the application accepts a metadata URL, select **Copy** beside the metadata URL and paste it into the application. The application then reads the other values from the metadata, and picks up a new certificate when your signing key rotates. The metadata lists the current certificate and, during a rotation, the previous one. To upload a file instead, select **Download .xml**.

If the application needs each value separately, the same section lists them:

| In the console      | Applications also call it | Value                                  |
| ------------------- | ------------------------- | -------------------------------------- |
| Sign-in URL         | SSO URL, sign-in page URL | `https://acme.authfi.io/saml/sso`      |
| Entity ID           | Issuer, IdP entity ID     | `https://acme.authfi.io/saml/metadata` |
| Signing certificate | Verification certificate  | **Download .pem** or **.cer**          |

The sign-on endpoint accepts the HTTP-Redirect and HTTP-POST bindings.

In the application, require a signed **assertion**. AuthFI signs the assertion with RSA-SHA256.

### Assign the application

An application that no group is assigned to is open to everyone in the project. To restrict it, select **Assign a group** on the application's page and choose a group. The first assignment closes the application to everyone else, and the console warns you before it does.

</Steps>

## Check that it works

Start a sign-in from AuthFI. Open the **IdP-initiated** URL the console showed you. It has this form, with your handle in place of `salesforce`:

```text
https://acme.authfi.io/saml/idp-initiated/salesforce
```

Sign in if you are asked to. You arrive in the application, signed in as yourself.

Then test the other direction. Open the application's own sign-in page and choose SSO. The application sends you to AuthFI and back.

## How a sign-in starts

A SAML sign-in can start from either side.

| Started by      | What happens                                                                                                     |
| --------------- | ---------------------------------------------------------------------------------------------------------------- |
| The application | It sends the browser to `/saml/sso` with a SAML request. A person with no session signs in, then continues.      |
| AuthFI          | The browser opens `/saml/idp-initiated/{name}`. An optional `RelayState` parameter is passed to the application. |

## What the application receives

AuthFI posts a SAML response to the ACS URL through the person's browser. The response contains one signed assertion.

| Part                 | Value                                                                 |
| -------------------- | --------------------------------------------------------------------- |
| Signature            | On the assertion, RSA-SHA256                                          |
| Audience             | The application's entity ID                                           |
| Valid for            | 5 minutes                                                             |
| NameID               | The person's email, in `emailAddress` format                          |
| Attributes           | `roles` and `groups`                                                  |
| Authentication class | How the person signed in: password, MFA, or another identity provider |

The `groups` attribute lists only the groups shared with this application, not every group the person belongs to.

## Change the NameID and attributes

Each application can have its own NameID and attributes. On the application's page, open the **What it receives** section.

1. To start from what a common application expects, choose a template under **Start from what the app documents**: **AuthFI default**, **Google Workspace**, **Salesforce**, **AWS IAM Identity Center**, **Microsoft claim names** or **Empty**.
2. Under **Who they are (NameID)**, choose **Their email address** or **Their user ID, which never changes**. The console shows the format that will be sent: `emailAddress` or `persistent`.
3. Under **Attributes**, select **+ Add an attribute**. Enter the name the application expects and choose its value.
4. Select **Save**.

| Attribute value in the console | Sends        |
| ------------------------------ | ------------ |
| Email address                  | `email`      |
| First name                     | `first_name` |
| Last name                      | `last_name`  |
| Full name                      | `full_name`  |
| User ID, which never changes   | `user_id`    |
| Every role they hold           | `roles`      |
| Groups shared with this app    | `groups`     |

You can define up to 50 attributes. An attribute with no value for a person is left out of that person's assertion.

## Require signed sign-in requests

If the application signs its requests, give AuthFI its certificate so the signature can be verified.

1. On the application's page, open the **Requests it sends** section.
2. Select **Add the application's certificate**, paste the certificate or select **Upload a file**, and select **Register it**.
3. To reject any request that is not signed, turn on **Refuse unsigned requests**.

## How sign-in requests are validated

When the application starts the sign-in, AuthFI validates its request before it shows the sign-in page. A request that fails a check gets a `403`.

- The request names an application registered in the project.
- `Destination`, when present, is your project's sign-on URL.
- The request is no more than 5 minutes old.
- An ACS URL in the request equals the registered ACS URL.
- The signature verifies, when the application has a signing certificate or signed requests are required.

AuthFI honours two options in a request:

- **`ForceAuthn`**. The person signs in again, even with a session.
- **A requested authentication class**. If it cannot be met, the application receives a signed response with the status `NoAuthnContext`.

## Troubleshooting

| What you see                                | Cause                                                               | Fix                                                                           |
| ------------------------------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `403` on every SAML URL                     | The plan does not include SAML single sign-on                       | Change the plan                                                               |
| `403` when the application starts a sign-in | The entity ID or ACS URL in the request is not the one registered   | Compare both values, character for character, with the application's settings |
| `403` only when requests are signed         | The certificate in AuthFI is not the one the application signs with | Add the application's current certificate under **Requests it sends**         |
| `403` on a request that used to work        | The request is more than 5 minutes old                              | Check the clock on the application's server                                   |
| A page saying the person is not assigned    | The application is assigned to groups, and the person is in none    | Select **Assign a group** and choose one of the person's groups               |
| The application reports `NoAuthnContext`    | It asked for a way of signing in that the person could not use      | Enrol the person in MFA, or relax the application's requirement               |

## Next steps

<Cards>
  <Card href="/concepts/access" title="Roles, groups and grants">
    How assigning an application to a group decides who can sign in.
  </Card>
  <Card href="/connections/scim" title="Provision people with SCIM">
    Create and suspend accounts from your directory.
  </Card>
  <Card href="/security/keys" title="Keys and secrets">
    What happens to the signing certificate when a key rotates.
  </Card>
</Cards>
