I'm building a login system using OAuth
to integrate with various social networks.
The flow is very simple, first, the user is redirected to their social network to grant permission to read the necessary information, and after that my application has access to the following user information:
auth_id, auth_provider, email, name, picture
example with Facebook:
auth_id = fb-12345,
auth_provider = facebook,
email = [email protected],
name = john donate,
picture = http://site.com/profile.jpeg
this is the current Login UseCase:
export default class Login {
private userRepositoryInterface: UserRepositoryInterface
private tokenGeneratorAdapter: TokenGeneratorAdapterInterface
private clockAdapterInterface: ClockAdapterInterface
constructor(
userRepositoryInterface: UserRepositoryInterface,
tokenGeneratorAdapter: TokenGeneratorAdapter,
clockAdapterInterface: ClockAdapterInterface
) {
this.userRepositoryInterface = userRepositoryInterface;
this.tokenGeneratorAdapter = tokenGeneratorAdapter;
this.clockAdapterInterface = clockAdapterInterface
}
public async login(loginInput: LoginInput): Promise<LoginOutput> {
let user: User;
user = await this.userRepositoryInterface.findByAuthProviderAndAuthProviderId(loginInput.authProvider, loginInput.authProviderId);
if (user === null) {
const userId = await this.userRepositoryInterface.nextIdentity();
user = new User({
id: userId,
name: loginInput.name,
authProvider: loginInput.authProvider,
authProviderId: loginInput.authProviderId,
email: loginInput.email,
profilePicture: loginInput.profilePicture,
createdAt: this.clockAdapterInterface.now()
});
await this.userRepositoryInterface.create(user)
}
const authenticationToken = await this.tokenGeneratorAdapter.generate({
id: user.id,
name: user.name
});
return new LoginOutput(authenticationToken);
}
}
The problems:
The problem with the current approach is that the Login UseCase has two responsibilities, the first one is to check if the user exists in the database (which would be the login itself), and the second is to create the user if it doesn't exist (sign up), and this is due to the way the OAuth
flow works, as there is no failure scenario, whenever the user logs in to their social network, I will have access to the necessary information to either login or sign-up.
and the third problem is that the Login input DTO
has many parameters that will not always be used depending on the scenario of login or sign-up, for example:
If the user exists in the database and the login is successful, the name, email, and profile picture data won't be used, but they always need to be present in the Use Case.
none of this seems OK to me, Do you know a proper way to handle this use case?