Seperate logins on same email address

Published 2 years ago by rikw

Hi,

In my project I have separate frontend sections for different clients, but also one for backend. Now I'm looking for a solution to use the same email address for separate users for the different sections. How can I achieve something like that?

As example:

  • domain.tld
  • client1.domain.tld
  • client2.domain.tld
  • backend.domain.tld or domain.tld/backend

The users for client1 & client2 should also have addition fields compare to he user of the main domain.

I'm looking forward to your thoughts. I can't really get my head around it.

Best Answer (As Selected By rikw)
martinbean

@rikw Not necessarily. You could override the getCredentials() method from the AuthenticatesUsers trait in your AuthController to include the site_id:

public function getCredentials(Request $request)
{
    return array_merge($request->only($this->loginUsername(), 'password'), [
        'site_id' => config('site.id'), // or however you determine the current site ID
    ]);
}
jekinney
jekinney
2 years ago (213,695 XP)

With out understanding the big picture, I'm going to guess. You are way over complicating this.

I have yet, but like I said I don't know your specifics, ever needed a authentication system like that.

Generally a roles or roles and permissions with middleware solves the issue of allowing access to certain areas and features with out all the craziness you described.

Say only a user with permission to create a new user is needed. Simply secure the create and store user routes with a middleware that only allows a user with appropriate permissions to access. But the underlying code is the same as any other registration on most any site.

rikw
rikw
2 years ago (1,490 XP)

Thank you for thinking along. I'd like to keep it as simple as possible. Let me try to explain it a little.

Think of it as a SaaS platform on which users can register. But their account on client1.domain.tld isn't the same user as client2.domain.tld although their email address can be the same.

Our customer repairs devices and has an online platform to manage that proces. Customers can register their device for repair and create a login for that. Our customer wants to whitelabel the frontend part to other companies, but the devices need to go into the same platform to manage the repairs. A repair customer can have an account at multiple whitelabel without knowing it's actually the same platform.

I hope this clears up my situation...

martinbean

@rikw Group your users by site. Have a “site_id” column or similar in your table, and put a unique constraint on site_id and email so that a user can only sign up to one site with an email address once, but can use their email address to register on multiple sites. When logging in, check a user with the specified email and current site ID exists.

We do exactly this, where we have an “affinity partner” ID. The platform can be white-labelled and each instance would have their own affinity partner ID, so users who sign up on Partner Site A will need to re-register on Partner Site B.

rikw
rikw
2 years ago (1,490 XP)

Thanks @martinbean that sounds like a plan. That would mean a custom Guard for login/authentication am I right?

martinbean

@rikw Not necessarily. You could override the getCredentials() method from the AuthenticatesUsers trait in your AuthController to include the site_id:

public function getCredentials(Request $request)
{
    return array_merge($request->only($this->loginUsername(), 'password'), [
        'site_id' => config('site.id'), // or however you determine the current site ID
    ]);
}
Kemito
Kemito
2 years ago (41,650 XP)
  • Create sites table where you store information about site.
  • Add site_id under users table
  • Create middleware which will determine from which site user is comming and store it in session
  • Make a custom auth driver which takes site_id from session and validate it under place where you retrieve user

After that i suggest you to just create trait "BelongsToSite" which will have method bootBelongsToSite (boot{nameOfTrait}) and there apply global scope https://laravel.com/docs/5.2/eloquent#global-scopes which takes from session aswell. After that you have to just add this trait under any model which needs to be threat as "belonging to site" in this case "users"

https://gyazo.com/97030bd66088b35631416ae13243ccc7

Additionaly i listen to event and add site_id each time model is created (global scope don`t do that)

Hope that helps.

rikw
rikw
2 years ago (1,490 XP)

Hi @martinbean and @Kemito that helps a lot. With both I think I can manage my challenge. Maybe not the easiest one while starting Laravel.

Maybe one last tip I could use. At what point should I find the current (sub)domain? The whitelabels use their own domain the they 'send' to our platform. Like: sub1.domain-a.tld, sub2.domain-b.tld.

These kind of questions might show I'm struggling a bit with this structure in Laravel.

martinbean

@rikw I’d put that in your AppServiceProvider. Create a map of hostnames to site IDs, pick up the hostname from the request and set the site ID in the container so you application has access to it elsewhere:

public function boot()
{
    if (! $this->app->runningInConsole()) {
        $hostname = $this->app['request']->getHost();

        // Find site ID based on $hostname or throw 404, as accessing from invalid domain name

        $this->app->bind('site_id', $site->id);
    }
}
rikw
rikw
2 years ago (1,490 XP)

Sweet @martinbean, I can really work with this. Thanks for thinking with me and showing me a good solution.

Please sign in or create an account to participate in this conversation.