[GH-ISSUE #8573] [sso plugin] saml mappings doesn't seem to have any effect #19753

Open
opened 2026-04-15 19:05:35 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @formatlos on GitHub (Mar 12, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/8573

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Even though I can configure mapping like the following for SAML, it doesn't seem that additionalFields like firstName, lastName do get persisted to the user

mapping: {
    id: "nameID",
    email: "email",
    name: "displayName",
    firstName: "givenName",
    lastName: "surname",
    emailVerified: "email_verified",
    extraFields: {
        department: "department",
        role: "role"
    }
}

Current vs. Expected behavior

I'd expect that the additionalFields are getting persisted to the DB as well.

What version of Better Auth are you using?

1.5.4

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 24.6.0: Wed Nov  5 21:33:58 PST 2025; root:xnu-11417.140.69.705.2~1/RELEASE_ARM64_T6000",
    "release": "24.6.0",
    "cpuCount": 10,
    "cpuModel": "Apple M1 Max",
    "totalMemory": "64.00 GB",
    "freeMemory": "0.53 GB"
  },
  "node": {
    "version": "v22.14.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "10.9.2"
  },
  "frameworks": [
    {
      "name": "fastify",
      "version": "^5.5.0"
    }
  ],
  "databases": [
    {
      "name": "pg",
      "version": "^8.17.2"
    },
    {
      "name": "postgres",
      "version": "^3.4.8"
    },
    {
      "name": "@prisma/client",
      "version": "^6.18.0"
    },
    {
      "name": "kysely",
      "version": "^0.28.9"
    }
  ],
  "betterAuth": {
    "version": "^1.5.4"
    }
  }
}

Which area(s) are affected? (Select all that apply)

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
});

Additional context

No response

Originally created by @formatlos on GitHub (Mar 12, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/8573 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Even though I can configure mapping like the following for SAML, it doesn't seem that additionalFields like `firstName`, `lastName` do get persisted to the user ``` mapping: { id: "nameID", email: "email", name: "displayName", firstName: "givenName", lastName: "surname", emailVerified: "email_verified", extraFields: { department: "department", role: "role" } } ``` ### Current vs. Expected behavior I'd expect that the additionalFields are getting persisted to the DB as well. ### What version of Better Auth are you using? 1.5.4 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 24.6.0: Wed Nov 5 21:33:58 PST 2025; root:xnu-11417.140.69.705.2~1/RELEASE_ARM64_T6000", "release": "24.6.0", "cpuCount": 10, "cpuModel": "Apple M1 Max", "totalMemory": "64.00 GB", "freeMemory": "0.53 GB" }, "node": { "version": "v22.14.0", "env": "development" }, "packageManager": { "name": "npm", "version": "10.9.2" }, "frameworks": [ { "name": "fastify", "version": "^5.5.0" } ], "databases": [ { "name": "pg", "version": "^8.17.2" }, { "name": "postgres", "version": "^3.4.8" }, { "name": "@prisma/client", "version": "^6.18.0" }, { "name": "kysely", "version": "^0.28.9" } ], "betterAuth": { "version": "^1.5.4" } } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, }); ``` ### Additional context _No response_
GiteaMirror added the enterpriseidentity labels 2026-04-15 19:05:35 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Mar 12, 2026):

This is actually expected behavior, not a bug. The SSO plugin extracts firstName, lastName, and extraFields from SAML attributes, but only the standard user fields (email, name, id, emailVerified) are persisted to the database. The firstName and lastName are combined into a single name field and then discarded.

To persist these additional fields, you'll need to:

1. Extend the user schema with a plugin:

const samlAttributesPlugin = () => ({
  id: "saml-attributes",
  schema: {
    user: {
      fields: {
        firstName: { type: "string", required: false },
        lastName: { type: "string", required: false },
        department: { type: "string", required: false },
        role: { type: "string", required: false },
      },
    },
  },
});

2. Use provisionUser to save the fields:

sso({
  provisionUser: async ({ user, userInfo }) => {
    // userInfo contains all mapped fields including extraFields
    await auth.api.updateUser({
      userId: user.id,
      update: {
        firstName: userInfo.firstName,
        lastName: userInfo.lastName,
        department: userInfo.department,
        role: userInfo.role,
      },
    });
  },
})

