How to change realm user password when using jwt auth

I’m using custom JWT for authorization.

When I trigger a password reset, using either the internal email confirmed reset or a custom reset password function, the next time I login using JWT, a different user is created with the same name and I can no longer access the existing account.

Hi @Ryan_Goodwin,

The Custom JWT is coming from an external authentication service, so the password reset needs to be handled completely on that service, Realm doesn’t have a password for the users authenticated that way, then cannot reset nor change it.

It will be that service responsibility, after the password reset, to send the same user id in the token payload, so that Realm will still recognise the same user (in other words, the sub claim shouldn’t change after the reset). If a different sub claim is sent, a new user will be created.

Thanks for the response @Paolo_Manna
I understand that what you describe is supposed to be the case.
However, it doesn’t seem to be working in my experience.

I am handling JWT on my own service. I successfully change the password for the user on that service.

I then attempt to change the realm password via custom function. This only works with one specific user. Attempting on any other user returns a ‘User not found’ error.

Now when I have run the realm password change function against that specific user that it does seem to work with, if I then create a JWT with the corresponding unique user id under the .sub key in the payload, Realm creates a new user.

At this point, I’m switching to .emailPassword authentication through Realm and partially ditching my jwt system. It’s not ideal, but I’ve been struggling to get responses on these forums. Here’s a related post if that helps at all.

I was able to get this to work, finally.
The main point of confusion was that it was not working with older users in my system.
It may be that in the past I created some users with a sub key that is not their user id. I can’t figure out what the sub might have been. And I don’t see any way to figure it out? So I think I’m going to have to create new users and port over the data associated with those users to the new users.

Some random notes about how this ended up working, in case it helps someone someday:

I create a user. This is the Mongo Record:

Then I verify that user by providing a token supplied in the verification email.
Then I authenticate that user to my system, accepting email and password…
And returning a token…
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6ZmFsc2UsInVzZXIiOiJreXR5ZmVAb25la2lzc3ByZXNhdmUuY29tIiwic3ViIjoiNjFiM2JmNmYzZjc2NDQwMDE2Nzk3MDY2IiwiYXVkIjoiZnVua3ktcmFkaXNoLXR3ZHh2IiwiYXV0aG9yIjoiIiwiaWF0IjoxNjM5MTY5OTAzLCJleHAiOjE2MzkyNTYzMDN9.ShCk95HD-BiZp80jujg6xdFwOpXZXsq0XCboIzHMRjl8a1_9ixseb8JskbYFczKkt9tSejI8tjzzMymO3WRZjxp0bzKg6qlNAfhzKzCzsDOTPMpjNtl9W95RY-0PVH7N7G5l_yUqFumfn6_JtPJQ1AGOQXyJcZWuLMNHHek0-BRReRN8wjcPLKVA5E7yGi1VFKSm38IyiQl7I1ZsiFjuP60AU9xu9_yqMhg9vY4JrIGgCdz6dNT_XHL5jxW4C0DtR89hhsXLTeNrod7xi-OVshPScq2efSunVNVryhAZNolOSHTeoIAHRRP2GeS73er5s979JyzVNUprUEoQwFI27w

Here’s what the payload looks like:

{
  "admin": false,
  "user": "kytyfe@onekisspresave.com",
  "sub": "61b3bf6f3f76440016797066",
  "aud": "funky-radish-twdxv",
  "author": "",
  "iat": 1639169903,
  "exp": 1639256303
}

So I then use that token in a realm credential and login.

const credentials = Realm.Credentials.jwt(token)
return realmApp.logIn(credentials)

And here’s the response, a new Realm user.

