Skip to main content

Oops, you aren’t meant to see this screen — React Navigation: Deep linking Authorization

React Nav

By Eric Chang and Ethan Wan

At Chime, we believe everyone deserves financial peace of mind.

Opportunity

To enable financial peace of mind, Chime offers a suite of products, including the Chime Credit Builder Secured Visa® Credit Card*, Pay Anyone**, and other products. Credit Builder is a popular product that allows our customers — what we call our members — to safely build their credit history with no annual fees. But not all of our members have signed up for Credit Builder.

And yet, many of our members can end up on a Credit Builder-specific screen thanks to deep links.

Deep links are links that send members directly to specific parts of the app, and there are currently hundreds of them within Chime’s application — they act as a kind of shortcut for members.

But deep links can take members to places they shouldn’t go. For example, for a Chime member who hasn’t yet activated our Credit Builder product, we don’t want them to access deep links that direct to Credit Builder-specific screens, to avoid a bad user experience.

That’s where deep link authorization comes in. Without the barrier of deep link authorization, users may access screens that are not meant for them, which can render an empty or error state and create confusion. But with deep link authorization, members can’t access data that isn’t intended for them. Deep link authorization optimizes the user experience by limiting it to relevant content and data for each user.

Zooming out, this turns out to be a generic problem that mobile engineers encounter often. Say there are 2 sets of users — User Type A (Regular) and User Type B (Limited). Each of the user types should only be able to see the screens that correspond to a subset of the deep links available. The challenge lies in making sure the deep links have the right authorizations for different types of users.

This is how we thought about solving this and implemented a solution for Chime’s members.

Solution

At Chime, we use React Native as one of our core mobile technologies. In React Native mobile app navigation design, it’s common to have navigation stacks. Basically, we can make sure that we use different navigation stacks for different types of users so they don’t interfere with each other. We can then add a screen wrapper layer and a permit list in said wrapper layer to ensure that users only see the authorized screens.

Step 1: Have a list of deep links and create a permit list

const DEEP_LINKS = {
DEEP_LINK_1: 'app://deeplink1',
DEEP_LINK_2: 'app://deeplink2',
DEEP_LINK_3: 'app://deeplink3'

}
const USER_TYPE_LIMITED_PERMIT_LIST = [
DEEP_LINKS.DEEP_LINK_1,
DEEP_LINKS.DEEP_LINK_2
]

Step 2: Create an `isValidScreenForTypeLimitedUsers` method

const userTypeLimitedLinks: ReadonlySet<string> = new Set(
USER_TYPE_LIMITED_PERMIT_LIST
);
export function isValidScreenForTypeLimitedUsers(
screenLink: string,
) {
return userTypeLimitedLinks.has(screenLink);
}

Step 3: Use the `isValidScreenForTypeLimitedUsers` function in the ScreenWrapper

class UserTypeRegularScreenWrapper<Props> {
render() {
const { accessAuthorized } = this.props;

if (!accessAuthorized(screenLink)) {
navigateToHome(navigator);
return null;
}

}
}
class UserTypeLimitedScreenWrapper extends Component<Props> {
render() {
const { children, …props } = this.props;

const accessAuthorized = (screenLink) => {
return isUserTypeLimited &&
!isValidScreenForTypeLimitedUsers(screenLink)
}

return (
<UserTypeRegularScreenWrapper {…props} accessAuthorized={accessAuthorized}>
{children}
</UserTypeRegularScreenWrapper>
);
}
}

Step 4: Use the ScreenWrapper

Where we create navigation stacks, we can then use the `ScreenWrapper`

const createStacks = (stackName: string, userType: string) => {
const getScreenWrapper = (userType: string) => {
switch(userType) {
case TYPE_REGULAR:
return UserTypeRegularScreenWrapper;
case TYPE_LIMITED:
return UserTypeLimitedScreenWrapper;
default:
return UserTypeRegularScreenWrapper;
}
}

const Stack = () => {
return (
<Screen
screenWrapper={getScreenWrapper(userType)}
/>
)
}

returnStack
}

This achieves the goal of controlling deep link authorization.

One of the challenges we faced during this implementation was cross-functional communication and alignment. Since we were dealing with a fundamental part of Chime’s mobile navigation, we had to ensure we didn’t affect existing user flows. At Chime, we have a weekly mobile guild meeting where mobile engineers give feedback on proposals that can impact the whole app. We presented in the mobile guild meeting for review. It was a great opportunity to discover our blindspots and gain more professional experience in thinking holistically about our work. We addressed the feedback from peers to make sure the implementation was robust.

Conclusion

By the end of the implementation, we were able to successfully limit the screens that users can see when they navigate using deep links — Chime members now only see the screens they’re authorized to see. If a user accidentally clicks on an unauthorized link, we’ll gracefully bring them back to the home screen.

React Native is a great open-source framework for building mobile apps. We’re glad that we can give back to the community as we have discovered this can be a more generic problem when an app is growing and serving different types of users. This lets us maintain a great user experience while building new features for different types of members.

Shoutouts

  • Daniel Lin, Miron Pawlik and Arthur Lee for the excellent feedback and code review
  • Jen Wibowo for the user experience guidance
  • My amazing colleagues (Sam Milechman, Alexander Boldov, Michael Halvorson, Rahul Gupta) who helped me edit this post

*To apply for Credit Builder, you must have received a single qualifying direct deposit of $200 or more to your Checking Account. The qualifying direct deposit must be from your employer, payroll provider, gig economy payer, or benefits payer by Automated Clearing House (ACH) deposit OR Original Credit Transaction (OCT). Bank ACH transfers, Pay Anyone transfers, verification or trial deposits from financial institutions, peer to peer transfers from services such as PayPal, Cash App, or Venmo, mobile check deposits, cash loads or deposits, one-time direct deposits, such as tax refunds and other similar transactions, and any deposit to which Chime deems to not be a qualifying direct deposit are not qualifying direct deposits.

**Sometimes instant transfers can be delayed. The recipient must use a valid debit card to claim funds. See your issuing bank’s Deposit Account Agreement for full Pay Anyone Transfers details.