hippware / rn-chat

MIT License
5 stars 0 forks source link

Firebase dynamic links #2817

Closed bengtan closed 5 years ago

bengtan commented 6 years ago

We want to incorporate Firebase dynamic links so we can use it to create 'auto-friend' links (as discussed in #2722). So, something like this:

but it's unsure how many steps are needed to reach the end, nor what the in-between steps are.

For starters, let's just integrate the Firebase dynamic links library into the app. That will give us more insight into how it works, and how we can use it.

Optionally, if the developer can proceed beyond the first two steps, that would be a bonus.

southerneer commented 6 years ago

Dynamic Links are included in react-native-firebase so this would be the place to start: https://rnfirebase.io/docs/v4.3.x/links/ios

aksonov commented 5 years ago

@thescurry Should we start working on it before app release? I think it would be more sense to fix all bugs and publish new version first.

thescurry commented 5 years ago

Hello Aksonov, I'm going to delay the app release a week, so hopefully, we can accomplish both. Yes, please start.

aksonov commented 5 years ago

Okey, Firebase docs are pretty clear and I started creation of dynamic links. @thescurry Basically dynamic links are the deep links plus possibility to open these links after app install.

So we need to define full list of required links and their deep link URLs (every dynamic link should have http/https appropriate link).

I guess we need to have 'invite' dynamic link, so first we should implement 'invite' deep link (i.e. do some actions /open some UI or given link - need to have exact requirements here) and define https URLs for it (https://tinyrobot/*?) Also we must define 'fallback' URLs - what to show for unsupported devices (Android)

cc @bengtan

thescurry commented 5 years ago

Thanks for the feedback @aksonov. I'll discuss this with Beng tonight and get back to you.

southerneer commented 5 years ago

Seems like at a minimum we would need the ability to create dynamic links for bots with the following characteristics:

a) if the friend has the app already, the link takes them directly to the bot in the app b) if the friend doesn't have the app and taps the link on an iPhone, it directs them to the App Store and, after downloading the app, opening, and signing up, takes them directly to the bot c) if the friend taps the link on an Android or other non-mobile browser, take them to a page on the tinyrobot website.

bengtan commented 5 years ago

To make things easier to discuss, here's a stab at an hypothetical example. The following are intentionally contrived placeholders.

Let's say Alice is already on tinyrobot. Her user id is aaaaaaaa-e89b-12d3-a456-426655440000.

