Skip to content
View as Markdown

Security and Sign-in ​

This page covers how people sign in to the app you build with ERP Kit, and the settings to tighten before go-live. For access to the ERP Kit packages themselves, see Registry access.

How sign-in works ​

The app templates use the platform's built-in IdP, configured with defineIdp in backend/tailor.config.ts:

  • Sign-in page. Users sign in on a page hosted by Tailor Platform, not by your app. The frontend's default OAuth2 client is a public client with DPoP, and its redirect URIs are the deployed default-web site and http://localhost:5173. See Log in to your app.
  • User profile. Each sign-in identity maps to a User record from the user-management module, matched by email. The user's permissions attribute comes from the roles assigned to that user.
  • Creating users. The template's createUser resolver creates the User record through the module command and the sign-in identity in the IdP in one step. Create users through it, not directly in the IdP, so the two stay in sync.
  • Machine users. The developer machine user is for the CLI and scripts. It carries the module permissions directly and has no sign-in identity.

Restrict sign-in to your domains ​

Set userAuthPolicy.allowedEmailDomains to the email domains your users have:

typescript
const idp = defineIdp("default", {
  // ...
  userAuthPolicy: {
    allowSelfPasswordReset: true,
    allowedEmailDomains: ["example.com"],
  },
});

To add a "Sign in with Google" or "Sign in with Microsoft" button, see Google OAuth and Microsoft OAuth. For single sign-on with your own identity provider and user provisioning, see Authentication and SCIM.

Security defaults ​

The templates are set up for a first deploy by one developer. Change these before anyone else signs in, and before you deploy to staging or production. Each is a small change in tailor.config.ts or a seed file.

SettingTemplate defaultSet it to
userAuthPolicy.allowedEmailDomainsNot set. An empty list currently allows every domain, but that is changingYour company's email domains. Never ["*"] for an internal ERP.
Seeded admin in seed/data/_User.jsonlA fixed password committed to the repositoryChange the password after the first sign-in, and delete the seeded user once a real admin exists. Do not seed it into staging or production.
IdP permissions_loggedIn for create, read, update, delete, and password reset, so any signed-in user can create sign-in identitiesThe admin permission scope only
defaultPermission on the resolver namespace_loggedInKeep it, and give each resolver that needs more its own permission.
gqlOperations"query": tables are read-only over GraphQL and writes go through resolversKeep it.
disableIntrospectionNot set (false)true in production
corsIncludes http://localhost:5173Remove localhost entries in production.
OAuth2 clients for AI agentsNot in the templateRegister agent clients such as a Claude connector in development and staging only, unless you have reviewed them for production.

For network-level restrictions, see IP restriction.