{
	"id": "61b3c21290cda269ec058e8f",
	"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJiYWFzX2RldmljZV9pZCI6IjYxYjNjMjEyOTBjZGEyNjllYzA1OGVjYiIsImJhYXNfZG9tYWluX2lkIjoiNWYwY2E5Zjk1NWJhYjVkZWZhODI5ZGM5IiwiZXhwIjoxNjM5MTcyMzc5LCJpYXQiOjE2MzkxNzA1NzksImlzcyI6IjYxYjNjMjEzOTBjZGEyNjllYzA1OGYwMiIsInN0aXRjaF9kZXZJZCI6IjYxYjNjMjEyOTBjZGEyNjllYzA1OGVjYiIsInN0aXRjaF9kb21haW5JZCI6IjVmMGNhOWY5NTViYWI1ZGVmYTgyOWRjOSIsInN1YiI6IjYxYjNjMjEyOTBjZGEyNjllYzA1OGU4ZiIsInR5cCI6ImFjY2VzcyJ9.hC807g-l0mNML9wgQ94VtNQUJZoUD8JQ61HFbFVCqC4",
	"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJiYWFzX2RhdGEiOm51bGwsImJhYXNfZGV2aWNlX2lkIjoiNjFiM2MyMTI5MGNkYTI2OWVjMDU4ZWNiIiwiYmFhc19kb21haW5faWQiOiI1ZjBjYTlmOTU1YmFiNWRlZmE4MjlkYzkiLCJiYWFzX2lkIjoiNjFiM2MyMTM5MGNkYTI2OWVjMDU4ZjAyIiwiYmFhc19pZGVudGl0eSI6eyJpZCI6IjYxYjNiZjZmM2Y3NjQ0MDAxNjc5NzA2NiIsInByb3ZpZGVyX3R5cGUiOiJjdXN0b20tdG9rZW4iLCJwcm92aWRlcl9pZCI6IjVmYmM2ZWE1YjUyZjRiODdiM2IzZGM5NyJ9LCJleHAiOjE2NDQzNTQ1NzksImlhdCI6MTYzOTE3MDU3OSwic3RpdGNoX2RhdGEiOm51bGwsInN0aXRjaF9kZXZJZCI6IjYxYjNjMjEyOTBjZGEyNjllYzA1OGVjYiIsInN0aXRjaF9kb21haW5JZCI6IjVmMGNhOWY5NTViYWI1ZGVmYTgyOWRjOSIsInN0aXRjaF9pZCI6IjYxYjNjMjEzOTBjZGEyNjllYzA1OGYwMiIsInN0aXRjaF9pZGVudCI6eyJpZCI6IjYxYjNiZjZmM2Y3NjQ0MDAxNjc5NzA2NiIsInByb3ZpZGVyX3R5cGUiOiJjdXN0b20tdG9rZW4iLCJwcm92aWRlcl9pZCI6IjVmYmM2ZWE1YjUyZjRiODdiM2IzZGM5NyJ9LCJzdWIiOiI2MWIzYzIxMjkwY2RhMjY5ZWMwNThlOGYiLCJ0eXAiOiJyZWZyZXNoIn0.2ejD0bvSzmb6ZZJx34WV67eJNGhjOrrBGrcSWaSPiPw",
	"profile": {
		"type": "normal",
		"identities": [{
			"id": "61b3bf6f3f76440016797066",
			"providerType": "custom-token"
		}],
		"data": {
			"name": "kytyfe@onekisspresave.com",
			"admin": false
		}
	},
	"state": "active",
	"customData": {}
}

So then I trigger a password reset email to that account, including a password reset token.

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2MWIzYmY2ZjNmNzY0NDAwMTY3OTcwNjYiLCJpYXQiOjE2MzkxNzA5ODUsImV4cCI6MTYzOTI1NzM4NX0.Qr7pVfeyAQRtVhAfFAVv721Pw5xaWqRbRT_jUJejyXfFAtDcwvBRAKXnE1iwAct0XS62schikkl5VedOSkRTLFXjezsSw6HKGNK-8RnPw2osnihNEfYwgC9ZC-LVT3TfY0aGNmwI8TtN9VxbHWrvZWRPaa6x0tBBq2NjpjYXn1uaCkaMmasmH-y5wmbYOf5cU3O56Ywf69s5EeHAAUtlabWOyJbDt9dEUGm631L-PcVBE9qXKFtyu_3Vug6c8ZhT7fZw1WT_5x3k-9YAKPHTh2BLtapdDIq0S9hGSsgBzqxI5dtfYj2WSyXbmcvGaWdiaiDxV6ksoHieP_RYJMLvFw

And that token payload decodes to this:

{
  "userId": "61b3bf6f3f76440016797066",
  "iat": 1639170985,
  "exp": 1639257385
}

So then I hit my endpoint to change the user’s password.
And I verify that the password hash on that mongo record has changed.
Which means I can now authenticate to my system with the new password.
I authenticate to my system and return this token…

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6ZmFsc2UsInVzZXIiOiJreXR5ZmVAb25la2lzc3ByZXNhdmUuY29tIiwic3ViIjoiNjFiM2JmNmYzZjc2NDQwMDE2Nzk3MDY2IiwiYXVkIjoiZnVua3ktcmFkaXNoLXR3ZHh2IiwiYXV0aG9yIjoiIiwiaWF0IjoxNjM5MTcxOTA0LCJleHAiOjE2MzkyNTgzMDR9.rKiF5QndEXhbtSxQzbZnk-wArmrgYFR2fAOa-FUz4SPaQP1Un5g0dRc2aZX_qnEpwLIMQscRIUNOZ0K0pGa8Jdq668kcbjXlMR_TmC5WoB3_hd5tRaNei6w8y555QWpZan1tcElOHnB_TsAALcmG7HgeEmBkZ-Cf6oj582RgCGAWhQH9UL2HbC-R3fuA12DvfhBsaMyb5r9J_jPEUQSTmDg2zfLjAjVjvG6EqaWkw45iao9J8bMWxw_xaxnSwR3EZLAqu7-m_QnhDZCqJvvvljqxi273on9yQHQ2o4P7x5mZlerwcrDcnqp0Eo2sDV0i0JKav3T3sKYbJpE4CfescQ

