Skip to content

Commit

Permalink
feat: verified oidc access token in jwt auth middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
er-santosh committed Mar 20, 2024
1 parent fbb7786 commit 1b7dfa5
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 66 deletions.
6 changes: 1 addition & 5 deletions packages/server/src/api/controllers/Oidc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,9 @@ export default class OidcController extends BaseController {
try {
const { token } = req;

const oidcIdToken = token.oidc_id_token;
const oidcAccessToken = token.oidc_access_token;

const logoutUrl = await this.oidcService.generateEndSessionUrl({
oidcIdToken,
oidcAccessToken,
});
const logoutUrl = await this.oidcService.generateEndSessionUrl(oidcAccessToken);

return res.status(200).send({ logoutUrl });
} catch (error) {
Expand Down
2 changes: 0 additions & 2 deletions packages/server/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ import { ImportController } from './controllers/Import/ImportController';
import { BankingController } from './controllers/Banking/BankingController';
import { Webhooks } from './controllers/Webhooks/Webhooks';
import OidcController from '@/api/controllers/Oidc'
import oidcSessionMiddleware from '@/api/middleware/oidcSession'

export default () => {
const app = Router();
Expand All @@ -85,7 +84,6 @@ export default () => {

dashboard.use(JWTAuth);
dashboard.use(AttachCurrentTenantUser);
dashboard.use(oidcSessionMiddleware);
dashboard.use(TenancyMiddleware);
dashboard.use(EnsureTenantIsInitialized);
dashboard.use(SettingsMiddleware);
Expand Down
33 changes: 31 additions & 2 deletions packages/server/src/api/middleware/jwtAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { Request, Response, NextFunction } from 'express';
import { Container } from 'typedi';
import jwt from 'jsonwebtoken';
import config from '@/config';
import { OidcService } from '@/services/Oidc';

const authMiddleware = (req: Request, res: Response, next: NextFunction) => {
const Repositories = Container.get('repositories');
const Logger = Container.get('logger');
const token = req.headers['x-access-token'] || req.query.token;

Expand All @@ -16,7 +18,34 @@ const authMiddleware = (req: Request, res: Response, next: NextFunction) => {
Logger.info('[auth_middleware] jwt verify success.');
next();
};
if (!token) { return onError(); }
if (!token) { return onError();}

const verifyOidcAccessToken = async () => {
try {
const oidcService = new OidcService();

const introspectResponse = await oidcService.introspectAccessToken(token);

if (!introspectResponse.active)
throw new Error(`Invalid access token: ${token}`);

const { systemUserRepository } = Repositories;

const email = introspectResponse.email;

const systemUser = await systemUserRepository.findOneByEmail(email);

const payload = {
id: systemUser.id,
oidc_access_token: token,
exp: introspectResponse.exp,
};

onSuccess(payload);
} catch (error) {
onError();
}
};

const verify = new Promise((resolve, reject) => {
jwt.verify(token, config.jwtSecret, async (error, decoded) => {
Expand All @@ -27,6 +56,6 @@ const authMiddleware = (req: Request, res: Response, next: NextFunction) => {
}
});
});
verify.then(onSuccess).catch(onError);
verify.then(onSuccess).catch(verifyOidcAccessToken);
};
export default authMiddleware;
28 changes: 0 additions & 28 deletions packages/server/src/api/middleware/oidcSession.ts

This file was deleted.

15 changes: 3 additions & 12 deletions packages/server/src/services/Authentication/_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,12 @@ import JWT from 'jsonwebtoken';
import { ISystemUser } from '@/interfaces';
import config from '@/config';

interface IExtendedSystemUser extends ISystemUser {
oidc_access_token?: string;
oidc_id_token?: string;
oidc_refresh_token?: string;
}

/**
* Generates JWT token for the given user.
* @param {IExtendedSystemUser} user
* @param {ISystemUser} user
* @return {string} token
*/
export const generateToken = (user: IExtendedSystemUser): string => {
export const generateToken = (user: ISystemUser): string => {
const today = new Date();
const exp = new Date(today);
exp.setDate(today.getDate() + 60);
Expand All @@ -22,10 +16,7 @@ export const generateToken = (user: IExtendedSystemUser): string => {
{
id: user.id, // We are gonna use this in the middleware 'isAuth'
exp: exp.getTime() / 1000,
oidc_access_token: user.oidc_access_token,
oidc_id_token: user.oidc_id_token,
oidc_refresh_token: user.oidc_refresh_token,
},
config.jwtSecret
);
};
};
46 changes: 29 additions & 17 deletions packages/server/src/services/Oidc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ import {
} from '@/config/oidcConfig';
import { ISystemUser, ITenant } from '@/interfaces';
import { oidcClient } from '@/lib/Oidc/OidcClient';
import { generateToken } from '@/services/Authentication/_utils';
import TenantsManagerService from '@/services/Tenancy/TenantsManager';
import { Tenant } from '@/system/models';
import { cloneDeep } from 'lodash';
import moment from 'moment';
import { TokenSet, UnknownObject, UserinfoResponse } from 'openid-client';
import {
IntrospectionResponse,
TokenSet,
UnknownObject,
UserinfoResponse,
} from 'openid-client';
import { Inject } from 'typedi';
interface IOidcLoginResponse {
token: string;
Expand Down Expand Up @@ -54,7 +58,20 @@ export class OidcService {
}

/**
* Authorize and grant access tokens
* Introspect access token
* @param {string} accessToken
* @return {Promise<IntrospectionResponse>}
*/
public async introspectAccessToken(
accessToken: string
): Promise<IntrospectionResponse> {
const introspectionResponse = await oidcClient.introspect(accessToken);

return introspectionResponse;
}

/**
* Get user info by access token
* @param {string} accessToken
* @return {Promise<UserinfoResponse<UnknownObject, UnknownObject>>}
*/
Expand Down Expand Up @@ -115,13 +132,7 @@ export class OidcService {
// Remove password property from user object.
Reflect.deleteProperty(user, 'password');

const token = generateToken({
...systemUser,
oidc_access_token: tokenSet.access_token,
oidc_id_token: tokenSet.id_token,
oidc_refresh_token: tokenSet.refresh_token,
});

const token = accessToken;
return {
token,
user,
Expand All @@ -131,17 +142,18 @@ export class OidcService {

/**
* Logout oidc user
* @param {string} idToken
* @param {string} oidcAccessToken
* @return {string}
*/
public async generateEndSessionUrl({
oidcIdToken,
oidcAccessToken,
}): Promise<string> | null {
if (!oidcIdToken || !oidcAccessToken) return null;
public async generateEndSessionUrl(
oidcAccessToken: string
): Promise<string> | null {
if (!oidcAccessToken) return null;

const loggedOutUrl = oidcClient.endSessionUrl({
id_token_hint: oidcIdToken,
id_token_hint: {
access_token: oidcAccessToken,
},
});

await oidcClient.revoke(oidcAccessToken, 'access_token');
Expand Down

0 comments on commit 1b7dfa5

Please sign in to comment.