# Coming from SSOfy

> What changed from SSOfy and how to move an existing integration to 9in.

Source: https://9in.io/docs/coming-from-ssofy/

9in is SSOfy, rebuilt and relaunched on Cloudflare with standard OpenID Connect at its core. SSOfy's v1 endpoints and its signed API are not part of 9in, so an integration moves over rather than running unchanged. Most moves are small.

## What maps to what

| SSOfy | 9in |
|---|---|
| `https://<name>.ssofy.com` | `https://<name>.9in.io` (or your custom domain) |
| SSOfy SDKs (`ssofy/*`, `@ssofy/*`) | 9in SDKs: `@9in-io/sdk`, `@9in-io/node`, `@9in-io/express-server`, `9in/php-sdk`, `9in/laravel`. They read the old `SSOFY_*` environment variables when `NINE_*` ones are missing. Any OpenID Connect library works too. |
| API key + request signatures | The [Management API](https://9in.io/docs/reference/management-api/) with a client-credentials token |
| `auth/token` (signing a user in from your app) | [Login links](https://9in.io/docs/login-links/) |
| reCAPTCHA / hCaptcha / image captcha | Cloudflare Turnstile ([bot protection](https://9in.io/docs/security/#bot-protection)) |
| `custom_1` … `custom_9` | [Custom profile fields](https://9in.io/docs/users/#custom-profile-fields) with your own keys |
| Hybrid token validation | `createTokenVerifier` in hybrid mode ([Protecting your API](https://9in.io/docs/protecting-apis/)) |

## Your user database

Keep it. The adapter now has **three** endpoints instead of eight: `/authenticate`, `/user` and `/event` ([Your own user database](https://9in.io/docs/own-database/)). Applications, scopes, social login and one-time-code options are configured in 9in instead of being served from your server. Requests and responses are signed with `9in-signature` (HMAC-SHA256), and the SDK handlers do it for you.

## Themes

SSOfy Handlebars themes import as they are: layout, page partials, `manifest.json` and translations (**Themes → Import theme**). 9in renders them with the same component and partial names; pages a theme doesn't include (such as the newer two-factor pages) come from the default theme. Inline scripts need `nonce="{{ csp_nonce }}"`, or `allowInlineScripts` in the manifest's `security` section for themes ported as they are. See the [theme reference](https://9in.io/docs/reference/themes/).

## Users

Import them with their password hashes and their ids, so `sub` doesn't change ([Importing users](https://9in.io/docs/importing-users/)), or let them move over as they sign in, through the adapter with **Import users on first login**.

## Step by step

1. Create a tenant and recreate your applications (callback and logout URLs) and APIs.
2. Configure sign-in methods, social providers, branding and your theme.
3. Move users: import them, or connect your database.
4. Switch your apps to the 9in SDK for your stack (or an OIDC library) and the new issuer.
5. Replace SSOfy API calls with the Management API, and `auth/token` with login links.
6. Test everything in the sandbox, then go live.
