(encrypted: string): Promise
{
21 | return this.cipherService.decrypt(encrypted);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/oauth2/modules/common/token/strategies/index.ts:
--------------------------------------------------------------------------------
1 | export * from './strategy';
2 | export * from './jwt.strategy';
3 | export * from './aes.strategy';
4 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/oauth2/modules/common/token/strategies/jwt.strategy.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { TokenStrategy } from './strategy';
3 | import { JwtService } from '@app/lib/jwt';
4 | import { ConfigService } from '@nestjs/config';
5 |
6 | @Injectable()
7 | export class JwtStrategy implements TokenStrategy {
8 | constructor(
9 | private readonly config: ConfigService,
10 | private readonly jwtService: JwtService,
11 | ) {}
12 |
13 | sign(payload: any): Promise (encrypted: string): Promise {
21 | return this.jwtService.verify(encrypted, 'access_token');
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/oauth2/modules/common/token/strategies/strategy.ts:
--------------------------------------------------------------------------------
1 |
2 | export interface TokenStrategy {
3 | sign(payload: any): Promise (encrypted: string): Promise ;
6 | }
7 |
8 | export const TOKEN_STRATEGY = 'TOKEN_STRATEGY';
9 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/oauth2/modules/index.ts:
--------------------------------------------------------------------------------
1 | export * from './common';
2 | export * from './client-credentials';
3 | export * from './password';
4 | export * from './refresh-token';
5 | export * from './authorization-code';
6 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/oauth2/modules/password/index.ts:
--------------------------------------------------------------------------------
1 | export * from './services';
2 | export * from './password.module';
3 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/oauth2/modules/password/password.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { CommonModule } from '../common';
3 | import { PasswordServiceGrant } from './services';
4 | import { TypeOrmModule } from '@nestjs/typeorm';
5 | import { User } from '@app/entities';
6 |
7 | @Module({
8 | imports: [
9 | CommonModule,
10 | TypeOrmModule.forFeature([User]),
11 | ],
12 | providers: [
13 | PasswordServiceGrant,
14 | ],
15 | exports: [
16 | PasswordServiceGrant,
17 | ],
18 | })
19 | export class PasswordModule {}
20 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/oauth2/modules/password/services/index.ts:
--------------------------------------------------------------------------------
1 | export * from './password.service-grant';
2 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/oauth2/modules/refresh-token/index.ts:
--------------------------------------------------------------------------------
1 | export * from './refresh-token.module';
2 | export * from './services';
3 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/oauth2/modules/refresh-token/refresh-token.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { CommonModule } from '../common';
3 | import { RefreshTokenServiceGrant } from './services';
4 |
5 | @Module({
6 | imports: [
7 | CommonModule,
8 | ],
9 | providers: [
10 | RefreshTokenServiceGrant,
11 | ],
12 | exports: [
13 | RefreshTokenServiceGrant,
14 | ],
15 | })
16 | export class RefreshTokenModule {}
17 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/oauth2/modules/refresh-token/services/index.ts:
--------------------------------------------------------------------------------
1 | export * from './refresh-token.service-grant';
2 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/oauth2/oauth2.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { CodeService, TokenService } from './services';
3 | import { AuthorizeController, TokenController } from './controllers';
4 | import {
5 | CommonModule,
6 | ClientCredentialsModule,
7 | PasswordModule,
8 | RefreshTokenModule,
9 | AuthorizationCodeModule,
10 | } from './modules';
11 | import { TypeOrmModule } from '@nestjs/typeorm';
12 | import { OAuthAccessToken, OAuthClient, OAuthRefreshToken } from '@app/entities';
13 | import { DebugController } from '@app/modules/oauth2/controllers/debug.controller';
14 |
15 | @Module({
16 | imports: [
17 | CommonModule,
18 | ClientCredentialsModule,
19 | PasswordModule,
20 | RefreshTokenModule,
21 | AuthorizationCodeModule,
22 | TypeOrmModule.forFeature([
23 | OAuthAccessToken,
24 | OAuthRefreshToken,
25 | OAuthClient,
26 | ]),
27 | ],
28 | providers: [
29 | TokenService,
30 | CodeService,
31 | ],
32 | controllers: [
33 | TokenController,
34 | AuthorizeController,
35 | DebugController,
36 | ],
37 | })
38 | export class OAuth2Module {}
39 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/oauth2/services/index.ts:
--------------------------------------------------------------------------------
1 | export * from './token.service';
2 | export * from './code.service';
3 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/openid/controllers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './well-known.controller';
2 | export * from './user-info.controller';
3 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/openid/controllers/user-info.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get, Post, UseGuards } from '@nestjs/common';
2 | import { AccessToken, CurrentUser, JwtGuard } from '@app/modules/auth';
3 | import { User } from '@app/entities';
4 | import { AccessTokenJwtPayload } from '@app/modules/oauth2/interfaces';
5 | import { Scopes } from '@app/modules/oauth2/constants';
6 |
7 | @Controller('userinfo')
8 | export class UserInfoController {
9 | @UseGuards(JwtGuard)
10 | @Get()
11 | @Post()
12 | async userInfo(
13 | @CurrentUser() user: User,
14 | @AccessToken() token: AccessTokenJwtPayload,
15 | ) {
16 | return user.toOpenIdProfile((token.scopes || []) as Scopes[]);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/openid/controllers/well-known.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get } from '@nestjs/common';
2 | import { OpenIdService } from '../services';
3 | import { JwtService } from '@app/lib/jwt';
4 |
5 | @Controller('.well-known')
6 | export class WellKnownController {
7 | constructor(
8 | private readonly openIdService: OpenIdService,
9 | private readonly jwtService: JwtService,
10 | ) {}
11 |
12 | @Get('openid-configuration')
13 | getOpenIdConfig() {
14 | return this.openIdService.getConfig();
15 | }
16 |
17 | @Get('jwks.json')
18 | getJwks() {
19 | return this.jwtService.jwks(undefined, 'public');
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/openid/index.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Davide-Gheri/nestjs-oauth2/3bc3eb9f2b20d3ded242d3ac4e48ef594689cb0c/src/apps/oauth2/modules/openid/index.ts
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/openid/open-id-config.ts:
--------------------------------------------------------------------------------
1 | import { GrantTypes, ResponseModes, ResponseTypes, Scopes, TokenAuthMethod } from '@app/modules/oauth2/constants';
2 |
3 | export class OpenIdConfig {
4 | private readonly response_types_supported: ResponseTypes[] = Object.values(ResponseTypes);
5 | private readonly grant_types_supported: GrantTypes[] = Object.values(GrantTypes);
6 | private readonly response_modes_supported: ResponseModes[] = Object.values(ResponseModes);
7 | private readonly scopes_supported: Scopes[] = Object.values(Scopes);
8 | private readonly token_endpoint_auth_methods_supported: TokenAuthMethod[] = Object.values(TokenAuthMethod);
9 | private readonly subject_types_supported: string[] = ['public'];
10 |
11 | issuer: string;
12 | authorization_endpoint: string;
13 | registration_endpoint: string;
14 | token_endpoint: string;
15 | jwks_uri: string;
16 | userinfo_endpoint: string;
17 | revocation_endpoint: string;
18 | introspection_endpoint: string;
19 |
20 | constructor(baseUrl: string) {
21 | this.issuer = baseUrl;
22 | this.authorization_endpoint = new URL('/oauth2/authorize', baseUrl).toString();
23 | this.token_endpoint = new URL('/oauth2/token', baseUrl).toString();
24 | this.introspection_endpoint = new URL('/oauth2/introspect', baseUrl).toString();
25 | this.revocation_endpoint = new URL('/oauth2/revoke', baseUrl).toString();
26 |
27 | this.registration_endpoint = new URL('/clients', baseUrl).toString();
28 | this.jwks_uri = new URL('/.well-known/jwks.json', baseUrl).toString();
29 | this.userinfo_endpoint = new URL('/userinfo', baseUrl).toString();
30 | }
31 |
32 | toJson() {
33 | return JSON.stringify(this);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/openid/open-id.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { ConfigModule } from '@nestjs/config';
3 | import { OpenIdService } from './services';
4 | import { UserInfoController, WellKnownController } from './controllers';
5 | import { JwtModule } from '@app/lib/jwt';
6 | import { AuthModule } from '@app/modules/auth';
7 |
8 | @Module({
9 | imports: [
10 | ConfigModule,
11 | AuthModule,
12 | JwtModule,
13 | ],
14 | providers: [
15 | OpenIdService,
16 | ],
17 | controllers: [
18 | WellKnownController,
19 | UserInfoController,
20 | ],
21 | })
22 | export class OpenIdModule {}
23 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/openid/services/index.ts:
--------------------------------------------------------------------------------
1 | export * from './open-id.service';
2 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/openid/services/open-id.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { ConfigService } from '@nestjs/config';
3 | import { OpenIdConfig } from '../open-id-config';
4 |
5 | @Injectable()
6 | export class OpenIdService {
7 | constructor(
8 | private readonly config: ConfigService,
9 | ) {}
10 |
11 | getConfig() {
12 | const appUrl = this.config.get('app.appUrl');
13 | const openIdConfig = new OpenIdConfig(appUrl);
14 |
15 | return openIdConfig;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/user-api/controllers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './user-api.controller';
2 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/user-api/controllers/user-api.controller.ts:
--------------------------------------------------------------------------------
1 | import { BadRequestException, Controller, Get, Param, Query, UseGuards } from '@nestjs/common';
2 | import { UserService } from '@app/modules/user';
3 | import { AccessToken, JwtGuard, Scope, ScopeGuard } from '@app/modules/auth';
4 | import { AccessTokenJwtPayload } from '@app/modules/oauth2/interfaces';
5 | import { ApiScopes } from '@app/modules/oauth2/constants';
6 |
7 | @UseGuards(JwtGuard, ScopeGuard)
8 | @Controller('api/users')
9 | export class UserApiController {
10 | constructor(
11 | private readonly userService: UserService,
12 | ) {}
13 |
14 | @Scope(ApiScopes.users_profile, ApiScopes.users_email)
15 | @Get()
16 | async getUsers(
17 | @Query('ids') ids: string[],
18 | @AccessToken() token: AccessTokenJwtPayload,
19 | ) {
20 | if (!ids) {
21 | throw new BadRequestException('"ids" query parameter is required');
22 | }
23 | return this.userService.repository.findByIds(ids)
24 | .then(users => users.map(u => u.toApiProfile(token.scopes as any)))
25 | .catch(err => {
26 | throw new BadRequestException(err.message);
27 | })
28 | }
29 |
30 | @Scope(ApiScopes.users_profile, ApiScopes.users_email)
31 | @Get(':id')
32 | async getUser(
33 | @Param('id') id: string,
34 | @AccessToken() token: AccessTokenJwtPayload,
35 | ) {
36 | try {
37 | const user = await this.userService.repository.findOneOrFail(id);
38 | return user.toApiProfile(token.scopes as any);
39 | } catch (e) {
40 | return null;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/user-api/user-api.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { ConfigModule } from '@nestjs/config';
3 | import { AuthModule } from '@app/modules/auth';
4 | import { UserModule } from '@app/modules/user';
5 | import { UserApiController } from '@app/modules/user-api/controllers';
6 |
7 | @Module({
8 | imports: [
9 | ConfigModule,
10 | AuthModule,
11 | UserModule,
12 | ],
13 | controllers: [
14 | UserApiController,
15 | ],
16 | })
17 | export class UserApiModule {}
18 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/user/controllers/email.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get, Param, Redirect, UseFilters, UseGuards } from '@nestjs/common';
2 | import { SignedGuard } from '@app/lib/sign';
3 | import { AuthenticatedGuard } from '@app/modules/auth/guards';
4 | import { ForbiddenExceptionFilter } from '@app/modules/auth/filters';
5 | import { RegisterService } from '../services';
6 | import { CurrentUser } from '@app/modules/auth/decorators';
7 | import { User } from '@app/entities';
8 |
9 | @UseFilters(ForbiddenExceptionFilter)
10 | @Controller('email')
11 | export class EmailController {
12 | constructor(
13 | private readonly registerService: RegisterService,
14 | ) {}
15 |
16 | @UseGuards(SignedGuard, AuthenticatedGuard)
17 | @Redirect('/')
18 | @Get('confirm/:idHash/:emailHash')
19 | async verifyEmail(
20 | @CurrentUser() user: User,
21 | @Param('idHash') idHash: string,
22 | @Param('emailHash') emailHash: string,
23 | ) {
24 | await this.registerService.verifyEmail(user, idHash, emailHash);
25 | return null;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/user/controllers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './email.controller';
2 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/user/index.ts:
--------------------------------------------------------------------------------
1 | export * from './user.module';
2 | export * from './services';
3 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/user/services/index.ts:
--------------------------------------------------------------------------------
1 | export * from './user.service';
2 | export * from './register.service';
3 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/user/services/password.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import estimator from 'zxcvbn';
3 | import { ConfigService } from '@nestjs/config';
4 |
5 | @Injectable()
6 | export class PasswordService {
7 | constructor(
8 | private readonly config: ConfigService,
9 | ) {}
10 |
11 | checkPasswordStrength(pass: string) {
12 | const result = estimator(pass);
13 | if (result.score < this.config.get('app.security.minPasswordScore')) {
14 | return result.feedback.warning || result.feedback.suggestions[0];
15 | }
16 | return null;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/apps/oauth2/modules/user/test.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get } from '@nestjs/common';
2 | import { InjectRepository } from '@nestjs/typeorm';
3 | import { User } from '@app/entities';
4 | import { Repository } from 'typeorm';
5 | import { RegisterService } from './services';
6 |
7 | @Controller('test')
8 | export class TestController {
9 | constructor(
10 | @InjectRepository(User)
11 | private userRepo: Repository Welcome {{nickname}}
7 | Click the button below to activate your account
8 |
11 | {{link}}
12 |