Run npx auth migrate after adding the schema plugin to update your database. Note that provisionUser is called on every SAML authentication, so attributes will stay in sync with your IdP.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:4047875076 --> @dosubot[bot] commented on GitHub (Mar 12, 2026): <!-- Answer --> This is actually expected behavior, not a bug. The SSO plugin extracts `firstName`, `lastName`, and `extraFields` from SAML attributes, but [only the standard user fields (`email`, `name`, `id`, `emailVerified`) are persisted to the database](https://github.com/better-auth/better-auth/blob/db5a44424f5747c47a7da347613e42b664e1e734/packages/sso/src/routes/sso.ts#L2386-L2402). The `firstName` and `lastName` are [combined into a single `name` field](https://github.com/better-auth/better-auth/blob/db5a44424f5747c47a7da347613e42b664e1e734/packages/sso/src/routes/sso.ts#L2332-L2359) and then discarded. To persist these additional fields, you'll need to: **1. Extend the user schema with a plugin:** ```typescript const samlAttributesPlugin = () => ({ id: "saml-attributes", schema: { user: { fields: { firstName: { type: "string", required: false }, lastName: { type: "string", required: false }, department: { type: "string", required: false }, role: { type: "string", required: false }, }, }, }, }); ``` **2. Use [`provisionUser`](https://better-auth.com/docs/plugins/sso#user-provisioning) to save the fields:** ```typescript sso({ provisionUser: async ({ user, userInfo }) => { // userInfo contains all mapped fields including extraFields await auth.api.updateUser({ userId: user.id, update: { firstName: userInfo.firstName, lastName: userInfo.lastName, department: userInfo.department, role: userInfo.role, }, }); }, }) ``` Run `npx auth migrate` after adding the schema plugin to update your database. Note that `provisionUser` is [called on every SAML authentication](https://github.com/better-auth/better-auth/blob/db5a44424f5747c47a7da347613e42b664e1e734/packages/sso/src/routes/sso.ts#L2412-L2418), so attributes will stay in sync with your IdP. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=brand-link).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/7695f24d-7eb8-49ff-a976-e4ceca099a40?feedback_type=great_response&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/7695f24d-7eb8-49ff-a976-e4ceca099a40?feedback_type=irrelevant_answer&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/7695f24d-7eb8-49ff-a976-e4ceca099a40?feedback_type=incorrect_sources&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/7695f24d-7eb8-49ff-a976-e4ceca099a40?feedback_type=too_verbose&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/7695f24d-7eb8-49ff-a976-e4ceca099a40?feedback_type=hallucination&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/7695f24d-7eb8-49ff-a976-e4ceca099a40?feedback_type=bug_report&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-bug_report) | [Other](https://app.dosu.dev/response-feedback/7695f24d-7eb8-49ff-a976-e4ceca099a40?feedback_type=other&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=chat-badge)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20is%20actually%20expected%20behavior%2C%20not%20a%20bug.%20The%20SSO%20plugin%20extracts%20%60firstName%60%2C%20%60lastName%60%2C%20and%20%60extraFields%60%20from%20SAML%20attributes%2C%20but%20%5Bonly%20the%20standard%20user%20fields%20%28%60email%60%2C%20%60name%60%2C%20%60id%60%2C%20%60emailVerified%60%29%20are%20persisted%20to%20the%20database%5D%28https%3A//github.com/better-auth/better-auth/blob/db5a44424f5747c47a7da347613e42b664e1e734/packages/sso/src/routes/sso.ts%23L2386-L2402%29.%20The%20%60firstName%60%20and%20%60lastName%60%20are%20%5Bcombined%20into%20a%20single%20%60name%60%20field%5D%28https%3A//github.com/better-auth/better-auth/blob/db5a44424f5747c47a7da347613e42b664e1e734/packages/sso/src/routes/sso.ts%23L2332-L2359%29%20and%20then%20discarded.%0A%0ATo%20persist%20these%20additional%20fields%2C%20you%27ll%20need%20to%3A%0A%0A%2A%2A1.%20Extend%20the%20user%20schema%20with%20a%20plugin%3A%2A%2A%0A%60%60%60typescript%0Aconst%20samlAttributesPlugin%20%3D%20%28%29%20%3D%3E%20%28%7B%0A%20%20id%3A%20%22saml-attributes%22%2C%0A%20%20schema%3A%20%7B%0A%20%20%20%20user%3A%20%7B%0A%20%20%20%20%20%20fields%3A%20%7B%0A%20%20%20%20%20%20%20%20firstName%3A%20%7B%20type%3A%20%22string%22%2C%20required%3A%20false%20%7D%2C%0A%20%20%20%20%20%20%20%20lastName%3A%20%7B%20type%3A%20%22string%22%2C%20required%3A%20false%20%7D%2C%0A%20%20%20%20%20%20%20%20department%3A%20%7B%20type%3A%20%22string%22%2C%20required%3A%20false%20%7D%2C%0A%20%20%20%20%20%20%20%20role%3A%20%7B%20type%3A%20%22string%22%2C%20required%3A%20false%20%7D%2C%0A%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%7D%2C%0A%20%20%7D%2C%0A%7D%29%3B%0A%60%60%60%0A%0A%2A%2A2.%20Use%20%5B%60provisionUser%60%5D%28https%3A//better-auth.com/docs/plugins/sso%23user-provisioning%29%20to%20save%20the%20fields%3A%2A%2A%0A%60%60%60typescript%0Asso%28%7B%0A%20%20provisionUser%3A%20async%20%28%7B%20user%2C%20userInfo%20%7D%29%20%3D%3E%20%7B%0A%20%20%20%20//%20userInfo%20contains%20all%20mapped%20fields%20including%20extraFields%0A%20%20%20%20await%20auth.api.updateUser%28%7B%0A%20%20%20%20%20%20userId%3A%20user.id%2C%0A%20%20%20%20%20%20update%3A%20%7B%0A%20%20%20%20%20%20%20%20firstName%3A%20userInfo.firstName%2C%0A%20%20%20%20%20%20%20%20lastName%3A%20userInfo.lastName%2C%0A%20%20%20%20%20%20%20%20department%3A%20userInfo.department%2C%0A%20%20%20%20%20%20%20%20role%3A%20userInfo.role%2C%0A%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%7D%29%3B%0A%20%20%7D%2C%0A%7D%29%0A%60%60%60%0A%0ARun%20%60npx%20auth%20migrate%60%20after%20adding%20the%20schema%20plugin%20to%20update%20your%20database.%20Note%20that%20%60provisionUser%60%20is%20%5Bcalled%20on%20every%20SAML%20authentication%5D%28https%3A//github.com/better-auth/better-auth/blob/db5a44424f5747c47a7da347613e42b664e1e734/packages/sso/src/routes/sso.ts%23L2412-L2418%29%2C%20so%20attributes%20will%20stay%20in%20sync%20with%20your%20IdP.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=join-discord)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/8573)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#19753