Add a new user using a token?

How do you add a new user to Ghost when the e-mail link is not working or e-mail is not set up at all? I have the invite token here now. So now what? This is an idea I picked up from @egg in an old forum post and I thought I might want to give this a try. Perhaps Fabien would be so kind and shed some light on this?

I am running Ghost 3.12.1 on Ubuntu 18.04 LTS and Nginx 1.14.0.

In my opinion there should be a built in mechanism for adding new users to Ghost without e-mail verification.

I have created a new user, but I was unable to circumvent the e-mail verification requirement. Despite having the invitation token and the correct URL format. So there must be more to it, and I don’t bother hacking the verification code, it’s not worth my time.

For the record, the correct URL format is:
http://yourdomain.tld/ghost/signup/invitation-token-in-base64/

So just to be absolutely clear here, I was looking for a way to add new users to a Ghost production environment from the admin panel without having to go through the verification process using e-mail. Why, you may ask? Because… why not? If I’m the only owner and I’m creating users for my own needs. Why do I need to prove to myself that I am who I say I am by sending out a verification e-mail?.. from myself to myself?.. But more specifically, it’s because e-mail was not configured in my Ghost installation at the time.

So the proposed solution I found (link above) was to get to the database and find the “token” (presumably invitation token). That is, I would use that token as if I had received it by e-mail to activate the new account, or at least that’s my interpretation of how this would work. But this proved to be nothing but a futile exercise. For starters, I did not know the URL path for invitation links that Ghost uses. Because as with all e-mail based account verifications, you would get a link to click on, so the verification is done over HTTP (or HTTPS).

So I ended up doing it the “right way” by configuring e-mail for my Ghost installation. I then created a dummy account and had an e-mail sent to a valid e-mail address. Once I had that first invitation e-mail, I knew how to format the URL for activating new Ghost user accounts. So I tested this theory with my previously created user account for which the invitation token was still pending (it’s valid up to 7 days). But this only proved to produce “invalid token” messages. In fact, I subsequently tried to create additional Ghost user accounts, now that I had a working e-mail configuration. I tried using invalid recipient e-mail addresses and I was unable to use the invitation tokens from the database to activate these new user accounts. It had to be a valid e-mail address for activation to be a success, and even then, it only worked if the e-mail was successfully sent to the recipient. And even then, it had to be an e-mail address that was not previously used (even though the original had been modified since), or alternatively you had to click on the link in the e-mail because the “grab the token from database” method did not work at all.

This is the message you will get if the registered e-mail has already been used once (and changed to something else for an existing account).

This is the “invalid token” message you will get if you are signed in while trying to activate the new account. You have to sign out your current user first. Another reason you would want to be able to do this the easy way right from the admin panel whilst still signed in as owner and without having to go through the e-mail verification process…

Whit your current user signed out, this is the “invalid token” message you will get when trying to activate the new user.

Grabbing the invitation token from the database and using that to activate a new Ghost user account will not work. E-mail needs to be configured for Ghost to use, and an e-mail must be sent to a valid e-mail address. Alternatively, you may be able to create unverified users by other (unsupported) means like creating them directly in the database, or otherwise.

That’s correct, but you can modify the database to allow the account to be created. Update invites.status from pending to sent

Yeah, I figured that out. I had the status changed from “pending” to “sent”.

update invites set status='sent' where status='pending';

Unfortunately that did not help. I may be missing something, maybe not? Is there another token elsewhere that I need to use?

This issue may be unrelated, but I also found this guy suggesting the same approach:

He just sets all rows to “sent” and he does mention something about omitting the last = character and that’s something that I have been trying to figure out. Because my tokens often have PQ== at the end of the string. I’m not sure if it’s always like that, I have not been paying attention well enough. But I know that the length of a valid token is 104 characters. If memory serves me well mine have been 106 or 108 characters, if PQ== is included.

I managed to pull it off! I got lucky with a dummy e-mail address of gary@bikinibottom.org

Here I will demonstrate activation of a new user account. Below is the token from the database and associated e-mail address with its “pending” status.

