# FusionAuth setup

Source: https://docs.settlemint.com/docs/developers/sso-oidc/fusionauth-setup
End-to-end FusionAuth configuration for DALP OIDC sign-in: the full-name claim and id-token roles requirements the standard setup misses, plus every step to wire it in.



This guide configures FusionAuth as a DALP sign-in provider end to end. It covers a local development instance (`http://localhost:9011`) and a production deployment. Substitute your own host, application and credentials.

Each step describes what to set in FusionAuth and links to the relevant FusionAuth documentation. Two DALP-specific requirements the standard OIDC setup misses:

* The OIDC `name` claim comes from the user's full name field, not first and last name.
* Application roles appear only in the access token by default. DALP reads the ID token, so a populate lambda must copy roles into it.

Read the [configuration reference](/docs/developers/sso-oidc/configure-provider) first for what each DALP field means.

## Prerequisites [#prerequisites]

* A running FusionAuth instance with administrator access (the examples use `http://localhost:9011` for local development).
* The DALP Console URL(s) the deployment serves, so you can register the OAuth callback.
* The [FusionAuth documentation](https://fusionauth.io/docs/) open for the exact configuration steps.

<Callout type="warning" title="Keep secrets out of source">
  The OAuth client secret is sensitive. Load it from a secret store or a
  protected environment variable. Never commit a real client secret to
  `config.yml` (see [Deploy OIDC in
  production](/docs/developers/sso-oidc/deploy-production)).
</Callout>

## Steps [#steps]

<Steps>
  <Step>
    ### Create the OIDC application [#create-the-oidc-application]

    Create a FusionAuth [application](https://fusionauth.io/docs/get-started/core-concepts/applications) (or reuse an existing one), enable the Authorization Code grant on its OAuth configuration, and note the client ID and client secret. You will set these in DALP config.
  </Step>

  <Step>
    ### Register the redirect (callback) URL [#register-the-redirect-callback-url]

    Add DALP's callback URL to the application's authorized redirect URLs ([OAuth configuration](https://fusionauth.io/docs/lifecycle/authenticate-users/oauth/endpoints)). The callback path is:

    ```text
    https://<dapp-host>/api/auth/oauth2/callback/<provider-id>
    ```

    `<provider-id>` is the `id` you will set in DALP config (for example `fusionauth`). Add the full URL for every host the Console serves. A host that is not registered fails the sign-in with `invalid_redirect_uri`, and local deployments behind a per-branch host must register each host they answer on.
  </Step>

  <Step>
    ### Confirm the requested scopes [#confirm-the-requested-scopes]

    DALP requests `openid email profile` by default. FusionAuth returns `email` and `name` for these scopes once the user's profile is populated (next steps). No extra scope configuration is required for the default setup.
  </Step>

  <Step>
    ### Create the admin role and assign it [#create-the-admin-role-and-assign-it]

    Create an application [role](https://fusionauth.io/docs/get-started/core-concepts/roles) whose name matches the `adminClaim` you will configure in DALP (this guide uses `dalp-admin`).

    Assign it by giving the user a [registration](https://fusionauth.io/docs/get-started/core-concepts/registrations) for the DALP application with the `dalp-admin` role selected. Only registered users that hold the role carry it in their token.
  </Step>

  <Step>
    ### Set the user's full name (required for the `name` claim) [#set-the-users-full-name-required-for-the-name-claim]

    FusionAuth derives the OIDC `name` claim from the full name field on the account record. A user with only first and last name set, but no full name set, produces a token without a `name` claim. DALP sign-in then fails with `name_is_missing`. Set the full name on the profile and confirm it is populated for every user who will sign in.
  </Step>

  <Step>
    ### Add a lambda to put roles in the ID token [#add-a-lambda-to-put-roles-in-the-id-token]

    By default FusionAuth includes application roles in the access token only. DALP reads the ID token, so the admin role never arrives. The user signs in as a member. Create a [JWT Populate lambda](https://fusionauth.io/docs/extend/code/lambdas/jwt-populate) that copies the registration roles into the token, then assign it to the application's ID token populate slot.

    ```js
    function populate(jwt, user, registration) {
      if (registration && registration.roles) {
        jwt.roles = registration.roles;
      }
    }
    ```

    The lambda writes `roles` as an array, which is exactly the shape DALP's admin-claim resolver looks for (`dalp-admin` inside a `roles` array). Confirm the `populate` signature against your FusionAuth version, because the lambda contract has varied across releases.
  </Step>

  <Step>
    ### Wire the provider into DALP [#wire-the-provider-into-dalp]

    Add the provider to `auth.oidcProviders`, setting `requireIssuerValidation: false` because FusionAuth lacks RFC 9207 support.

    ```yaml
    auth:
      oidcProviders:
        - id: fusionauth
          displayName: FusionAuth
          issuer: http://localhost:9011
          clientId: ${OIDC_PROVIDER_CLIENT_ID:-}
          clientSecret: ${OIDC_PROVIDER_CLIENT_SECRET:-}
          adminClaim: dalp-admin
          requireIssuerValidation: false
    ```

    For production, inject `clientId` and `clientSecret` from the environment or a secret store rather than committing them, and use an `https://` issuer. See [Deploy OIDC in production](/docs/developers/sso-oidc/deploy-production).
  </Step>

  <Step>
    ### Restart and verify [#restart-and-verify]

    DALP reads provider configuration at boot, so restart the stack after changing config. Then open the Console sign-in page. Only the Sign in with FusionAuth button should appear, because local login is now disabled. Complete the sign-in: a user holding `dalp-admin` lands as a platform admin, and everyone else as a regular member. If the round-trip or role is wrong, see [Troubleshooting](/docs/developers/sso-oidc/troubleshooting).
  </Step>
</Steps>

## What success looks like [#what-success-looks-like]

* The Console sign-in page shows only the FusionAuth button.
* Clicking it redirects to FusionAuth, and after login the browser returns to the Console with a session.
* A user holding `dalp-admin` resolves to `role: admin`; others resolve to `role: member`.

If any step fails, the [Troubleshooting](/docs/developers/sso-oidc/troubleshooting) page maps each error to its cause, and the fix to apply.

## Enable OIDC wallet verification (optional) [#enable-oidc-wallet-verification-optional]

OIDC wallet verification (`OIDC_MFA`) is independent of sign-in. Enable it when you want signing operations authorized through a FusionAuth TOTP factor. These steps add to the sign-in setup above; they do not replace it. A deployment can enable OIDC wallet verification without OIDC sign-in.

<Steps>
  <Step>
    ### Add a server API key [#add-a-server-api-key]

    During verification the platform calls FusionAuth server-to-server: it reads the user (`/api/user`) and runs the two-factor flow (`/api/two-factor/start`, then `/api/two-factor/login`). Create an [API key](https://fusionauth.io/docs/apis/api-keys) and set `OIDC_PROVIDER_MFA_API_KEY` to its value.

    A super-user key (no endpoint restrictions) is the simplest choice. If you restrict the key to specific endpoints, note that `/api/two-factor/login` is a public authentication endpoint that does not appear in the API-key endpoint list, so a key limited to only the OIDC MFA endpoints rejects the login call. Keep the key in a secret store; never commit it.
  </Step>

  <Step>
    ### Enable the authenticator factor on the tenant [#enable-the-authenticator-factor-on-the-tenant]

    OIDC wallet verification uses a time-based one-time password (TOTP) authenticator. Enable **Authenticator** as a multi-factor method on the FusionAuth [tenant](https://fusionauth.io/docs/lifecycle/authenticate-users/multi-factor-authentication). Without it no user can enroll a factor, and every verification attempt returns `USER_MISSING_2FA`.
  </Step>

  <Step>
    ### Enroll each user's authenticator [#enroll-each-users-authenticator]

    Each user who authorizes signing must hold an enrolled authenticator factor. Enroll it from the user's profile or through your own enrollment flow. The platform looks the user up by the email on their session, so that email must match a FusionAuth user that holds an `authenticator` factor.
  </Step>

  <Step>
    ### Add the verification fields to DALP config [#add-the-verification-fields-to-dalp-config]

    Add `apiKey` and `applicationId` to the provider entry. `applicationId` is the FusionAuth application id (the same value as `clientId`).

    ```yaml
    auth:
      oidcProviders:
        - id: fusionauth
          displayName: FusionAuth
          issuer: http://localhost:9011
          clientId: ${OIDC_PROVIDER_CLIENT_ID:-}
          clientSecret: ${OIDC_PROVIDER_CLIENT_SECRET:-}
          adminClaim: dalp-admin
          requireIssuerValidation: false
          apiKey: ${OIDC_PROVIDER_MFA_API_KEY:-}
          applicationId: ${OIDC_PROVIDER_MFA_APPLICATION_ID:-}
    ```

    For a verification-only provider with no OIDC sign-in, set `issuer`, `apiKey`, and `applicationId`, and leave `clientId` and `clientSecret` empty.
  </Step>

  <Step>
    ### Restart and verify [#restart-and-verify-1]

    Restart the stack so the platform re-reads the provider configuration. A signing request that declares `OIDC_MFA` with a current authenticator code now authorizes through FusionAuth. If it fails, the [Troubleshooting](/docs/developers/sso-oidc/troubleshooting) page maps each OIDC MFA error to its cause and fix.
  </Step>
</Steps>