She wants to 'invite' Bob (who doesn't have a user account yet) so she sends a link which is a dynamic link.

The payload of the link is https://dynlink.tinyrobot.com/user/aaaaaaaa-e89b-12d3-a456-426655440000/follow which tells Bob's app (when it is installed) to open user aaaaaaaa-e89b-12d3-a456-426655440000 and follow it.

(Note: I don't think there's a way to make Alice follow Bob. Bob's account doesn't exist yet. So this only works for unidirectional follow. Well ... maybe there is a way to do bidirectional friending, but in a future iteration.)

Note that Alice invites Bob, but the link's payload action isn't to 'invite', but the reciprocal of 'invite' ie. 'follow' or 'accept'.

So the payload (which is the link parameter of the dynamic link) is decided. That's for the happy path.

However, we also need to define a lot of stuff for this one operation.

We also need to specify:

link - payload of the dynamic link - https://dynlink.tinyrobot.com/user/aaaaaaaa-e89b-12d3-a456-426655440000/follow

isi - app's App Store id - id1076718311 or 1076718311

ibi - app bundle id (com.hippware.ios.Chat?? I'm not sure) ifl - (mobile) web link to open if app isn't installed, if user is on iPhone or iPod

ipbi - app bundle id of iPad app (if applicable) ipfl - web link to open if app isn't installed, if user is on iPad

apn - package name of android app afl - web link to open if app isn't installed, if user is on Android

ofl - web link to open if the app isn't installed if user is on non-iOS, non-Android. This is optional, if ofl isn't specified, then it uses link instead.

Reference: https://firebase.google.com/docs/dynamic-links/create-manually

There's a bunch of other parameters documented in https://firebase.google.com/docs/dynamic-links/create-manually which I haven't included here, but these are the main ones, I think.

I think most of these are optional, but definitely link is required. Probably the app bundle (or android package name) needs to be in there.


So, in order to use dynamic links, we need to decide whether we want to implement fallback web links when the app is not installed, whether to have different web links for Android,iPhone,iPad,other, or whether to just not bother with the fallback web links for now (if it is viable).

And this is for each operation.

bengtan commented 5 years ago

Was talking with @thescurry. He wants the link to create a bidirectional friend.

This means that a payload like https://dynlink.tinyrobot.com/user/aaaaaaaa-e89b-12d3-a456-426655440000/follow is not going to work because, while user B can follow user A, user B cannot make user A follow user B.

So ... we're going to have to do something like the following:

  1. When user A sends an invite link to user B, an invite id is generated and embedded into the link (ie. id-foo) ie. The payload will be something like https://dynlink.tinyrobot.com/redeem-invite/id-foo. The invite id (along with the ids of both users) is also stored at the server.

  2. Then, when user B (installs and registers and) logs into the app, the app will invoke some new ('redeem'?) API with id-foo.

  3. The server looks up the invite id-foo and bidirectionally friends the two users.

Or something to that effect. Since user B doesn't exist yet, we need to store, and track, some sort of token or id somewhere.

aksonov commented 5 years ago

@bengtan Could you create needed tickets? I guess we need to implement deep links first. Could you clarify how many dynamic links do we need? One for mutual friend request, one for bot invite? Or it should be just one dynamic link?

aksonov commented 5 years ago

Am I correct that we need to use dynamic link within our "Invite Friends" CTA?

aksonov commented 5 years ago

Here is our use-case described https://firebase.google.com/docs/dynamic-links/use-cases/user-to-user

bengtan commented 5 years ago

Could you create needed tickets? ...

I figured we could talk with @thescurry at your regular after-all-hands meeting.

But yes, after talking and clarifying sufficiently, I can create the tickets.

I've already started the back-end discussion: hippware/wocky#1889

aksonov commented 5 years ago

For future reference, react native docs: https://github.com/invertase/react-native-firebase-docs/blob/master/docs/links/reference/links.md

aksonov commented 5 years ago

As I understand from dynamic links docs, we must set universal links first (not custom schema URLs like we are doing now): https://developer.apple.com/documentation/uikit/core_app/allowing_apps_and_websites_to_link_to_your_content

It requires some changes to be done for our web site. Probably it worth separate ticket for both rn-chat and web site

southerneer commented 5 years ago

After I get out the Staging deploy today I'll get together with Steve to work out which tickets we need.

southerneer commented 5 years ago

Adding ticket stubs now:

southerneer commented 5 years ago

This will be a handy tool for validating the website piece: https://branch.io/resources/aasa-validator/

southerneer commented 5 years ago

Tentative plan for a v1 (path of least resistance) flow:

  1. User taps the current "Invite Friends" CTA. screen shot 2018-09-27 at 4 49 23 pm

  2. A native iOS share dialog pops up and the user chooses their preferred method of sending out the invite.

    screen shot 2018-09-27 at 4 41 17 pm
  3. The messaging app opens with a pre-generated message including the dynamic link (complete with unique id from wocky)

  4. Invitees (potentially multiple) can tap on the link and once they eventually open the app, create an account, and sign in we call up to wocky with the unique ID to establish the bi-directional friendship.

southerneer commented 5 years ago

@aksonov we need to write logic to store off the dynamic link ID (for the invited user) for the following scenario:

Basically we need to make sure that we have the id to make the "accept invite" call to the backend once the user does eventually sign up and login.

bengtan commented 5 years ago

The list of To-Do's is growing. I'm going to convert this ticket into an Epic so it's easier to track tickets which are spun out.

bengtan commented 5 years ago

Invitees (potentially multiple)

I had assumed the invite code would only be used once, although I didn't say this out.

Allowing for multiple uses, or multiple users, could lead to abuse unless we put in some safeguards.

The naive way to allow for multiple invitees is to have an invite code that doesn't expire so it can be reused.

However, it would allow for:

  1. User A sends an invite code to User B.
  2. User B uses the invite code to make User A bidirectionally friend User B.
  3. User A discovers User B is a troll and unfollows User B.
  4. User B re-uses the same invite code to make User A bidirectionally friend User B.

Repeat steps 3 and 4.

And so, then, we have to think of ways to safeguard against this ... or else we just don't allow multiple uses in the first place.

bengtan commented 5 years ago

we must set universal links first

Universal links is a problem ... in that, in order to support it, we have to decide, ahead of time, how the webapp version of tinyrobot has it's URL structure.

It's not feasible for us to devise a URL structure for the entire app. We'll just have to create one just for the one use case, and hope it's flexible enough to accommodate a full URL hierarchy in the future.

Also, I'm going to spin out a ticket to implement support for Apple's Universal Links.

bengtan commented 5 years ago

It requires some changes to be done for our web site.

Crap.

Not the tinyrobot.com website, but for the webapp version of the app. Which currently doesn't exist.

Okay, we don't have to create a full webapp version of the app. We can just a mostly empty webapp and only implement one URL 'subdirectory' https://app.tinyrobot.com/invite/redeem/user/... but it's still work that needs to be done.

bengtan commented 5 years ago

@aksonov: Can you see if there's a way to support/receive universal links without requiring a separate web(app) version? I'm not optimistic about it, but worth looking.

aksonov commented 5 years ago

I will investigate

28 сент. 2018 г., в 9:17, Beng Tan notifications@github.com написал(а):

@aksonov https://github.com/aksonov: Can you see if there's a way to support/receive universal links without requiring a separate web(app) version? I'm not optimistic about it, but worth looking.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/hippware/rn-chat/issues/2817#issuecomment-425345166, or mute the thread https://github.com/notifications/unsubscribe-auth/ABQpcXS3m1DGDezw512cUlYZOc_vw2RIks5ufc0igaJpZM4WxbHU.

southerneer commented 5 years ago

Universal links is a problem ... in that, in order to support it, we have to decide, ahead of time, how the webapp version of tinyrobot has it's URL structure.

For v1 we should just set the fallback website for all dynamic links to tinyrobot.com. Done. We can fine tune it for v2+.

Allowing for multiple uses, or multiple users, could lead to abuse unless we put in some safeguards.

True, but I think we target v2 for the safeguards.

thescurry commented 5 years ago

Yes, let's please just use tinyrobot.com as the fallback... v1 should be as lean as possible. I am ok with reusable links for now, the audience is small and manageable. In an effort to save time/cycles, let's not engineer for problems we don't yet have.

southerneer commented 5 years ago

@bengtan I agree that a re-usable code isn't ideal, but unless we want to tack on weeks to our timeline I don't see any way around it.

The problem is that we don't have access to any contact information for people that don't already have an account on the app. We don't have a way to pre-populate a SMS, email, Tweet, etc to a specific contact on a user's device without that information. Inviters won't be selecting invitees from a list of their devices's contacts. They're just tapping a button, selecting a message vector, and getting a pre-populated message (which they can edit to their heart's content) to send out as they please. On the front-end we can add messaging to gently steer users to send links to individuals rather than groups, but that's about it.

We could always enforce links as single-use or set an expiration date on the server side, but I think the cost (losing new friend relationships on the app leading to greater drop-off) would far outweigh the benefits (prevent abuse by re-using the same link). The abuse angle is something to factor in for the long-term, but it seems like a tiny edge case that we should deal with on a case-by-case basis for v1 and account for in a more structured way in v2.

bengtan commented 5 years ago

I agree that a re-usable code isn't ideal,

As long as we are aware of this (and we are aware, now), then, okay.

aksonov commented 5 years ago

@bengtan No need to setup web app/pages for dynamic linking. Google provides everything we need automatically (with info/URLs we set for dynamic links, like fallback URL)

toland commented 5 years ago
  1. User A sends an invite code to User B.
  2. User B uses the invite code to make User A bidirectionally friend User B.
  3. User A discovers User B is a troll and unfollows User B.
  4. User B re-uses the same invite code to make User A bidirectionally friend User B.

An easy short-term fix for this is to disallow using the invite code when a user has blocked another. In this case, if User A blocks User B in step 3, then step 4 can't happen. And, it seems to me, the behavior of disallowing invite links when there is a block relationship is sort of the obvious default thing to do, anyway.

southerneer commented 5 years ago

Better yet, we only ever use the codes for new user sign-ups. In other words, if an existing user opens the app via the dynamic link then we (front-end code) just ignore the id/code payload, never send it to the back-end, and the bad actor stays unfollowed/blocked.

toland commented 5 years ago

That works, too. As long as it meets the business requirements.

thescurry commented 5 years ago

either of those options would work for now. It might be beneficial to allow existing users to become bi-directional friends... in the event where you don't think they are on the app, but still want to invite them and friend up. Because of this, I give Phil's suggestion a bit more of a 👍 than Erics.

My 2 cents.

toland commented 5 years ago

I think that it is appropriate not to allow invite codes to friend users who have blocked each other. I will be adding code to check blocking regardless of what other external precautions we wish to take.

southerneer commented 5 years ago

Both good points...plus it makes the front-end code simpler 😎.

bengtan commented 5 years ago

Summarising recent comments (this ticket and sub-tickets):

I think we're agreed (from this ticket):

and (from hippware/wocky#1889):


Furthermore, cross-posting https://github.com/hippware/wocky/issues/1889#issuecomment-426104003

if a user tries to "redeem" an expired code are we cool with it failing silently (i.e. no bi-directional friend created)?

Just throwing out an idea ...

I think the app should show the account profile of the 'invite-origin' (for lack of a better term) account (if not blocked). Then the user can decide there-and-then whether to follow or not.

It's just an idea, and probably needs more (conceptual) development.

(Maybe this is already designed into the flow, I dunno. If so, please ignore.)

bengtan commented 5 years ago

@thescurry (and anyone else who's interested):

Here's some info about dynamic links, and an example (now that we have them working):

  1. Firebase dynamic links console

Firstly, all the minified dynamic links are listed at

https://console.firebase.google.com/u/0/project/my-project-1480497595993/durablelinks

(If you're logged into multiple google accounts on your browser, replace the u/0 in the url with u/1 for the second google account, u/2 for the next one etc.)

Unminified links aren't listed here (but I don't think we'll be using unminified links).

  1. Example link

There is an existing link we can use as an example. The minified link is:

https://tinyrobot.page.link/hKWM

The unminified link is:

https://tinyrobot.page.link/?link=https://tinyrobot.com&isi=1198202376&ibi=com.hippware.ios.ChatStaging&ius=tinyrobotStaging&ifl=https://tinyrobot.com

See https://firebase.google.com/docs/dynamic-links/create-manually for documentation on all the parameters of the link.

  1. Debug and flowchart

If we append &d=1 to the end of an unminified link, we can get a flowchart of the detection logic:

https://tinyrobot.page.link/?link=https://tinyrobot.com&isi=1198202376&ibi=com.hippware.ios.ChatStaging&ius=tinyrobotStaging&ifl=https://tinyrobot.com&d=1

screenshot from 2018-10-02 11-42-00

Notice in this flowchart, the iOS detection logic is quite deep whereas the Android logic is quite shallow. That's because no Android-specific parameters are specified in the link. If they were specified, the Android detection logic would probably be just as complicated as for iOS.

The same probably also applies for the (shallow?) desktop detection logic.

thescurry commented 5 years ago

@bengtan thanks for that summary and the information. 👍

bengtan commented 5 years ago

This Epic can be closed and its sub-tickets individually tracked instead.