Я создаю API hapi (v18.4.0), который хочу аутентифицировать пользователей в службе Discord OAuth2. Я использую @hapi/bell(v11.1.0) для обработки рукопожатия OAuth2.
Я могу пройти аутентификацию через Discord, но не могу заставить @hapi/cookie(v10.1.2) взять на себя ответственность за аутентификацию. Я вижу, что файл cookie создается, но единственный раз, когда я вижу функцию cookie validateFunc, вызываемую с маршрутом «выход из системы». Я считаю, что установил все необходимые флаги для разработки на локальном хосте.
По сути, я не могу заставить работать стратегию аутентификации cookie. И я удивлен, что не вижу вызываемой функции validateFunc, когда я перехожу к маршрутам, требующим аутентификации.
Ниже приведены настройки моей стратегии аутентификации, функция cookie validateFunc, маршруты входа/выхода из системы и тестовые маршруты.
Спасибо за помощь!
exports.plugin = {
name: 'auth',
dependencies: ['hapi-mongodb', 'bell', '@hapi/cookie'],
register: (server, options) => {
server.auth.strategy('session', 'cookie', {
cookie: {
name: 'sid-demo',
password: SECRET_KEY,
isSecure: false,
isSameSite: 'Lax'
},
redirectTo: '/demo-server/api/v1/auth/login', //If there is no session, redirect here
validateFunc: async (request, session) => {
console.log("validating cookie...");
const db = request.mongo.db;
const ObjectID = request.mongo.ObjectID;
try {
const user = await db.collection(usersTable).findOne({ _id: new ObjectID(session.id) });
if (!user) {
console.log("no user found, cookie invalid");
return { valid: false };
}
return { valid: true, credentials: user };
}
catch (err) {
console.log("Validation error:", err);
return { valid: false };
}
}
});
server.auth.strategy('discord', 'bell', {
provider: 'discord',
password: SECRET_KEY,
clientId: DISCORD_CLIENT_ID,
clientSecret: DISCORD_SECRET,
isSecure: false,
isSameSite: 'Lax'
});
}
};
exports.plugin = {
name: 'routes-auth',
dependencies: ['hapi-mongodb', 'auth'],
register: (server, options) => {
server.auth.default('session');
server.route({
method: ['GET', 'POST'],
path: '/demo-server/api/v1/auth/login',
options: {
auth: 'discord',
handler: async (request, h) => {
if (!request.auth.isAuthenticated) {
console.log("authenticaion failed");
return `Authentication failed due to: ${request.auth.error.message}`;
}
const db = request.mongo.db;
const credentials = request.auth.credentials;
const profile = request.auth.credentials.profile;
try {
const result = await db.collection(usersTable).findOne({ email: request.auth.credentials.profile.email });
if (result) {
console.log("user exists");
request.cookieAuth.set({
id: result.id,
username: profile.username,
token: credentials.token
});
return h.redirect('/demo-server/restricted');
}
}
catch (err) {
console.log(err);
return Boom.serverUnavailable('database error');
}
console.log("user does not exists, registering new user");
const user = {
email: request.auth.credentials.profile.email,
last_login: new Date(),
username: request.auth.credentials.profile.username,
};
try {
const result = await db.collection(usersTable).insertOne(user);
request.cookieAuth.set({
id: result.insertedId,
username: profile.username,
token: credentials.token
});
}
catch (err) {
return Boom.serverUnavailable('database error');
}
return h.redirect('/demo-server/restricted');
},
tags: ['auth', 'api']
}
});
server.route({
method: 'GET',
path: '/demo-server/api/v1/auth/logout',
options: {
handler: (request, h) => {
request.cookieAuth.clear();
return h.redirect('/demo-server');
}
}
});
exports.plugin = {
name: 'routes-default',
dependencies: ['auth'],
register: (server, options) => {
server.route({
method: 'GET',
path: '/demo-server',
handler: (request, h) => {
return h.response({ result: 'Welcome to demo-server!' }).code(200);
},
config: {
description: 'This is default route for the API.',
response: {
status: {}
},
tags: ['default','test']
}
});
server.route({
method: 'GET',
path: '/demo-server/restricted',
handler: (request, h) => {
return h.response({ message: 'Ok, You are authorized.' }).code(200);
},
config: {
auth: {
mode: 'try'
},
description: 'This is a default route used for testing the jwt authentication.',
response: {
status: {}
},
tags: ['default','test','auth']
}
});
}
};