如何使用 nodejs 和 okta 进行应用程序注销
Posted
技术标签:
【中文标题】如何使用 nodejs 和 okta 进行应用程序注销【英文标题】:How to do an app logout using nodejs and okta 【发布时间】:2021-11-10 02:30:47 【问题描述】:我目前正在使用带有 OIDC 和 Node Express 的 Okta 来登录我制作的 Web 应用程序。我希望我的用户能够仅注销我的应用程序而不是 okta 本身,因为 okta 是为我的公司服务的,这将使他们从使用公司 okta 的所有其他网站中注销。 Okta 建议在他们的网站上这样做。
app.get('/local-logout', (req, res) =>
req.logout();
res.redirect('/');
);
(https://developer.okta.com/docs/guides/sign-users-out/nodeexpress/sign-out-of-your-app/)
我已经尝试过实现它,但它不起作用。我也尝试过使用 req.session.destroy、res.clearCookie("connect.sid")、req.session = null 以及这些有或没有回调的许多不同组合。每当我重定向时,它只会返回主页并且同一用户已登录。每当我尝试删除 connect.sid cookie 时,它都会删除,然后在用户被重定向时重新初始化。我不确定该怎么做。我删除了不相关端点的代码如下。
require('dotenv').config();
import 'zone.js/dist/zone-node';
import ngExpressEngine from '@nguniversal/express-engine';
import join from 'path';
import * as express from 'express';
import AppServerModule from './src/main.server';
import APP_BASE_HREF from '@angular/common';
import existsSync, read from 'fs';
// 30 minutes
const sessionMaxAge = 1800000;
import * as e from 'cors';
import resolveForwardRef from '@angular/core';
import User from '@okta/okta-sdk-nodejs';
const session = require('express-session');
const ExpressOIDC = require('@okta/oidc-middleware');
const cookieParser = require("cookie-parser");
/** Creates the OpenID Connect Middleware and configures it to work with Okta */
const oidc = new ExpressOIDC(
appBaseUrl: process.env.HOST_URL,
issuer: `$process.env.OKTA_ORG_URL/oauth2/default`,
client_id: process.env.OKTA_CLIENT_ID,
client_secret: process.env.OKTA_CLIENT_SECRET,
redirect_uri: process.env.REDIRECT_URL,
scope: 'openid profile',
routes:
loginCallback:
path: '/authorization-code/callback'
,
);
// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express
var root_folder: string = process.env.ROOT_FOLDER || "dist/angular-app/browser"
const server = express();
const distFolder = join(process.cwd(), root_folder);
const indexhtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
// Our Universal express-engine (found @ https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_angular_universal_tree_master_modules_express-2Dengine&d=DwIGAg&c=-35OiAkTchMrZOngvJPOeA&r=03NdPO1x-l0QAZ_R9TNGwA&m=WF5ia-YADjCituVWMV5vLoZ5wg7d_W1qhCYDTbJNGT0&s=WPOkeRsetPDQ6TrD26RKLo1m9_zxBfQXGhUUSkth0Ew&e= )
server.engine('html', ngExpressEngine(
bootstrap: AppServerModule,
));
server.set('view engine', 'html');
server.set('views', distFolder);
// Serve static files from /browser
server.get('*.*', express.static(distFolder,
maxAge: '1y'
));
// Configure Session Support
server.use( session(
secret: process.env.APP_SECRET,
resave: false,
saveUninitialized: false,
cookie: maxAge: sessionMaxAge
)
);
server.use(cookieParser());
server.use(oidc.router);
// Log the user out of the local session
server.get('/local-logout',(req:any, res:any) =>
req.logout();
res.redirect('/');
);
// All regular routes use the Universal engine
server.get('*', oidc.ensureAuthenticated( redirectTo: '/login' ), (req: any, res: any) =>
if(req.session && req.session.username != null)
console.log(process.env);
res.render(indexHtml, req, providers: [ provide: APP_BASE_HREF, useValue: req.baseUrl ] );
else
console.log("getting user info");
getUserInfo(req)
.then(userInfo =>
req.session.username = userInfo.username;
req.session.group = userInfo.group;
if (userInfo.group=="unauthorized")
res.sendFile('./403.html', root: ".")
else
console.log(process.env);
res.render(indexHtml, req, providers: [ provide: APP_BASE_HREF, useValue: req.baseUrl ] );
);
);
return server;
function run(): void
const port = process.env.PORT || 4000;
// Start up the Node server
const server = app();
server.listen(port, () =>
console.log(`Node Express server listening on https://urldefense.proofpoint.com/v2/url?u=http-3A__localhost-3A-24-257Bport-257D&d=DwIGAg&c=-35OiAkTchMrZOngvJPOeA&r=03NdPO1x-l0QAZ_R9TNGwA&m=WF5ia-YADjCituVWMV5vLoZ5wg7d_W1qhCYDTbJNGT0&s=PUb7XMS4uP9ICqUY28QgXNRxoWk6sGatPdmZMqmgbJs&e= `);
);
// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode'))
run();
export * from './src/main.server';
【问题讨论】:
【参考方案1】:经过详尽的搜索,我认为这是不可能的。我最终做了req.logout()
,然后重定向到一个页面,上面写着“您已退出应用程序,但仍可能登录到您的单点登录提供商。”
【讨论】:
以上是关于如何使用 nodejs 和 okta 进行应用程序注销的主要内容,如果未能解决你的问题,请参考以下文章
如何配置 Spring Security SAML 以与 Okta 一起使用?