Appearance
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
defaultOAuth2 client is a public client with DPoP, and its redirect URIs are the deployeddefault-website andhttp://localhost:5173. See Log in to your app. - User profile. Each sign-in identity maps to a
Userrecord from theuser-managementmodule, matched by email. The user'spermissionsattribute comes from the roles assigned to that user. - Creating users. The template's
createUserresolver creates theUserrecord 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
developermachine 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.
| Setting | Template default | Set it to |
|---|---|---|
userAuthPolicy.allowedEmailDomains | Not set. An empty list currently allows every domain, but that is changing | Your company's email domains. Never ["*"] for an internal ERP. |
Seeded admin in seed/data/_User.jsonl | A fixed password committed to the repository | Change 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 identities | The admin permission scope only |
defaultPermission on the resolver namespace | _loggedIn | Keep it, and give each resolver that needs more its own permission. |
gqlOperations | "query": tables are read-only over GraphQL and writes go through resolvers | Keep it. |
disableIntrospection | Not set (false) | true in production |
cors | Includes http://localhost:5173 | Remove localhost entries in production. |
| OAuth2 clients for AI agents | Not in the template | Register 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.