jwt issuing

This commit is contained in:
Evert Prants 2022-09-16 18:11:36 +03:00
parent 5769eca8ee
commit ff431c958c
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
11 changed files with 75 additions and 10 deletions

6
package-lock.json generated
View File

@ -2142,8 +2142,8 @@
"dev": true
},
"node_modules/@icynet/oauth2-provider": {
"version": "1.0.0",
"resolved": "git+https://gitlab.icynet.eu/IcyNetwork/oauth2-provider.git#a440d1f4ac53ccb6989dd25221797490611e240a",
"version": "1.0.5",
"resolved": "git+https://gitlab.icynet.eu/IcyNetwork/oauth2-provider.git#20c0771bf08cafb27809e6cdb21dbff0ae40aec3",
"license": "MIT",
"dependencies": {
"express": "^4.17.3",
@ -14155,7 +14155,7 @@
"dev": true
},
"@icynet/oauth2-provider": {
"version": "git+https://gitlab.icynet.eu/IcyNetwork/oauth2-provider.git#a440d1f4ac53ccb6989dd25221797490611e240a",
"version": "git+https://gitlab.icynet.eu/IcyNetwork/oauth2-provider.git#20c0771bf08cafb27809e6cdb21dbff0ae40aec3",
"from": "@icynet/oauth2-provider@git+https://gitlab.icynet.eu/IcyNetwork/oauth2-provider.git",
"requires": {
"express": "^4.17.3",

View File

@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
import { Client } from 'connect-redis';
import { User } from 'src/modules/objects/user/user.entity';
const UNPRIVILEGED_STRIP = ['openid', 'id_token', 'management', 'implicit'];
const UNPRIVILEGED_STRIP = ['id_token', 'management', 'implicit'];
@Injectable()
export class AdminService {

View File

@ -39,8 +39,8 @@ export const configProviders: Provider<any>[] = [
},
jwt: {
algorithm: 'RS256',
issuer: 'localhost',
expiration: 3600,
issuer: 'http://localhost',
expiration: 604800,
},
database: {
type: 'mysql',

View File

@ -56,6 +56,8 @@ export class ClientAdapter implements OAuth2ClientAdapter {
}
checkScope(client: OAuth2Client, scope: string[]): boolean {
return scope.every((one) => client.scope.includes(one));
return scope.every(
(one) => one === 'profile' || client.scope.includes(one),
);
}
}

View File

@ -12,6 +12,7 @@ export class CodeAdapter implements OAuth2CodeAdapter {
clientId: string,
scope: string | string[],
ttl: number,
nonce?: string,
): Promise<string> {
const client = await this._service.clientService.getById(clientId);
const user = await this._service.userService.getById(userId);
@ -31,6 +32,7 @@ export class CodeAdapter implements OAuth2CodeAdapter {
scopes,
expiresAt,
user,
nonce,
);
return accessToken;

View File

@ -0,0 +1,43 @@
import { JWTAdapter, OAuth2User, OAuth2Client } from '@icynet/oauth2-provider';
import { OAuth2Service } from '../oauth2.service';
export class IcyJWTAdapter implements JWTAdapter {
constructor(private _client: OAuth2Service) {}
async issueIdToken(
rawUser: OAuth2User,
rawClient: OAuth2Client,
scope: string[],
nonce?: string,
): Promise<string> {
const user = await this._client.userService.getById(rawUser.id as number);
const userData: Record<string, unknown> = {
name: user.display_name,
preferred_username: user.username,
nickname: user.display_name,
updated_at: user.updated_at,
nonce,
};
if (scope.includes('email')) {
userData.email = user.email;
userData.email_verified = true;
}
if (
(scope.includes('image') || scope.includes('profile')) &&
user.picture
) {
userData.picture = `${this._client.config.get('app.base_url')}/uploads/${
user.picture.file
}`;
}
return this._client.jwt.issue(
userData,
user.uuid as string,
rawClient.id as string,
);
}
}

View File

@ -3,10 +3,17 @@ import { OAuth2ClientModule } from 'src/modules/objects/oauth2-client/oauth2-cli
import { OAuth2TokenModule } from 'src/modules/objects/oauth2-token/oauth2-token.module';
import { UploadModule } from 'src/modules/objects/upload/upload.module';
import { UserModule } from 'src/modules/objects/user/user.module';
import { JWTModule } from '../jwt/jwt.module';
import { OAuth2Service } from './oauth2.service';
@Module({
imports: [UserModule, UploadModule, OAuth2ClientModule, OAuth2TokenModule],
imports: [
UserModule,
UploadModule,
OAuth2ClientModule,
OAuth2TokenModule,
JWTModule,
],
providers: [OAuth2Service],
exports: [OAuth2Service],
})

View File

@ -5,9 +5,11 @@ import { OAuth2ClientService } from 'src/modules/objects/oauth2-client/oauth2-cl
import { OAuth2TokenService } from 'src/modules/objects/oauth2-token/oauth2-token.service';
import { UserService } from 'src/modules/objects/user/user.service';
import { TokenService } from 'src/modules/utility/services/token.service';
import { JWTService } from '../jwt/jwt.service';
import { AccessTokenAdapter } from './adapter/access-token.adapter';
import { ClientAdapter } from './adapter/client.adapter';
import { CodeAdapter } from './adapter/code.adapter';
import { IcyJWTAdapter } from './adapter/jwt.adapter';
import { RefreshTokenAdapter } from './adapter/refresh-token.adapter';
import { UserAdapter } from './adapter/user.adapter';
@ -27,6 +29,7 @@ export class OAuth2Service {
user: new UserAdapter(this),
client: new ClientAdapter(this),
code: new CodeAdapter(this),
jwt: new IcyJWTAdapter(this),
};
public oauth = new OAuth2Provider(
@ -64,6 +67,7 @@ export class OAuth2Service {
constructor(
public token: TokenService,
public jwt: JWTService,
public config: ConfigurationService,
public userService: UserService,
public clientService: OAuth2ClientService,

View File

@ -4,7 +4,6 @@ import {
Entity,
ManyToOne,
OneToMany,
OneToOne,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';

View File

@ -20,7 +20,13 @@ export class OAuth2ClientService {
'implicit',
];
public availableScopes = ['image', 'email', 'privileges', 'management'];
public availableScopes = [
'image',
'email',
'privileges',
'management',
'openid',
];
constructor(
@Inject('CLIENT_REPOSITORY')

View File

@ -18,6 +18,7 @@ export class OAuth2TokenService {
scope: string,
expiry: Date,
user?: User,
nonce?: string,
): Promise<OAuth2Token> {
const newToken = new OAuth2Token();
newToken.client = client;
@ -26,6 +27,7 @@ export class OAuth2TokenService {
newToken.scope = scope;
newToken.user = user;
newToken.expires_at = expiry;
newToken.nonce = nonce;
await this.tokenRepository.save(newToken);