We’re building Gusto Embedded as a set of APIs and prebuilt components to be customized by our partners, so they can deliver the best payroll experience for their customers. But not everything is one-size-fits all: sometimes our partners need us to customize the product experience to meet their needs.
Every partner is different, and requirements vary. Generally, we aim to prioritize the projects on our roadmap that will have the greatest impact for the largest number of partners and employers.
First, we start by understanding our partners’ needs. One partner, for example, requested that we limit the Gusto-hosted interfaces an employer or employee can access, restricting them from logging into Gusto.com. This helps our partner strengthen their brand as a payroll leader and reduces potential confusion for their customers.
Understanding the Challenge
This seemed like a straightforward enough request, but with it came a lot of nuances that we had to explore in depth. And while the request came initially from one partner, we acknowledged the benefits this feature could have for all partners that choose to enable it – and, indeed, had heard from other partners that this was also on their roadmaps. It was time to start scoping.
Here’s where things got tricky: our existing infrastructure didn’t account for embedded partner access at the login level. We had to figure out a way to determine which partner and which user roles should be blocked from accessing certain resources at both the login level and the in-app level.
Identifying the Problems
Before diving into solutions, we had to understand the core problems:
- Role-Based Blocking: Partners wanted to restrict access for certain roles. For instance, employees and payroll admins should be blocked from accessing some Gusto resources, but contractors and accountants should still be able to access them. This required a role-specific control mechanism.
- Multi-Role Complexity: In our system, a user might hold multiple roles across different companies under one user account. For example, someone could be an employee at one company and a contractor at another. There could be a mix and match of blocked companies, partners, and user roles per user we had to consider.
- Account Switching: In our Gusto app, we allow a user to switch between their user role accounts, so even if a user’s role was blocked, they might still have access via a different role. In such cases, we had to allow the user to login, but prevent them from switching to the restricted account. We worked a lot with our Security teams and GraphQL teams to make sure our changes were valid.
- Third-party Logins: There are many ways to login to Gusto besides the traditional email/password login, including Google OAuth, Intuit login, etc. that we had to consider when blocking a user login.
Simplified workflow of determining whether a user should be blocked when logging into Gusto
Building the Solution
About a year ago, when we planned this project, we decided to roll it out in phases to better meet customer needs. In the first phase, we focused on partners with net-new embedded customers—those who hadn’t used Gusto before—because they made up the bulk of our customer base. This approach let us get an MVP out the door quickly and start testing things right away. In the second phase, we tackled more complex cases, like partners with embedded companies that used to be Gusto customers. By breaking it up like this, we could deliver faster and fine-tune as we went along.
To address these challenges we started by working on these steps:
-
- Configuring Partner Settings: Through this new configuration only available internally, our CX (customer experience) team members could enable or disable this feature for partners. This flexibility allowed partners to choose whether to use Gusto directly for certain features or keep their customers within their own app.
- Adding a new Blocked Company Model: We introduced a new model to manage partner-specific login controls. This model enabled us to configure whether a company under an embedded partner had blocking enabled, and is maintained by Sidekiq jobs that would run whenever the partner was modified.
- Role-Specific Blocking Logic: We keep a list of roles that are explicitly blocked, and we use this to decide whether a user’s role should prevent them from accessing certain resources on Gusto. For instance, if the employee role is restricted, the system will block them from logging in, but still allow access if they’re logged in as a contractor. We also had to build in extra logic to handle situations where an employee had been a Gusto customer in the past, ensuring their account was managed properly.
- Handling Account Switching: When a user with multiple roles logged in, we ensured they could still access non-restricted accounts. However, if one of their roles was blocked, they couldn’t switch to that account once logged in. We needed to ensure that the default login did not automatically select a blocked company.
- Handling Login blocking: We added the block check at the main login entry point and third party login entry points, making sure to raise a generic login error due to security guidance.
Performance and Security
For this project, since we were working with logins—the most frequently accessed part of Gusto—it was crucial to keep everything fast and secure. Gusto developed a slow query checker that engineers could use to debug performance issues. This tool was especially useful when adding block checks across various key parts of the codebase, ensuring everything performed as smoothly as possible.
On the security side, we had to be careful not to introduce any vulnerabilities with this project. Following advice from our Security team, we avoided showing a specific “blocked” error message. Instead, if a user was blocked, we’d show a generic error message that didn’t unintentionally reveal any details about the partner or end customer.
Conclusion
This access project was a complex, multi-faceted solution to a problem that impacted both Gusto and our partners. We collaborated with a multitude of teams across Gusto, including Identity, Security, PeopleOS, and the GraphQL teams. By focusing on flexibility and control, we enabled partners to create the experience they wanted for their customers, while still leveraging Gusto’s powerful backend capabilities. This experience reinforced the importance of clear documentation, early planning, and a deep understanding of customer needs.
For our partners, this new feature unlocks a new level of customization. It allows them to decide when they’d like to lean on existing Gusto functionality, and when they’d like to build out more nuanced features themselves – a major benefit of working with a company like Gusto that’s been building and handling payroll for over 12 years.