+---------+--------------------------------------------------------------------------------------------------------------+------------------------+
| status  | token                                                                                                        | email                  |
+---------+--------------------------------------------------------------------------------------------------------------+------------------------+
| pending | MTU4NjIwNjA1ODE2MXx2b2xkZW1vcnRAaG9nd2FydHMub3JnfHh6NTVXbi9sNmZ4ZnNpY1BPK1ppaysyQXFuVzJrT2lhWFQrdS85bk9ITGc9 | voldemort@hogwarts.org |
+---------+--------------------------------------------------------------------------------------------------------------+------------------------+

The pending status needs to be cleared before proceeding to the next step. Here we see what happens if we fail to do so. So this is what the activation URL might look like.

https://example.com/ghost/signup/MTU4NjIwNjA1ODE2MXx2b2xkZW1vcnRAaG9nd2FydHMub3JnfHh6NTVXbi9sNmZ4ZnNpY1BPK1ppaysyQXFuVzJrT2lhWFQrdS85bk9ITGc9/

If we use this URL without first clearing the token status – that is updating it to “sent” – we get the following message.

The invitation does not exist or is no longer valid.


So we need to clear that first, and we can do that with the following SQL command.

update invites set status='sent' where status='pending';

The pending status has now been cleared…

+--------+--------------------------------------------------------------------------------------------------------------+------------------------+
| status | token                                                                                                        | email                  |
+--------+--------------------------------------------------------------------------------------------------------------+------------------------+
| sent   | MTU4NjIwNjA1ODE2MXx2b2xkZW1vcnRAaG9nd2FydHMub3JnfHh6NTVXbi9sNmZ4ZnNpY1BPK1ppaysyQXFuVzJrT2lhWFQrdS85bk9ITGc9 | voldemort@hogwarts.org |
+--------+--------------------------------------------------------------------------------------------------------------+------------------------+

So if we use the same URL again…

https://example.com/ghost/signup/MTU4NjIwNjA1ODE2MXx2b2xkZW1vcnRAaG9nd2FydHMub3JnfHh6NTVXbi9sNmZ4ZnNpY1BPK1ppaysyQXFuVzJrT2lhWFQrdS85bk9ITGc9/

We are greeted with a page for creating a new user account.

Create your account


Once we have provided our details we are signed in and welcomed to Ghost…

Welcome to Ghost (lord Voldemort)!

If we inspect the invites table, we can see that it’s empty now…

Empty set (0.00 sec)

All invitation tokens have been consumed.

Note that the token strings are of variable length. So 104, 106, 108, more or less, it’s all good. Also, more importantly, if the token string has any equal signs at the end, either double equal signs == or a single equal sign = , you will have to remove them before using the token in your URL.

Here is an example of such token that I used to activate my (lucky) Gary user account.

MTU4NjE5ODIxNTg4NHxnYXJ5QGJpa2luaWJvdHRvbS5vcmd8MnJrU0pIcCt3ejN2akVWTVlXQ1RzV1NBRjJQMFpkSTVHdXFqbkxiYzdKRT0=

The URL for this one would be (was)…

https://example.com/ghost/signup/MTU4NjE5ODIxNTg4NHxnYXJ5QGJpa2luaWJvdHRvbS5vcmd8MnJrU0pIcCt3ejN2akVWTVlXQ1RzV1NBRjJQMFpkSTVHdXFqbkxiYzdKRT0/

That’s all Folks! Happy ghosting!

That’s because there cannot be more than one equal sign once the token has been decoded.

Input:
MTU4NjE5ODIxNTg4NHxnYXJ5QGJpa2luaWJvdHRvbS5vcmd8MnJrU0pIcCt3ejN2akVWTVlXQ1RzV1NBRjJQMFpkSTVHdXFqbkxiYzdKRT0=

Output:
1586198215884|gary@bikinibottom.org|2rkSJHp+wz3vjEVMYWCTsWSAF2P0ZdI5GuqjnLbc7JE=

If the equal sign is ignored and then appended to the key. So instead of this:
2rkSJHp+wz3vjEVMYWCTsWSAF2P0ZdI5GuqjnLbc7JE=

You end up with this:
2rkSJHp+wz3vjEVMYWCTsWSAF2P0ZdI5GuqjnLbc7JE==

Which makes it invalid.

Of course, you’re not supposed to hacktivate your Ghost user accounts, but that’s beyond the point.