В этом руководстве будет представлен пример кода и общее объяснение того, как создать интеграцию OIDC с нуля. У вас должен быть установлен Node.js 10 или более поздней версии в вашей локальной среде, и вы должны иметь элементарные знания о современном Javascript. В этом руководстве будет использоваться password.js со стратегией oauth2, а также экспресс для облегчения интеграции.

Шаг 1 — Получите ваши клиентские ключи

Для обработки ваших запросов на аутентификацию вам необходимо создать набор учетных данных, чтобы определить, в каком приложении пользователь пытается пройти аутентификацию. Эти учетные данные обозначены как ваши APPID и ваши APPSECRET.

Для получения учетных данных необходимо выполнить следующие шаги:

Создайте новую учетную запись администратора

Ваша панель инструментов должна выглядеть примерно так.

Создать учетные данные

В полученную форму необходимо ввести следующую информацию:

  • Имя приложения
  • URI обратного вызова

Обратите внимание, что в этом руководстве мы будем использовать http://localhost:9876/callback для обратного вызова; ваше собственное пользовательское приложение может использовать другой URI.

Из соображений безопасности, если CallbackURL неверен, ваши вызовы API не будут выполняться.

После того, как вы создадите новую интеграцию, вам будет предоставлено следующее на панели инструментов:

  • Идентификатор приложения используется для идентификации вашего приложения.
  • APP SECRET используется для проверки утверждений

Скопируйте и запишите APP ID и APP SECRET, потому что они не будут отображаться позже. Эти значения понадобятся вам для создания демонстрационного приложения.

Шаг 2 — Настройка Node-Express

Зависимости и среда

Откройте терминал/командную строку в выбранной вами папке и инициализируйте npm.

npm init

Следующим, что вы хотели бы добавить в эту папку, будет файл .env. Этот файл будет содержать информацию, которая не должна передаваться в систему управления версиями и может быть изменена в зависимости от среды. Вы хотели бы заполнить его следующей информацией.

LOGIN_URI=https://oauth2.usw1.loginid.io #replace usw1 with another region if you are not in north america
LOGIN_REDIRECT_URI=http://localhost:9876/callback
LOGIN_SCOPES=openid
LOGIN_APPID=<your app ID>
LOGIN_APPSECRET=<your app Secret>
PORT=9876 #important, port number must match the port in callbackURI above

Базовое экспресс-приложение

В этом разделе описывается, как настроить базовое экспресс-приложение. Если вы уже знаете, как это сделать, перейдите к шагу 3 — Интеграция OIDC.

Давайте установим необходимые нам зависимости с помощью следующей команды:

npm i base64url express express-session passport passport-oauth2 dotenv cookie-parser connect-ensure-login

Давайте теперь настроим базовый код для базового веб-сервера. Давайте создадим наш основной файл и назовем его app.js

touch app.js

Давайте импортируем все наши библиотеки и создадим экспресс-сервер в app.js

require("dotenv").config();
const base64url = require("base64url");
const express = require("express");
const session = require("express-session");
const cookie = require("cookie-parser");
const passport = require("passport");
const OAuth2Strategy = require("passport-oauth2");
const { ensureLoggedOut, ensureLoggedIn } = require("connect-ensure-login");
const app = express();
const port = process.env.PORT || 9876;
app.listen(port, () => {
console.log(`listening on port ${port}`);
});

Затем добавьте несколько маршрутов к этому серверу:

app.get("/", (req, res) => {
res.send("Homepage<br/><a href='/login'>Login</a>");
});
app.get("/login", (req, res) => {
res.send("login");
});
app.get("/callback", (req, res) => {
res.send("callback uri");
});
app.get("/dashboard", (req, res) => {
res.send("dashboard <br><a href='/logout'>logout</a>");
});
app.get("/logout", (req, res) => {
res.send("logout");
});

Чтобы запустить это, мы будем использовать nodemon для отслеживания изменений.

npm i --save-dev nodemon

Затем добавьте следующую строку в объект «scripts» вашего package.json

"start": "nodemon app.js"

Затем вы можете ввести npm run start в своей консоли и посетить 5 маршрутов, которые мы только что создали.

http://localhost:9876/
http://localhost:9876/login
http://localhost:9876/callback
http://localhost:9876/dashboard
http://localhost:9876/logout

Теперь, когда все работы по настройке завершены, мы готовы начать интеграцию.

Шаг 3 — Интеграция OIDC

Настройка промежуточного ПО для аутентификации

Здесь мы будем использовать промежуточное ПО passport.js и connect-ensure-login, чтобы упростить управление сеансом входа в систему.

Давайте добавим их в наше экспресс-приложение:

app.use(cookie());
app.use(
session({
secret: "keyboard cat", // change the secret when in production
resave: false,
saveUninitialized: true
})
);
app.use(passport.initialize());
app.use(passport.session());
passport.use(new OAuth2Strategy(options, verify)); // important line
passport.serializeUser((user, done) => {
// note that the user param is whatever you passed into the done() function
// in the verify function you defined earlier
done(null, user);
});
passport.deserializeUser((user, done) => {
// the user param here is what you have stored in the session
done(null, user);
});

Для стратегии аутентификации мы будем использовать OAuth2Strategy.

В соответствии с документацией для Oauth2Strategy нам потребуется настроить объект, содержащий параметры конфигурации, а также функцию, которая проверяет аутентификацию, как показано в следующем фрагменте кода:

