In application user should be able to authorize using his twitch account, here is how business requirements looks like:
- for twitch authorization user should be redirected (by the backend application) to the twitch authentication page
- after logging in on twitch side:
_ if user was not found in our application - new user should be created and then logged in to our application
_ if user already existed - it should be logged in - then user should be redirected back to the frontend application
And here is how I've managed to do it:
// this class represents business logic
class TwitchAuthService {
// this method returns url and then controller redirects user to the appropriate page
public getRedirectionUrlToStartAuth = (
{ successUrl, failUrl }: { successUrl: string; failUrl: string; }
): string => {
return 'https://id.twitch.tv/oauth2/authorize?' +
new URLSearchParams({
response_type: 'code',
client_id: this.twitchId,
redirect_uri: this.getRedirectUrl(),
scope: 'user:read:email',
state: `successUrl=${successUrl}&failUrl=${failUrl}`,
})
}
// after receiving token from twitch, we
// - return already existing user or
// - create a new one and return it
authenticateUser() { ... }
}
And at the moment when I receive callback from twitch, I have to parse successUrl and failUrl parameters from twitch-url in response for further redirection (I've provided these parameters earlier while using getRedirectionUrlToStartAuth method)
I've created a separate method for this "parsing" functionality, getRedirectUrlsFromCallback but where should I locate it?
Is it still part of business logic? Or should I create some infrastructure service for Twitch and put this method here? Or it simply can be added as private method of the controller?
public getRedirectUrlsFromCallback = (state: string): { successUrl: string; failUrl: string } => {
const urlParams = new URLSearchParams(state);
const successUrl = urlParams.get('successUrl');
const failUrl = urlParams.get('failUrl');
if (!successUrl || !failUrl) {
throw new IncorrectCallbackUrlError();
}
return {
successUrl,
failUrl,
}
}