Skip to content

Commit

Permalink
chore: esm imports!
Browse files Browse the repository at this point in the history
  • Loading branch information
danieldietzler committed Oct 21, 2024
1 parent 82f9fc7 commit 1432183
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 77 deletions.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22.10.0
63 changes: 19 additions & 44 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"format:fix": "prettier --write .",
"start": "npm run start:dev",
"nest": "nest",
"start:dev": "nest start --watch --",
"start:debug": "nest start --debug 9240 --watch --",
"start:dev": "nest start --watch -e 'node --experimental-require-module' --",
"start:debug": "nest start --debug 9240 --watch -e 'node --experimental-require-module' --",
"lint": "eslint \"src/**/*.ts\" --max-warnings 0",
"lint:fix": "npm run lint -- --fix",
"check": "tsc --noEmit",
Expand Down Expand Up @@ -46,7 +46,7 @@
"kysely": "^0.27.4",
"lodash": "^4.17.21",
"luxon": "^3.4.3",
"openid-client": "^5.6.5",
"openid-client": "6.0.0",
"pg": "^8.12.0",
"zulip-js": "^2.0.9"
},
Expand Down Expand Up @@ -75,6 +75,6 @@
"npm": ">=7.0.0"
},
"volta": {
"node": "20.18.0"
"node": "22.10.0"
}
}
48 changes: 19 additions & 29 deletions src/services/oauth.service.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,37 @@
import { BadRequestException, Inject, Injectable, InternalServerErrorException, Logger } from '@nestjs/common';
import { Client, Issuer, generators } from 'openid-client';
// @ts-expect-error f'ing ts does not let you import types from esm
import type { Configuration, ServerMetadata } from 'openid-client';
// @ts-expect-error we have the experimental flag enabled so we can import esm packages
import client from 'openid-client';
import { getConfig } from 'src/config';
import { OAuthAuthorizeDto, OAuthCallbackDto } from 'src/dtos/oauth.dto';
import { IDatabaseRepository } from 'src/interfaces/database.interface';

type GithubProfile = {
login: string;
id: string;
avatar_url: string;
url: string;
type: 'User';
name: string;
created_at: string;
updated_at: string;
};

type StateItem = { value: string; expiresAt: number };
const stateMap = new Map<string, StateItem>();

@Injectable()
export class OAuthService {
private logger: Logger = new Logger(OAuthService.name);
private client: Client;
private config: Configuration;

constructor(@Inject(IDatabaseRepository) private database: IDatabaseRepository) {
const issuer = new Issuer({
const { github } = getConfig();
const server: ServerMetadata = {
issuer: 'https://github.com',
authorization_endpoint: 'https://github.com/login/oauth/authorize',
token_endpoint: 'https://github.com/login/oauth/access_token',
userinfo_endpoint: 'https://api.github.com/user',
});
};

const { github } = getConfig();
this.client = new issuer.Client({
client_id: github.clientId,
client_secret: github.clientSecret,
});
this.config = new client.Configuration(server, github.clientId, github.clientSecret);
}

authorize(dto: OAuthAuthorizeDto) {
const state = generators.state();
stateMap.set(state, { value: state, expiresAt: Date.now() + 5 * 60 * 1000 });
const state = client.randomState();
stateMap.set(dto.redirectUri, { value: state, expiresAt: Date.now() + 5 * 60 * 1000 });
return {
url: this.client.authorizationUrl({
url: client.buildAuthorizationUrl(this.config, {
state,
scope: 'openid profile email',
redirect_uri: dto.redirectUri,
Expand All @@ -53,21 +42,22 @@ export class OAuthService {
async callback({ url }: OAuthCallbackDto) {
try {
const redirectUri = new URL(url).origin + '/claim/callback';
const params = this.client.callbackParams(url);

if (!params.state || !stateMap.has(params.state)) {
if (!stateMap.has(redirectUri)) {
throw new BadRequestException('Invalid state parameter');
}

const stateItem = stateMap.get(params.state);
const stateItem = stateMap.get(redirectUri);
if (!stateItem || stateItem.expiresAt < Date.now()) {
throw new BadRequestException('Invalid state parameter');
}

const tokens = await this.client.oauthCallback(redirectUri, params, { state: stateItem.value });
const profile = await this.client.userinfo<GithubProfile>(tokens);
const tokens = await client.authorizationCodeGrant(this.config, new URL(redirectUri), {
expectedState: stateItem.value,
});
const profile = await client.fetchUserInfo(this.config, tokens.access_token, tokens.claims()?.sub || '');

const licenses = await this.database.getSponsorLicenses(profile.login);
const licenses = await this.database.getSponsorLicenses(profile.sub);

return {
username: profile.login,
Expand Down

0 comments on commit 1432183

Please sign in to comment.