2 Commits

Author SHA1 Message Date
8734abcc99 updating ms graph module 2026-05-11 20:47:40 -05:00
c66cfb3c9e switching user module to msgraph module (#15) 2025-11-16 09:28:06 -06:00
20 changed files with 197 additions and 109 deletions

View File

@@ -0,0 +1,4 @@
import { Controller } from '@nestjs/common';
@Controller('auth-controller')
export class AuthControllerController {}

View File

@@ -1,11 +1,12 @@
import { ExecutionContext, Injectable } from '@nestjs/common'; import { ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AuthGuard as PassportAuthGuard } from '@nestjs/passport'; import { AuthGuard as PassportAuthGuard } from '@nestjs/passport';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { IS_PUBLIC_KEY } from '../decorators/public.decorator'; import { IS_PUBLIC_KEY } from '../decorators/public.decorator';
@Injectable() @Injectable()
export class AuthGuard extends PassportAuthGuard('oidc') { export class AuthGuard extends PassportAuthGuard('jwt') {
constructor() { constructor(private readonly reflector: Reflector) {
super(); super();
} }

View File

@@ -1,10 +1,5 @@
export interface AuthModuleOptions { export interface AuthModuleOptions {
authorizationUrl: string; audience: string;
issuer: string; issuerUrl: string;
callbackUrl: string; jwksUri: string;
clientId: string;
clientSecret: string;
scope: string;
tokenUrl: string;
userInfoUrl: string;
} }

View File

@@ -1,16 +1,16 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport'; import { PassportModule } from '@nestjs/passport';
import { OidcStrategy } from './oidc.strategy'; import { AuthStrategy } from './auth.strategy';
import { ConfigurableModuleClass } from './auth.module-definition'; import { ConfigurableModuleClass } from './auth.module-definition';
@Module({ @Module({
imports: [ imports: [
PassportModule.register({ PassportModule.register({
defaultStrategy: 'oidc' defaultStrategy: 'jwt'
}) })
], ],
providers: [ providers: [
OidcStrategy AuthStrategy
] ]
}) })
export class AuthModule extends ConfigurableModuleClass {} export class AuthModule extends ConfigurableModuleClass {}

View File

@@ -0,0 +1,29 @@
import { Inject, Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import * as jwksRsa from 'jwks-rsa';
import { AuthModuleOptions } from './auth.interface';
import { MODULE_OPTIONS_TOKEN } from './auth.module-definition';
@Injectable()
export class AuthStrategy extends PassportStrategy(Strategy, 'jwt') {
constructor(@Inject(MODULE_OPTIONS_TOKEN) authModuleOptions: AuthModuleOptions) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
audience: authModuleOptions.audience,
issuer: authModuleOptions.issuerUrl,
algorithms: ['RS256'],
ignoreExpiration: false,
secretOrKeyProvider: jwksRsa.passportJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: authModuleOptions.jwksUri,
}),
});
}
validate(payload: any) {
return payload;
}
}

View File

@@ -1,31 +0,0 @@
import { PassportStrategy } from "@nestjs/passport";
import { Strategy, Profile } from 'passport-openidconnect';
import { MODULE_OPTIONS_TOKEN } from "./auth.module-definition";
import { AuthModuleOptions } from "./auth.interface";
import { Inject, Injectable } from "@nestjs/common";
@Injectable()
export class OidcStrategy extends PassportStrategy(Strategy, 'oidc') {
constructor(@Inject(MODULE_OPTIONS_TOKEN) authModuleOptions: AuthModuleOptions) {
super({
authorizationURL: authModuleOptions.authorizationUrl,
callbackURL: authModuleOptions.callbackUrl,
clientID: authModuleOptions.clientId,
clientSecret: authModuleOptions.clientSecret,
issuer: authModuleOptions.issuer,
scope: authModuleOptions.scope,
tokenURL: authModuleOptions.tokenUrl,
userInfoURL: authModuleOptions.userInfoUrl
})
}
async validate(profile: Profile, done: Function): Promise<any> {
const user = {
id: profile.id,
email: profile.emails,
name: profile.displayName
}
done(null, user)
}
}

View File

@@ -1,4 +0,0 @@
import { SetMetadata } from "@nestjs/common";
export const IS_PUBLIC_KEY = 'isPublic'
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);

View File

