2022-03-09 18:37:04 +00:00
|
|
|
import { OAuth2CodeAdapter, OAuth2Code } from '@icynet/oauth2-provider';
|
|
|
|
import { OAuth2TokenType } from 'src/modules/objects/oauth2-token/oauth2-token.entity';
|
|
|
|
import { OAuth2Service } from '../oauth2.service';
|
|
|
|
|
|
|
|
export class CodeAdapter implements OAuth2CodeAdapter {
|
|
|
|
constructor(private _service: OAuth2Service) {}
|
|
|
|
|
|
|
|
ttl = 3600;
|
2022-12-03 08:02:58 +00:00
|
|
|
challengeMethods = ['plain', 'S256'];
|
2022-03-09 18:37:04 +00:00
|
|
|
|
|
|
|
async create(
|
|
|
|
userId: number,
|
|
|
|
clientId: string,
|
|
|
|
scope: string | string[],
|
|
|
|
ttl: number,
|
2022-09-16 15:11:36 +00:00
|
|
|
nonce?: string,
|
2022-12-03 08:02:58 +00:00
|
|
|
codeChallenge?: string,
|
|
|
|
codeChallengeMethod?: 'plain' | 'S256',
|
2022-03-09 18:37:04 +00:00
|
|
|
): Promise<string> {
|
|
|
|
const client = await this._service.clientService.getById(clientId);
|
|
|
|
const user = await this._service.userService.getById(userId);
|
|
|
|
const accessToken = this._service.token.generateString(64);
|
|
|
|
|
|
|
|
// Standardize scope value
|
|
|
|
const scopes = (
|
|
|
|
!Array.isArray(scope) ? this._service.splitScope(scope) : scope
|
|
|
|
).join(' ');
|
|
|
|
|
|
|
|
const expiresAt = new Date(Date.now() + ttl * 1000);
|
2022-12-03 08:02:58 +00:00
|
|
|
const pcke =
|
|
|
|
codeChallenge && codeChallengeMethod
|
|
|
|
? `${this.challengeMethods.indexOf(
|
|
|
|
codeChallengeMethod,
|
|
|
|
)}:${codeChallenge}`
|
|
|
|
: null;
|
2022-03-09 18:37:04 +00:00
|
|
|
|
|
|
|
this._service.tokenService.insertToken(
|
|
|
|
accessToken,
|
|
|
|
OAuth2TokenType.CODE,
|
|
|
|
client,
|
|
|
|
scopes,
|
|
|
|
expiresAt,
|
|
|
|
user,
|
2022-09-16 15:11:36 +00:00
|
|
|
nonce,
|
2022-12-03 08:02:58 +00:00
|
|
|
pcke,
|
2022-03-09 18:37:04 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
return accessToken;
|
|
|
|
}
|
|
|
|
|
|
|
|
async fetchByCode(code: string | OAuth2Code): Promise<OAuth2Code> {
|
|
|
|
const findBy = typeof code === 'string' ? code : code.code;
|
|
|
|
const find = await this._service.tokenService.fetchByToken(
|
|
|
|
findBy,
|
|
|
|
OAuth2TokenType.CODE,
|
|
|
|
);
|
|
|
|
|
2022-03-26 07:22:14 +00:00
|
|
|
if (!find) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2022-12-03 08:02:58 +00:00
|
|
|
let codeChallenge: string;
|
|
|
|
let codeChallengeMethod: 'plain' | 'S256';
|
|
|
|
if (find.pcke) {
|
|
|
|
codeChallengeMethod = this.challengeMethods[
|
|
|
|
Number(find.pcke.substring(0, 1))
|
|
|
|
] as 'plain' | 'S256';
|
|
|
|
codeChallenge = find.pcke.substring(2);
|
|
|
|
}
|
|
|
|
|
2022-03-09 18:37:04 +00:00
|
|
|
return {
|
|
|
|
...find,
|
|
|
|
code: find.token,
|
|
|
|
client_id: find.client.client_id,
|
|
|
|
user_id: find.user.id,
|
2022-12-03 08:02:58 +00:00
|
|
|
code_challenge: codeChallenge,
|
|
|
|
code_challenge_method: codeChallengeMethod,
|
2022-03-09 18:37:04 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
async removeByCode(code: string | OAuth2Code): Promise<boolean> {
|
|
|
|
const findBy = typeof code === 'string' ? code : code.code;
|
|
|
|
const find = await this._service.tokenService.fetchByToken(
|
|
|
|
findBy,
|
|
|
|
OAuth2TokenType.CODE,
|
|
|
|
);
|
|
|
|
this._service.tokenService.remove(find);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
getUserId(code: OAuth2Code): string {
|
|
|
|
return code.user_id as string;
|
|
|
|
}
|
|
|
|
|
|
|
|
getClientId(code: OAuth2Code): string {
|
|
|
|
return code.client_id as string;
|
|
|
|
}
|
|
|
|
|
|
|
|
getScope(code: OAuth2Code): string {
|
|
|
|
return code.scope;
|
|
|
|
}
|
|
|
|
|
|
|
|
checkTTL(code: OAuth2Code): boolean {
|
|
|
|
return code.expires_at.getTime() > Date.now();
|
|
|
|
}
|
2022-12-03 08:02:58 +00:00
|
|
|
|
|
|
|
getCodeChallenge(code: OAuth2Code) {
|
|
|
|
return {
|
|
|
|
method: code.code_challenge_method,
|
|
|
|
challenge: code.code_challenge,
|
|
|
|
};
|
|
|
|
}
|
2022-03-09 18:37:04 +00:00
|
|
|
}
|