const options = {
clientID: process.env.LOGIN_APPID,
clientSecret: process.env.LOGIN_APPSECRET,
callbackURL: process.env.LOGIN_REDIRECT_URI,
authorizationURL: `${process.env.LOGIN_URI}/oauth2/auth`,
tokenURL: `${process.env.LOGIN_URI}/oauth2/token`,
scope: process.env.LOGIN_SCOPES,
state: base64url(JSON.stringify({ state: process.env.LOGIN_APPID })),
passReqToCallback: true // this is important, so you can obtain the bearer token in the verify() function
};
const verify = (req, accessToken, refreshToken, params, profile, done) => {
console.log(`Access token is:  ${accessToken}`);
console.log(`Refresh token is: ${refreshToken}`);
console.log("Params: ", params["token_type"], params["id_token"]);
console.log("Profile:", profile);
// note due to the way passport works, profile would always be {} unless
// you override the default strategy.userProfile function (see below)
if (profile) {
// TODO; do something here validate the token's signature.
const user = profile;
return done(null, user);
}
return done(null, false);
};

Авторизоваться

Мы создали 5 маршрутов на шаге 2. Давайте внесем некоторые изменения в маршрут входа и маршрут обратного вызова, чтобы мы могли фактически войти в систему.

Замените маршрут входа следующим:

app.get("/login", passport.authenticate("oauth2"));

и замените маршрут обратного вызова следующим:

app.get(
"/callback",
passport.authenticate("oauth2", {
session: true,
successReturnToOrRedirect: "/dashboard"
})
);

Теперь, когда вы посещаете /login, вы должны быть перенаправлены на LoginID для аутентификации, и в случае успеха будут отправлены на /callback и, наконец, на /dashboard в случае успеха.

В этой демонстрации вы могли видеть токен доступа и токен носителя в консоли.

LoginID не предоставляет токен обновления, ваше приложение отвечает за управление сеансами для ваших пользователей.

Выйти

Конечно, пользователь также должен иметь возможность выйти из системы. замените маршрут выхода следующим:

app.get("/logout", (req, res) => {
req.logout();
res.redirect("/");
// alternatively, you could do the following
// req.session.destroy(() => res.redirect('/'));
});

Защита маршрутов

В настоящее время доступ к панели управления и маршрутам выхода из системы возможен без входа в систему, а маршрут входа может быть доступен при входе в систему, мы этого не хотим, именно здесь мы будем использовать connect-ensure-login для обеспечения управления сеансами. (вы можете написать свой собственный, если хотите).

Наша конечная точка входа теперь будет выглядеть примерно так:

app.get(
"/login",
ensureLoggedOut("/dashboard"),
passport.authenticate("oauth2")
);

ensureLoggedOut перенаправит маршрут /login на /dashboard, если пользователь вошел в систему, нет смысла входить в систему, если вы уже вошли в систему.

То же самое касается /dashboard:

app.get("/dashboard", ensureLoggedIn("/login"), (req, res) => {
res.send("dashboard <br><a href='/logout'>logout</a>");
});

ensureLoggedIn перенаправит пользователя на /login, если он нажмет /dashboard без аутентификации

Как насчет регистрации?

LoginID OIDC сделает это за вас.

Шаг 4 — Получение профиля пользователя

До этого момента, если вы заглядывали в console.log в терминале, вы замечали, что профиль — это пустая строка. Это связано с тем, что стратегия oauth2 в паспорте на самом деле не предоставляет стандартную функцию userProfile. Так что нам нужно будет сделать один самостоятельно.

Найдите следующую строку:

passport.use(new OAuth2Strategy(options, verify)); // important line

и замените его следующим:

const strategy = new OAuth2Strategy(options, verify);
strategy.userProfile = function (accessToken, done) {
this._oauth2._request(
"GET",
`${process.env.LOGIN_URI}/userinfo`,
null,
null,
accessToken,
(err, data) => {
if (err) {
return done(err);
}
try {
data = JSON.parse(data);
} catch (e) {
return done(e);
}
done(null, data);
}
);
};
passport.use(strategy);

Обратите внимание, что мы здесь сделали. Мы добавили функцию userProfile в стратегию, и в этой функции мы вызываем маршрут loginid userinfo и используем токен доступа для получения профиля пользователя. Теперь снова войдите в систему, и ваша консоль должна зарегистрировать профиль, подобный следующему.

Profile: { sid: 'b6230b39-b1e8-42c6-8379-df60050b9a19', sub: '[email protected]' }

Затем вы можете использовать эту информацию для надлежащего обслуживания контента.

Живая демонстрация

Нажмите на эту ссылку, если хотите увидеть его вживую: https://codesandbox.io/s/brave-meadow-1swdt?from-embed

Получать помощь

Мы будем рады помочь, если у вас есть какие-либо вопросы, пожалуйста, не стесняйтесь обращаться к [email protected].

О логине

LoginID — это комплексное решение для многофакторной аутентификации на основе FIDO, которое обеспечивает беспрепятственную аутентификацию. Созданный для разработчиков и предприятий, LoginID сертифицирован FIDO и соответствует принципам PSD2. Решение для многофакторной аутентификации LoginID, время внедрения которого составляет всего один час, представляет собой быстрый, простой в интеграции, экономичный и нормативный инструмент, обеспечивающий уверенность в безопасности вашего бизнеса и позволяющий вам сосредоточиться на развитии своего бизнеса.

Начните бесплатно здесь.