如何使用 nodejs 和 okta 进行应用注销
How to do an app logout using nodejs and okta
我目前正在使用 Okta 与 OIDC 和 Node Express 来登录我制作的 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';
经过详尽的搜索,我认为这是不可能的。我最终做了 req.logout()
,然后重定向到一个页面,上面写着“您已退出应用程序,但可能仍登录到您的单点登录提供商。”
我目前正在使用 Okta 与 OIDC 和 Node Express 来登录我制作的 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';
经过详尽的搜索,我认为这是不可能的。我最终做了 req.logout()
,然后重定向到一个页面,上面写着“您已退出应用程序,但可能仍登录到您的单点登录提供商。”