Tenant Admin Guide¶
Managing your organization's AuthVital tenant.
Overview¶
Tenant Admins (with admin role) can:
- Invite and manage members
- Configure tenant SSO settings
- Manage MFA policies
- View tenant subscription and licenses
- Configure tenant branding
Accessing Tenant Settings¶
Via Application¶
Your application may provide a tenant settings page. Look for: - "Organization Settings" - "Team Settings" - "Admin Panel"
Via SDK¶
// Check if user is tenant admin
const { user, memberships } = await authvital.getCurrentUser(req);
const membership = memberships.find(m => m.tenantId === currentTenantId);
const isAdmin = ['owner', 'admin'].includes(membership?.role);
Member Management¶
Viewing Members¶
// List all tenant members
// tenantId is automatically extracted from the JWT
const { memberships } = await authvital.memberships.listForTenant(req, {
status: 'ACTIVE',
includeRoles: true,
});
// memberships: [{ id, userId, status, user: { email, name, ... }, roles }]
Inviting Members¶
// Send invitation
// tenantId is automatically extracted from the JWT
const { roles } = await authvital.memberships.getTenantRoles();
const memberRole = roles.find(r => r.slug === 'member');
await authvital.invitations.send(req, {
email: 'newuser@example.com',
roleId: memberRole?.id, // Use role ID, not slug
});
Invitee receives email with link to accept.
Invitation States¶
| Status | Description |
|---|---|
PENDING | Waiting for user to accept |
ACCEPTED | User joined the tenant |
EXPIRED | Past expiration date |
REVOKED | Manually cancelled |
Managing Invitations¶
// List pending invitations
// tenantId is automatically extracted from the JWT
const { invitations } = await authvital.invitations.listPending(req);
// Resend invitation
await authvital.invitations.resend(req, {
invitationId: 'invitation-id',
expiresInDays: 7, // Optional: extend expiry
});
// Revoke invitation
await authvital.invitations.revoke(req, 'invitation-id');
Changing Member Roles¶
// Change to admin
// Signature: setMemberRole(request, membershipId, roleSlug)
await authvital.memberships.setMemberRole(req, 'membership-id', 'admin');
// Demote to member
await authvital.memberships.setMemberRole(req, 'membership-id', 'member');
Role Hierarchy: - Owner: Full access, can delete tenant, transfer ownership - Admin: Manage members, settings, but can't delete tenant - Member: Basic access, no admin functions
Suspending & Removing Members¶
Admin Dashboard Only
Member suspension and removal are currently performed through the AuthVital Admin Dashboard.
The SDK does not include suspend(), reactivate(), or remove() methods for memberships.
To suspend or remove a member:
- Go to AuthVital Admin Panel → Tenants → Select tenant
- Navigate to Members tab
- Click on the member → Use Suspend or Remove buttons
SSO Configuration¶
Tenant-Level SSO¶
Configure your organization's own SSO:
// Configure Microsoft SSO for your Azure AD
await authvital.tenants.configureSso('tenant-id', {
provider: 'MICROSOFT',
enabled: true,
clientId: 'your-azure-app-id',
clientSecret: 'your-azure-secret',
allowedDomains: ['yourcompany.com'],
});
Enforcing SSO¶
Disable password login, require SSO:
await authvital.tenants.configureSso('tenant-id', {
provider: 'MICROSOFT',
enabled: true,
enforced: true, // Password login disabled
// ...
});
When enforced: - Users must use SSO to log in - Password reset is disabled - Only SSO-linked users can access
Viewing SSO Configuration¶
// Get SSO config for a specific provider
const microsoftSso = await authvital.tenants.getSsoConfig('tenant-id', 'MICROSOFT');
const googleSso = await authvital.tenants.getSsoConfig('tenant-id', 'GOOGLE');
// Returns null if not configured, or:
// {
// provider: 'MICROSOFT',
// enabled: true,
// enforced: true,
// allowedDomains: ['yourcompany.com'],
// autoCreateUser: true,
// autoLinkExisting: true,
// }
MFA Policy¶
Setting MFA Requirements¶
// Require MFA for all members
await authvital.tenants.update('tenant-id', {
mfaPolicy: 'REQUIRED',
});
// Require after grace period
await authvital.tenants.update('tenant-id', {
mfaPolicy: 'ENFORCED_AFTER_GRACE',
mfaGracePeriodDays: 14, // 2 weeks to enable MFA
});
// Optional (default)
await authvital.tenants.update('tenant-id', {
mfaPolicy: 'OPTIONAL',
});
Viewing MFA Status¶
// Get MFA status for all members
const members = await authvital.memberships.listForTenant(req, {
tenantId: 'tenant-id',
includeUser: true,
});
const mfaStats = {
total: members.length,
enabled: members.filter(m => m.user.mfaEnabled).length,
pending: members.filter(m => !m.user.mfaEnabled && policy === 'REQUIRED').length,
};
Domain Verification¶
Verify your company's domain to: - Auto-add users with matching email - Restrict SSO to your domain - Enable domain-based features
Admin Dashboard Only
Domain management is currently performed through the AuthVital Admin Dashboard.
The SDK does not include a domains namespace.
To manage domains:
- Go to AuthVital Admin Panel → Tenants → Select tenant
- Navigate to Domains tab
- Add, verify, or configure domains from the UI
Adding a Domain (Admin Dashboard)¶
- Click Add Domain
- Enter your domain (e.g.,
yourcompany.com) - Copy the verification DNS record
Verifying Domain¶
Add the TXT record to your DNS:
Then click Verify in the Admin Dashboard.
Auto-Join Domain¶
Enable automatic tenant membership for verified domains via the Admin Dashboard settings.
License Management¶
Viewing Tenant License Overview (M2M)¶
// Uses M2M client credentials - no request needed
const overview = await authvital.licenses.getTenantOverview('tenant-id');
// {
// tenantId: 'tenant-123',
// tenantName: 'Acme Corporation',
// totalSeatsOwned: 50,
// totalSeatsAssigned: 35,
// totalSeatsAvailable: 15,
// subscriptions: [...]
// }
Viewing License Assignments¶
// Get all license holders for an application (uses JWT)
const holders = await authvital.licenses.getHolders(req, 'app-id');
// [{ userId, email, licenseType, assignedAt, ... }]
// Or get all licenses for a specific user
const userLicenses = await authvital.licenses.listForUser(req, 'user-id');
Granting Licenses¶
// Grant a license to a user (uses JWT, tenantId from token)
await authvital.licenses.grant(req, {
userId: 'user-id',
applicationId: 'app-id',
licenseTypeId: 'license-type-id',
});
Revoking Licenses¶
// Revoke a license from a user
await authvital.licenses.revoke(req, {
userId: 'user-id',
applicationId: 'app-id',
});
License Usage Statistics¶
// Get usage overview for tenant (uses JWT)
const usage = await authvital.licenses.getUsageOverview(req);
// {
// totalSeats: 10,
// seatsAssigned: 7,
// utilization: 70,
// ...
// }
// Get usage trends over time
const trends = await authvital.licenses.getUsageTrends(req, 30); // Last 30 days
Tenant Settings¶
Updating Tenant Info¶
await authvital.tenants.update('tenant-id', {
name: 'New Company Name',
settings: {
timezone: 'America/New_York',
language: 'en',
},
});
Custom Login URL¶
Configure where users are sent to log in:
await authvital.tenants.update('tenant-id', {
initiateLoginUri: 'https://acme.yourapp.com/login',
});
Ownership Transfer¶
Only the current Owner can:
API Endpoint - No SDK Method
Tenant ownership transfer is available via the REST API but not yet in the SDK.
// Direct API call (until SDK method is added)
const response = await fetch(`${authVitalHost}/api/tenants/${tenantId}/transfer-ownership`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
newOwnerId: 'usr_newowner123',
}),
});
Required permission: tenant:admin or current owner
After transfer: - New owner becomes Owner role - Previous owner becomes Admin role
Audit Trail¶
View recent activity in your tenant:
Audit Logs
License audit logs are available via the SDK:
// License-specific audit log
const auditLog = await authvital.licenses.getAuditLog(req, {
limit: 50,
offset: 0,
});
General audit logs are available via the REST API:
Building an Admin UI¶
React Admin Panel Example¶
function TenantAdminPanel() {
const { tenantId } = useCurrentTenant();
const { user } = useAuth();
// Check admin access
const membership = user.memberships.find(m => m.tenantId === tenantId);
const isAdmin = ['owner', 'admin'].includes(membership?.role);
if (!isAdmin) {
return <AccessDenied message="Admin access required" />;
}
return (
<Tabs>
<Tab label="Members">
<MemberList tenantId={tenantId} />
<InviteMemberForm tenantId={tenantId} />
</Tab>
<Tab label="Security">
<SsoConfiguration tenantId={tenantId} />
<MfaPolicySettings tenantId={tenantId} />
</Tab>
{membership.role === 'owner' && (
<Tab label="Settings">
<TenantSettings tenantId={tenantId} />
<DangerZone tenantId={tenantId} />
</Tab>
)}
</Tabs>
);
}
Best Practices¶
✅ Do¶
- Keep at least 2 admins - Avoid single point of failure
- Enable MFA for admins - Protect privileged accounts
- Verify your domain - Better security, auto-join
- Review members regularly - Remove inactive users
- Use SSO when possible - Centralize identity
❌ Don't¶
- Don't make everyone admin - Least privilege principle
- Don't skip MFA for admins - High-value targets
- Don't ignore inactive invitations - Clean up or resend
- Don't transfer ownership carelessly - Hard to reverse