@@ -1,8 +1,7 @@
// Auth // Auth
export * from './auth/auth.module'; export * from './auth/auth.module';
export * from './auth/auth.gaurd'; export * from './auth/auth.guard';
export * from './auth/public.decorator';
// Custom Error // Custom Error
@@ -12,7 +11,9 @@ export * from './util/customError';
export { IS_PUBLIC_KEY, Public } from './decorators/public.decorator' export { IS_PUBLIC_KEY, Public } from './decorators/public.decorator'
// User // MsGraph
export * from './msgraph/msgraph.module';
export * from './msgraph/msgraph.service';
export * from './user/user.module';
export * from './user/user.service';

View File

@@ -0,0 +1 @@
export const MSGRAPH_MODULE_OPTIONS = 'MSGRAPH_MODULE_OPTIONS'

View File

@@ -6,26 +6,26 @@ import {
StreamableFile, StreamableFile,
UseGuards, UseGuards,
} from '@nestjs/common'; } from '@nestjs/common';
import { UserService } from './user.service'; import { MsGraphService } from './msgraph.service';
import { Client as MsGraphClient } from '@microsoft/microsoft-graph-client'; import { Client as MsGraphClient } from '@microsoft/microsoft-graph-client';
import { AuthGuard } from '../auth/auth.gaurd'; import { AuthGuard } from '../auth/auth.guard';
@Controller('user') @Controller('msgraph')
export class UserController { export class MsGraphController {
constructor( constructor(
private readonly userService: UserService private readonly msGraphService: MsGraphService
) {} ) {}
@Get('photo') @Get('photo')
@UseGuards(AuthGuard) @UseGuards(AuthGuard)
async getProfilePhoto(@Headers() headers: any): Promise<StreamableFile> { async getProfilePhoto(@Headers() headers: any): Promise<StreamableFile> {
try { try {
const graphToken: string = await this.userService.getMsGraphAuth( const graphToken: string = await this.msGraphService.getMsGraphAuth(
headers.authorization.replace('Bearer ', ''), headers.authorization.replace('Bearer ', ''),
['user.read'] ['user.read']
); );
const client: MsGraphClient = const client: MsGraphClient =
await this.userService.getMsGraphClientDelegated(graphToken); await this.msGraphService.getMsGraphClientDelegated(graphToken);
const blob: Blob = await client.api(`me/photos('48x48')/$value`).get(); const blob: Blob = await client.api(`me/photos('48x48')/$value`).get();
const arrayBuffer: ArrayBuffer = await blob.arrayBuffer(); const arrayBuffer: ArrayBuffer = await blob.arrayBuffer();
const buffer: Buffer = Buffer.from(arrayBuffer); const buffer: Buffer = Buffer.from(arrayBuffer);
@@ -43,12 +43,12 @@ export class UserController {
@UseGuards(AuthGuard) @UseGuards(AuthGuard)
async getUserProfile(@Headers() headers: any): Promise<any> { async getUserProfile(@Headers() headers: any): Promise<any> {
try { try {
const graphToken: string = await this.userService.getMsGraphAuth( const graphToken: string = await this.msGraphService.getMsGraphAuth(
headers.authorization.replace('Bearer ', ''), headers.authorization.replace('Bearer ', ''),
['user.read'] ['user.read']
); );
const client: MsGraphClient = const client: MsGraphClient =
await this.userService.getMsGraphClientDelegated(graphToken); await this.msGraphService.getMsGraphClientDelegated(graphToken);
const userProfile = await client.api(`me`).get(); const userProfile = await client.api(`me`).get();
return userProfile; return userProfile;
@@ -66,7 +66,7 @@ export class UserController {
try { try {
const accessToken: string = headers.authorization.replace('Bearer ', ''); const accessToken: string = headers.authorization.replace('Bearer ', '');
const personSearchResults: any[] = const personSearchResults: any[] =
await this.userService.searchUsers(accessToken, search); await this.msGraphService.searchUsers(accessToken, search);
return personSearchResults; return personSearchResults;
} catch (error) { } catch (error) {

View File

@@ -1,5 +1,6 @@
export interface UserModuleOptions { export interface MsGraphModuleOptions {
tenantId: string; authority: string;
clientId: string; clientId: string;
clientSecret: string; clientSecret: string;
tenantId: string;
} }

View File

@@ -1,4 +1,4 @@
import { ConfigurableModuleBuilder } from '@nestjs/common'; import { ConfigurableModuleBuilder } from '@nestjs/common';
import { UserModuleOptions } from './user.interface'; import { MsGraphModuleOptions } from './msgraph.interface';
export const { ConfigurableModuleClass, ASYNC_OPTIONS_TYPE, MODULE_OPTIONS_TOKEN, OPTIONS_TYPE } = new ConfigurableModuleBuilder<UserModuleOptions>().build() export const { ConfigurableModuleClass, ASYNC_OPTIONS_TYPE, MODULE_OPTIONS_TOKEN, OPTIONS_TYPE } = new ConfigurableModuleBuilder<MsGraphModuleOptions>().build()

View File

@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { MsGraphService } from './msgraph.service';
import { ConfigurableModuleClass } from './msgraph.module-definition';
import { MsGraphController } from './msgraph.controller';
@Module({
controllers: [MsGraphController],
providers: [MsGraphService],
exports: [MsGraphService]
})
export class MsGraphModule extends ConfigurableModuleClass {}

View File

@@ -1,12 +1,12 @@
import { Inject, Injectable, StreamableFile } from '@nestjs/common'; import { Inject, Injectable, StreamableFile } from '@nestjs/common';
import { UserModuleOptions } from './user.interface'; import { MsGraphModuleOptions } from './msgraph.interface';
import { Client } from '@microsoft/microsoft-graph-client'; import { Client } from '@microsoft/microsoft-graph-client';
import { AuthenticationResult, ConfidentialClientApplication, OnBehalfOfRequest } from '@azure/msal-node'; import { AuthenticationResult, ConfidentialClientApplication, OnBehalfOfRequest } from '@azure/msal-node';
import { MODULE_OPTIONS_TOKEN } from './user.module-definition'; import { MODULE_OPTIONS_TOKEN } from './msgraph.module-definition';
@Injectable() @Injectable()
export class UserService { export class MsGraphService {
constructor(@Inject(MODULE_OPTIONS_TOKEN) private userModuleOptions: UserModuleOptions) {} constructor(@Inject(MODULE_OPTIONS_TOKEN) private msGraphModuleOptions: MsGraphModuleOptions) {}
async getMsGraphAuth(accessToken: string, scopes: string[]): Promise<string> { async getMsGraphAuth(accessToken: string, scopes: string[]): Promise<string> {
try { try {
@@ -16,9 +16,9 @@ export class UserService {
} }
const cca = new ConfidentialClientApplication({ const cca = new ConfidentialClientApplication({
auth: { auth: {
clientId: this.userModuleOptions.clientId, clientId: this.msGraphModuleOptions.clientId,
clientSecret: this.userModuleOptions.clientSecret, clientSecret: this.msGraphModuleOptions.clientSecret,
authority: `https://login.microsoftonline.com/${this.userModuleOptions.tenantId}` authority: this.msGraphModuleOptions.authority
} }
}); });
const authenticationResult: AuthenticationResult = await cca.acquireTokenOnBehalfOf(oboRequest); const authenticationResult: AuthenticationResult = await cca.acquireTokenOnBehalfOf(oboRequest);
@@ -67,7 +67,7 @@ export class UserService {
async searchUsers(accessToken, searchText: string): Promise<any> { async searchUsers(accessToken, searchText: string): Promise<any> {
try { try {
const graphToken: string = await this.getMsGraphAuth(accessToken, ['user.read']); const graphToken: string = await this.getMsGraphAuth(accessToken, ['user.read.all']);
const client: Client = await this.getMsGraphClientDelegated(graphToken); const client: Client = await this.getMsGraphClientDelegated(graphToken);
const results: any = await client const results: any = await client
.api('users') .api('users')

View File

@@ -1 +0,0 @@
export const USER_MODULE_OPTIONS = 'USER_MODULE_OPTIONS'

View File

@@ -1,11 +0,0 @@
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { ConfigurableModuleClass } from './user.module-definition';
import { UserController } from './user.controller';
@Module({
controllers: [UserController],
providers: [UserService],
exports: [UserService]
})
export class UserModule extends ConfigurableModuleClass {}

View File

@@ -5,5 +5,5 @@
"outDir": "../../dist/libs/modules" "outDir": "../../dist/libs/modules"
}, },
"include": ["src/**/*"], "include": ["src/**/*"],
"exclude": ["node_modules", "dist", "test", "**/*spec.ts"] "exclude": ["node_modules", "src/**/*.spec.ts"]
} }

127
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "@noahspan/noahspan-modules", "name": "@noahspan/noahspan-modules",
"version": "1.1.5", "version": "1.2.8",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@noahspan/noahspan-modules", "name": "@noahspan/noahspan-modules",
"version": "1.1.5", "version": "1.2.8",
"license": "UNLICENSED", "license": "UNLICENSED",
"dependencies": { "dependencies": {
"@azure/identity": "^4.2.0", "@azure/identity": "^4.2.0",
@@ -14,9 +14,12 @@
"@microsoft/microsoft-graph-client": "^3.0.7", "@microsoft/microsoft-graph-client": "^3.0.7",
"@nestjs/common": "^11.0.11", "@nestjs/common": "^11.0.11",
"@nestjs/core": "^11.0.11", "@nestjs/core": "^11.0.11",
"@nestjs/jwt": "^11.0.0",
"@nestjs/mapped-types": "*",
"@nestjs/passport": "^11.0.5", "@nestjs/passport": "^11.0.5",
"@nestjs/platform-express": "^11.0.11", "@nestjs/platform-express": "^11.0.11",
"axios": "^1.7.2", "axios": "^1.7.2",
"jwks-rsa": "^3.2.0",
"passport": "^0.7.0", "passport": "^0.7.0",
"passport-jwt": "^4.0.1", "passport-jwt": "^4.0.1",
"passport-openidconnect": "^0.1.2", "passport-openidconnect": "^0.1.2",
@@ -2369,6 +2372,37 @@
} }
} }
}, },
"node_modules/@nestjs/jwt": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-11.0.0.tgz",
"integrity": "sha512-v7YRsW3Xi8HNTsO+jeHSEEqelX37TVWgwt+BcxtkG/OfXJEOs6GZdbdza200d6KqId1pJQZ6UPj1F0M6E+mxaA==",
"dependencies": {
"@types/jsonwebtoken": "9.0.7",
"jsonwebtoken": "9.0.2"
},
"peerDependencies": {
"@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0"
}
},
"node_modules/@nestjs/mapped-types": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.1.0.tgz",
"integrity": "sha512-W+n+rM69XsFdwORF11UqJahn4J3xi4g/ZEOlJNL6KoW5ygWSmBB2p0S2BZ4FQeS/NDH72e6xIcu35SfJnE8bXw==",
"peerDependencies": {
"@nestjs/common": "^10.0.0 || ^11.0.0",
"class-transformer": "^0.4.0 || ^0.5.0",
"class-validator": "^0.13.0 || ^0.14.0",
"reflect-metadata": "^0.1.12 || ^0.2.0"
},
"peerDependenciesMeta": {
"class-transformer": {
"optional": true
},
"class-validator": {
"optional": true
}
}
},
"node_modules/@nestjs/passport": { "node_modules/@nestjs/passport": {
"version": "11.0.5", "version": "11.0.5",
"resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-11.0.5.tgz", "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-11.0.5.tgz",
@@ -2670,7 +2704,6 @@
"version": "1.19.5", "version": "1.19.5",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
"integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
"dev": true,
"dependencies": { "dependencies": {
"@types/connect": "*", "@types/connect": "*",
"@types/node": "*" "@types/node": "*"
@@ -2680,7 +2713,6 @@
"version": "3.4.38", "version": "3.4.38",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
"integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
"dev": true,
"dependencies": { "dependencies": {
"@types/node": "*" "@types/node": "*"
} }
@@ -2721,7 +2753,6 @@
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
"integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
"dev": true,
"dependencies": { "dependencies": {
"@types/body-parser": "*", "@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.33", "@types/express-serve-static-core": "^4.17.33",
@@ -2733,7 +2764,6 @@
"version": "4.19.1", "version": "4.19.1",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.1.tgz", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.1.tgz",
"integrity": "sha512-ej0phymbFLoCB26dbbq5PGScsf2JAJ4IJHjG10LalgUV36XKTmA4GdA+PVllKvRk0sEKt64X8975qFnkSi0hqA==", "integrity": "sha512-ej0phymbFLoCB26dbbq5PGScsf2JAJ4IJHjG10LalgUV36XKTmA4GdA+PVllKvRk0sEKt64X8975qFnkSi0hqA==",
"dev": true,
"dependencies": { "dependencies": {
"@types/node": "*", "@types/node": "*",
"@types/qs": "*", "@types/qs": "*",
@@ -2753,8 +2783,7 @@
"node_modules/@types/http-errors": { "node_modules/@types/http-errors": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
"integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA=="
"dev": true
}, },
"node_modules/@types/istanbul-lib-coverage": { "node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.6", "version": "2.0.6",
@@ -2796,6 +2825,14 @@
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
"dev": true "dev": true
}, },
"node_modules/@types/jsonwebtoken": {
"version": "9.0.7",
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz",
"integrity": "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/methods": { "node_modules/@types/methods": {
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz",
@@ -2805,14 +2842,12 @@
"node_modules/@types/mime": { "node_modules/@types/mime": {
"version": "1.3.5", "version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
"dev": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.12.12", "version": "20.12.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz",
"integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==",
"dev": true,
"dependencies": { "dependencies": {
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
@@ -2860,14 +2895,12 @@
"node_modules/@types/qs": { "node_modules/@types/qs": {
"version": "6.9.15", "version": "6.9.15",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz",
"integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg=="
"dev": true
}, },
"node_modules/@types/range-parser": { "node_modules/@types/range-parser": {
"version": "1.2.7", "version": "1.2.7",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
"integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="
"dev": true
}, },
"node_modules/@types/semver": { "node_modules/@types/semver": {
"version": "7.5.8", "version": "7.5.8",
@@ -2879,7 +2912,6 @@
"version": "0.17.4", "version": "0.17.4",
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
"integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
"dev": true,
"dependencies": { "dependencies": {
"@types/mime": "^1", "@types/mime": "^1",
"@types/node": "*" "@types/node": "*"
@@ -2889,7 +2921,6 @@
"version": "1.15.7", "version": "1.15.7",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz",
"integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==",
"dev": true,
"dependencies": { "dependencies": {
"@types/http-errors": "*", "@types/http-errors": "*",
"@types/node": "*", "@types/node": "*",
@@ -6783,6 +6814,14 @@
"url": "https://github.com/chalk/supports-color?sponsor=1" "url": "https://github.com/chalk/supports-color?sponsor=1"
} }
}, },
"node_modules/jose": {
"version": "4.15.9",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz",
"integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==",
"funding": {
"url": "https://github.com/sponsors/panva"
}
},
"node_modules/js-tokens": { "node_modules/js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -6898,6 +6937,22 @@
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
} }
}, },
"node_modules/jwks-rsa": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.2.0.tgz",
"integrity": "sha512-PwchfHcQK/5PSydeKCs1ylNym0w/SSv8a62DgHJ//7x2ZclCoinlsjAfDxAAbpoTPybOum/Jgy+vkvMmKz89Ww==",
"dependencies": {
"@types/express": "^4.17.20",
"@types/jsonwebtoken": "^9.0.4",
"debug": "^4.3.4",
"jose": "^4.15.4",
"limiter": "^1.1.5",
"lru-memoizer": "^2.2.0"
},
"engines": {
"node": ">=14"
}
},
"node_modules/jws": { "node_modules/jws": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
@@ -6947,6 +7002,11 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/limiter": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz",
"integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA=="
},
"node_modules/lines-and-columns": { "node_modules/lines-and-columns": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -6983,6 +7043,11 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true "dev": true
}, },
"node_modules/lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
},
"node_modules/lodash.includes": { "node_modules/lodash.includes": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -7055,6 +7120,31 @@
"yallist": "^3.0.2" "yallist": "^3.0.2"
} }
}, },
"node_modules/lru-memoizer": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.3.0.tgz",
"integrity": "sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==",
"dependencies": {
"lodash.clonedeep": "^4.5.0",
"lru-cache": "6.0.0"
}
},
"node_modules/lru-memoizer/node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/lru-memoizer/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/magic-string": { "node_modules/magic-string": {
"version": "0.30.17", "version": "0.30.17",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
@@ -9254,8 +9344,7 @@
"node_modules/undici-types": { "node_modules/undici-types": {
"version": "5.26.5", "version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
"dev": true
}, },
"node_modules/universalify": { "node_modules/universalify": {
"version": "2.0.1", "version": "2.0.1",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@noahspan/noahspan-modules", "name": "@noahspan/noahspan-modules",
"version": "1.2.0", "version": "1.2.11",
"description": "", "description": "",
"author": "", "author": "",
"license": "UNLICENSED", "license": "UNLICENSED",
@@ -29,9 +29,12 @@
"@microsoft/microsoft-graph-client": "^3.0.7", "@microsoft/microsoft-graph-client": "^3.0.7",
"@nestjs/common": "^11.0.11", "@nestjs/common": "^11.0.11",
"@nestjs/core": "^11.0.11", "@nestjs/core": "^11.0.11",
"@nestjs/jwt": "^11.0.0",
"@nestjs/mapped-types": "*",
"@nestjs/passport": "^11.0.5", "@nestjs/passport": "^11.0.5",
"@nestjs/platform-express": "^11.0.11", "@nestjs/platform-express": "^11.0.11",
"axios": "^1.7.2", "axios": "^1.7.2",
"jwks-rsa": "^3.2.0",
"passport": "^0.7.0", "passport": "^0.7.0",
"passport-jwt": "^4.0.1", "passport-jwt": "^4.0.1",
"passport-openidconnect": "^0.1.2", "passport-openidconnect": "^0.1.2",

View File

@@ -1,4 +1,4 @@
{ {
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"] "exclude": ["node_modules", "**/*.spec.ts"]
} }