60 lines
2.3 KiB
TypeScript
60 lines
2.3 KiB
TypeScript
import { AppError } from "../../../../helpers/error/instances/app";
|
|
import { googleProvider } from "../../providers/google.provider";
|
|
import { redis } from "../../../../utils/databases/redis/connection";
|
|
import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder";
|
|
import { UserHeaderInformation } from "../../../../helpers/http/userHeader/getUserHeaderInformation/types";
|
|
import { OAuthUserProvisionService } from "../internal/OAuthUserProvision.service";
|
|
import { GoogleCallbackUserData } from "../../auth.types";
|
|
|
|
export const googleCallbackService = async (
|
|
query: {
|
|
state: string;
|
|
code: string;
|
|
callbackURI?: string;
|
|
},
|
|
userHeaderInfo: UserHeaderInformation,
|
|
) => {
|
|
try {
|
|
// get code and state for validation from params and search for state in redis cache
|
|
const state = query.state;
|
|
const codeVerifier = await redis.get(`${process.env.APP_NAME}:pkce:${state}`);
|
|
|
|
// return error if the state for validation is not found in redis, and delete if found
|
|
if (!codeVerifier) throw new AppError(408, "Request timeout");
|
|
await redis.del(`${process.env.APP_NAME}:pkce:${state}`);
|
|
|
|
// create access token with the result of validating the authorization code that compares access code with validator state
|
|
const google = googleProvider(query.callbackURI);
|
|
const tokens = await google.validateAuthorizationCode(query.code, codeVerifier);
|
|
|
|
// get user data from Google using the access token that has been created.
|
|
const accessToken = tokens.accessToken();
|
|
const response = await fetch("https://openidconnect.googleapis.com/v1/userinfo", {
|
|
headers: {
|
|
Authorization: `Bearer ${accessToken}`,
|
|
},
|
|
});
|
|
|
|
// parse the user data response
|
|
const userData = (await response.json()) as GoogleCallbackUserData;
|
|
|
|
// Provision or authenticate the user in the system
|
|
return await OAuthUserProvisionService(
|
|
{
|
|
fullname: userData.name,
|
|
username: `gle_${userData.sub}`,
|
|
email: userData.email,
|
|
avatar: userData.picture,
|
|
oauthProvider: {
|
|
providerName: "google",
|
|
sub: userData.sub,
|
|
token: accessToken,
|
|
},
|
|
},
|
|
userHeaderInfo,
|
|
);
|
|
} catch (error) {
|
|
ErrorForwarder(error, 500, "Authentication service error");
|
|
}
|
|
};
|