Where the payload looks like this:

{
  "admin": false,
  "user": "kytyfe@onekisspresave.com",
  "sub": "61b3bf6f3f76440016797066",
  "aud": "funky-radish-twdxv",
  "author": "",
  "iat": 1639171904,
  "exp": 1639258304
}

The sub is the same…
But when I try to connect to Realm using that token…
Apparently it totally works… WTF!

{
	"id": "61b3c21290cda269ec058e8f",
	"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJiYWFzX2RldmljZV9pZCI6IjYxYjNjMjEyOTBjZGEyNjllYzA1OGVjYiIsImJhYXNfZG9tYWluX2lkIjoiNWYwY2E5Zjk1NWJhYjVkZWZhODI5ZGM5IiwiZXhwIjoxNjM5MTczOTU0LCJpYXQiOjE2MzkxNzIxNTQsImlzcyI6IjYxYjNjODNhZjEyNzM5MDBkMGM2YmJhMCIsInN0aXRjaF9kZXZJZCI6IjYxYjNjMjEyOTBjZGEyNjllYzA1OGVjYiIsInN0aXRjaF9kb21haW5JZCI6IjVmMGNhOWY5NTViYWI1ZGVmYTgyOWRjOSIsInN1YiI6IjYxYjNjMjEyOTBjZGEyNjllYzA1OGU4ZiIsInR5cCI6ImFjY2VzcyJ9.koROJ_t9H5em1J7au4BRZIigNhNQ4AOHQj5d6N6BoEA",
	"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJiYWFzX2RhdGEiOm51bGwsImJhYXNfZGV2aWNlX2lkIjoiNjFiM2MyMTI5MGNkYTI2OWVjMDU4ZWNiIiwiYmFhc19kb21haW5faWQiOiI1ZjBjYTlmOTU1YmFiNWRlZmE4MjlkYzkiLCJiYWFzX2lkIjoiNjFiM2M4M2FmMTI3MzkwMGQwYzZiYmEwIiwiYmFhc19pZGVudGl0eSI6eyJpZCI6IjYxYjNiZjZmM2Y3NjQ0MDAxNjc5NzA2NiIsInByb3ZpZGVyX3R5cGUiOiJjdXN0b20tdG9rZW4iLCJwcm92aWRlcl9pZCI6IjVmYmM2ZWE1YjUyZjRiODdiM2IzZGM5NyJ9LCJleHAiOjE2NDQzNTYxNTQsImlhdCI6MTYzOTE3MjE1NCwic3RpdGNoX2RhdGEiOm51bGwsInN0aXRjaF9kZXZJZCI6IjYxYjNjMjEyOTBjZGEyNjllYzA1OGVjYiIsInN0aXRjaF9kb21haW5JZCI6IjVmMGNhOWY5NTViYWI1ZGVmYTgyOWRjOSIsInN0aXRjaF9pZCI6IjYxYjNjODNhZjEyNzM5MDBkMGM2YmJhMCIsInN0aXRjaF9pZGVudCI6eyJpZCI6IjYxYjNiZjZmM2Y3NjQ0MDAxNjc5NzA2NiIsInByb3ZpZGVyX3R5cGUiOiJjdXN0b20tdG9rZW4iLCJwcm92aWRlcl9pZCI6IjVmYmM2ZWE1YjUyZjRiODdiM2IzZGM5NyJ9LCJzdWIiOiI2MWIzYzIxMjkwY2RhMjY5ZWMwNThlOGYiLCJ0eXAiOiJyZWZyZXNoIn0.xYRuCq_zlbI2kAjJCazKEVyB0sNSuP8xy24GHkV9Oqs",
	"profile": {
		"type": "normal",
		"identities": [{
			"id": "61b3bf6f3f76440016797066",
			"providerType": "custom-token"
		}],
		"data": {
			"name": "kytyfe@onekisspresave.com",
			"admin": false
		}
	},
	"state": "active",
	"customData": {}
}