Cannot set user.username from Google reconciliation lambda
-
I've modified the default google reconciliation lambda to add a default username:
// This is the default Google reconcile, modify this to your liking. function reconcile(user, registration, idToken) { // Un-comment this line to see the idToken object printed to the event log // console.info(JSON.stringify(idToken, null, 2)); // The idToken is the response from the tokeninfo endpoint // https://developers.google.com/identity/sign-in/web/backend-auth#calling-the-tokeninfo-endpoint console.info('Google User Object-------------------------'); console.info(JSON.stringify(idToken, null, 2)); user.firstName = idToken.given_name; user.lastName = idToken.family_name; user.fullName = idToken.name+"(really)"; user.username = user.firstName; user.userName = user.lastName; user.imageUrl = idToken.picture; console.info('User Object-------------------------'); console.info(JSON.stringify(user, null, 2)); console.info('Registration Object-------------------------'); console.info(JSON.stringify(registration, null, 2));
I've set it up so that if a user does not already exist for the application and they log in with a google login, the user will be created and a registration for the application will be created. the user is created but the username is not set for either the user or the application registration.
I'm assuming that if I can set the user username, it will carry through to the registration, and if there is already a username for another user, it will add random numbers per the configuration for the application.
However, the reconciliation lambda doesn't add the username, and although debugging is turned on for the lambda, the console.info lines in the lambda don't appear in the logs (I've tried modifying the fullname just to verify that this is the lambda that is being hit, and it is).
Please assist!
-
I need to be able to ensure that the application has a unique username for every user. I can munge it together by setting the username to be required as part of the registration form, but when logging in using a google account, this means that it's an extra required step, and all I need is the the firstname+lastname+an optional disambiguator (which would seem to be supported based on the configuration parameter). It's really frustrating that the debug logging doesn't work, and that I can't set the user's username. It would also be nice if I could use a lambda to set the registration username. I thought about using a webhook also (since that has a registration hook) and calling back to the API to set the username, but I'm assuming I can't do that since the registration hasn't finished being created at the time the webhook has been called.
-
You can enforce unique usernames at the tenant level: https://fusionauth.io/docs/v1/tech/core-concepts/tenants/
Have you explored this option?
This is a feature which requires a paid edition.
-
@dan I am a paid client. My tenant settings are as follows:
My application settings include the following:
When I log in for the first time using a google account, FusionAuth creates a user and a registration, and populates user.firstName, user.lastName, user.FullName, and user.imageUrl. However, it does not create a username (shows in the user console as - ). What I'd like to have happen is that it will create a default username of fistname+lastname, and if that username is already taken, it will automatically append a -### where the ### is chosen randomly, which looks like what should happen based on the tenant settings above. Instead, though, it doesn't create any username at all. The lambda function was an attempt to set the username manually, assuming that the rules for disambiguating duplicate usernames would kick in if it were populated. I can't debug what might be causing the problem (ex. I'm populating the wrong object property) since, although debugging is turned on for the lambda function, the console log statements are not being printed to the logs. -
OK, so based on the the information posted in response to #1356, there's no real way to do what I was looking to do, unless a webhook is fired after the db transaction completes (I was thinking I could receive notification of user creation via webhook, make an api call to set the username, but that won't work if the transaction isn't already committed. It also sounds like the lambda is being fired after validation checks have been run, which is an odd design decision.
I'd still like to know why turning on debug logs isn't working for the lambda.
-
Disclaimer - missed the above replies before submitting mine below :
@alex said in Cannot set user.username from Google reconciliation lambda:
It's really frustrating that the debug logging doesn't work
Can you elaborate on this a bit? Are you able to see anything in the event log (
sidebar > system > event log
)?Also, Unique user names were introduced in 1.27 with a paid edition (developer or higher). I am not sure if this meets your use case (and definitely giving you the autonomy to stay on community edition if that is what you selected as a solution).
https://github.com/FusionAuth/fusionauth-issues/issues/1190
https://fusionauth.io/docs/v1/tech/apis/tenants/#request-bodytenant.usernameConfiguration.unique.enabled [Boolean] OPTIONAL Defaults to false AVAILABLE SINCE 1.27.0
When true, FusionAuth will handle username collisions by generating a random suffix.Note: A paid edition of FusionAuth is required to utilize unique usernames.
Also in paid editions, we introduce the idea of linking strategies when connecting users, fusionauth, and an IdP which may also fit your use case.
https://fusionauth.io/docs/v1/tech/identity-providers/#linking-strategiesI hope this helps!
Thanks,
Josh -
@joshua In turn:
Logs
I do see some entries in the log files, though I have no idea whether I'm seeing everything I should. There are some info level messages from startup, and after that I'm only seeing ERROR level, ex.:--------------------------------------------------------------------------------------------------------- --------------------------------- Starting FusionAuth version [1.29.0] ---------------------------------- --------------------------------------------------------------------------------------------------------- 2021-08-20 6:06:55.435 PM INFO io.fusionauth.api.plugin.guice.PluginModule - No plugins found 2021-08-20 6:06:55.902 PM INFO io.fusionauth.api.service.system.NodeService - Node [c3c92207-821a-436e-abdb-0768499f491e] started. 2021-08-20 6:06:57.092 PM INFO io.fusionauth.api.configuration.DefaultFusionAuthConfiguration - Loading FusionAuth configuration file [/usr/local/fusionauth/config/fusionauth.properties] 2021-08-20 6:06:57.093 PM INFO io.fusionauth.api.configuration.DefaultFusionAuthConfiguration - Dynamically set property [fusionauth-app.url] set to [http://10.0.3.205:9011] 2021-08-20 6:06:57.093 PM INFO com.inversoft.configuration.BasePropertiesFileInversoftConfiguration - - Overriding default value of property [database.mysql.enforce-utf8mb4] with value [true] - Overriding default value of property [database.mysql.connector-version] with value [8.0.21] - Overriding default value of property [fusionauth-app.runtime-mode] with value [development] - Overriding default value of property [search.type] with value [database] 2021-08-20 6:06:57.099 PM INFO com.inversoft.jdbc.hikari.DataSourceProvider - Connecting to PostgreSQL database at [jdbc:postgresql://fusionauthdb.cluster-coqfhgx4e2sj.us-east-1.rds.amazonaws.com:5432/fusionauthdb] 2021-08-20 6:06:57.101 PM WARN com.zaxxer.hikari.HikariConfig - HikariPool-1 - idleTimeout has been set but has no effect because the pool is operating as a fixed size pool. 2021-08-20 6:06:57.106 PM INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting... 2021-08-20 6:06:57.245 PM INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed. 2021-08-20 6:06:59.512 PM INFO com.inversoft.scheduler.DefaultScheduler - Starting up scheduler 2021-08-20 6:06:59.513 PM INFO com.inversoft.scheduler.DefaultScheduler - Scheduler is running 2021-08-20 6:07:01.488 PM INFO io.fusionauth.api.service.system.NodeService - Node [c3c92207-821a-436e-abdb-0768499f491e] added with address [http://10.0.3.205:9011] 2021-08-20 6:07:01.556 PM INFO io.fusionauth.api.service.system.NodeService - Node [c3c92207-821a-436e-abdb-0768499f491e] promoted to master at [2021-08-20T18:07:01.556806Z], the previous master Node [f628dd78-ba19-46dd-8950-b0da92f35bd5] has been shutdown or removed
I don't see any info messages from the lambda function at the beginning of this chain (although, as mentioned, I have verified that the lambda is being called by customizing the user.fullname to something not in the default handler.
Paid edition
Yes, I have a paid edition, specifically in order to be able to get unique usernames.Unique Usernames
Although I'm using e-mail as the mapping key for the google authenticator, what I want it to do is also generate a unique username. In our application, we have links to user profiles, so we need a unique username (putting an e-mail address in the url is, well, I'm sure I don't need to enumerate all the reasons why that would be bad). What I would have expected is that since I've set it to require unique usernames and there's an autogeneration strategy set to disambiguate usernames, that If I set the username on the way in from the google connector, it would disambiguate as necessary (since my assumption would have been that the validation was downstream from all entry points, whether html forms for the self-service pages or registration via another identity provider.What I'd really like to be able to do is the following:
- The user account is uniquely identified by a username.
- When a user first logs in using an outside identifier, the usename is created based on one or more of the fields (my choice, per identity provider), and if that username is taken, it appends some random numbers according to the disambiguation strategy already present in the configuration.
- the user can add an alternate identity provider with a different e-mail address linked to the same username only when logged into the original account.
- The user can merge accounts (including all application specific data) by requesting a merge. The requested-of account would receive an e-mail notification asking permission to merge, which would be valid for a short/customizable period of time.
However, since there doesn't seem to be a way to customize how the username is generated, and since google doesn't provide a username via whatever field you're mapping it to, it seems like that's not going to be possible.
Have I got that right?
-
I was out of the office last week, but am looking at this now.
I would say that you would be best served by checking the event logs. The logs that you have displayed here are from the main application and may not show as much debug information as the events logs do (when the debug toggle is enabled in the specific IdP and/or lambda).
Regarding your other questions, I was able to make an advanced registration form with both an email and username input. Since Google does not return a username, FusionAuth will send you to a complete registration page and ask for a username. The unique username policy set on the tenant will ensure no username collisions.
Then
my_user_name
becomes appended by the unique user name constraint set on the tenant
re:
The user can merge accounts (including all application-specific data) by requesting a merge. The requested-of account would receive an e-mail notification asking permission to merge, which would be valid for a short/customizable period of time.
We don't have this functionality exactly but have an approximation. On this user, notice the linked accounts tab. You can remove externally linked accounts here as an admin. Additionally, if you set
create a pending link
, as your linking strategy (instead oflink on email
), you can have your user login with google and associate that google UUID to an existing FusionAuth user (or create a new user).I am not sure if this fully addresses what you are asking. My encouragement would be to review the documentation that we just released around linking IdP accounts, linking strategies, etc.
https://fusionauth.io/docs/v1/tech/identity-providers/Here for any further clarification needed
Thanks,
JoshThanks,
Josh
FusionAuth