G
GTM Vault
Browse
  • Dashboard
    • Automations
    • Skills
    • Prompts
    • Makers
  • Sign in
All Skills

netlify-identity

Reference for Netlify Identity setup — role-based access, GoTrue JS signup, custom user_metadata, Identity widget

skillInfrastructureClaude Code SkillsInternal Ops
Original
by Roheel Jain
Skill Content

Role-Based Access Control (netlify.toml)

Correct approach:

  • Redirect rules process top-to-bottom, first match wins
  • Must add explicit passthrough for public pages BEFORE catch-all /* rules
  • Role-gated rule needs force = true and conditions = {Role = ["rolename"]}
  • Fallback redirect also needs force = true
# 1. Passthrough — public pages
[[redirects]]
  from = "/login.html"
  to = "/login.html"
  status = 200

# 2. Role-gated access
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200
  force = true
  conditions = {Role = ["viewer"]}

# 3. Fallback — unauthenticated users
[[redirects]]
  from = "/*"
  to = "/login.html"
  status = 302
  force = true

Common errors:

  • Missing passthrough for login page → 404 because force=true on /* catches it in a loop
  • Missing force=true on fallback → doesn't override existing files
  • Relying only on server-side redirects without client-side backup

Roles

Correct approach:

  • There is NO "default role" setting in Netlify Identity UI
  • Roles are assigned per-user manually (Identity → Users → Edit settings → Roles field)
  • To auto-assign roles at signup: create netlify/functions/identity-signup.js
  • Role changes require logout + login to take effect (JWT refresh)
// netlify/functions/identity-signup.js
exports.handler = async (event) => {
    const { user } = JSON.parse(event.body);
    return {
        statusCode: 200,
        body: JSON.stringify({
            app_metadata: { ...user.app_metadata, roles: ['viewer'] },
        }),
    };
};

Common errors:

  • Assuming a "default role" setting exists — it doesn't
  • Forgetting to assign role to existing users → role-based redirect doesn't match

GoTrue JS for Custom Signup

  • Identity widget does NOT support custom form fields in its signup modal
  • Use GoTrue JS directly for signup with custom user_metadata:
    const auth = new GoTrue({ APIUrl: `${window.location.origin}/.netlify/identity`, setCookie: true });
    await auth.signup(email, password, { full_name, linkedin_url, company_name });
    
  • user_metadata is NOT visible in Netlify Identity UI but is stored on the user object
  • CDN: https://unpkg.com/gotrue-js@0.9.29/dist/gotrue.js

Identity Widget

  • Open login: netlifyIdentity.open('login')
  • Listen for login: netlifyIdentity.on('login', callback)
  • Check session: netlifyIdentity.currentUser()
  • Logout: netlifyIdentity.logout()
  • CDN: https://identity.netlify.com/v1/netlify-identity-widget.js

Client-Side Auth Check (Backup)

  • Register widget.on('init', callback) IMMEDIATELY — not inside DOMContentLoaded
  • Add widget.currentUser() fallback for when init already fired
  • Add timeout safety net (3s) to prevent permanent blank page

Common error: Registering widget.on('init', ...) inside DOMContentLoaded → widget's init event already fired → callback never runs → page stays blank

Docs

  • Role-based access control
  • Manage Identity users
  • Identity in functions
  • GoTrue JS repo
Tech Stack
JavaScript
JavaScript