Using the IdentityResource as a an upsert_identity

Hi there, I’m trying to use Ash/AshAuthentication for the first time and I can’t tell if what I’m looking to do is support / even the right way of thinking of things. In my system there are Accounts and Channels. Each account have have multiple channels and each channel can have multiple connections to thinks like Twitch, Youtube, etc. Ideally we can use those social connections to sign in / register to set the current channel (and account).

When trying to create the register_with_youtube create action I’m having some trouble coming up with the upsert_identity. Channels are unique by username, but that’s not how I would normally look up a channel to login if I was building this scratch. Instead I would normally lookup the equivalent of the IdentityResource for (source = youtube, external_id = {id from oauth}) and if it exists login to the associated channel and if not exists I would proceed with the registration.

Is there a way to set the upsert_identity to be a property from a relation? Or am I thinking of the whole registration flow incorrectly?

I also have other questions about this flow, but I’ll save those for other threads.

Thank you so much!

@jimsynz may have some input here. You can’t use attributes from relationships to upsert, but what you might be able to do is look up the account for a given channel in a change (in a before action hook using Ash.Changeset.before_action) and upsert with the account_id?

I’m not personally familiar with how the identity resource + social sign ons work currently, unfortunately, so maybe @jimsynz will have some better advice than me :slight_smile:

1 Like

@jimsynz Wondering if you’ve had a chance to look at this yet. Do you know if this story is one that AshAuthentication would ever want to cover? Or would you recommend I just avoid AshAuthentication for now and just use raw assent myself?

Hey there. Sorry it took so long to reply.

I’ve been going around and around with various possible solutions in my head, but since AA treats OAuth registrations and sign-ins as essentially the same thing it does make it a little tricky.

The first thing that comes to mind is that I’m guessing that the Channel is already known as the intention is that the user is adding or signing in to external identity providers. If that’s the case then you can use the channel’s ID as the upsert identity. If you need to take specific action based on whether this is a sign-in or a registration I’d add an after_action hook (either to the Channel or user identity resource) that checks to see if the record is the result of an upsert - I think the best way to decide that is if the inserted_at and updated_at times are equal - and takes the appropriate action.

We perform both the registration and the user identity change as upserts to avoid having to perform a read/lock/update process.

This sort of use case is definitely the intention of the user identity resource, but to my knowledge it hasn’t been extensively used. If it’s missing features then please open issues/PRs and we’ll try our best to get them sorted.

1 Like