REFACTOR: openid module

This commit is contained in:
marcos-silva-rodrigues
2025-04-03 07:46:16 -03:00
parent f1345472b5
commit 4c94a51a9d
7 changed files with 171 additions and 134 deletions
-51
View File
@@ -53,7 +53,6 @@ import jwt from 'jsonwebtoken';
import { LanguageEnum } from 'src/utils/languages.enum';
import { Language } from 'src/decorators/language.decorator';
import { ApiInternalOnlyEndpoint } from 'src/decorators/swagger.decorator';
import { CreatedIdentityProvider, CreateIdentityProvider } from './dtos/openid';
@ApiTags('Auth')
@ApiHeaders([{ name: 'dadosfera-lang', enum: LanguageEnum, required: false }])
@@ -111,56 +110,6 @@ export class AuthController {
return this.authClient.refreshAccessToken({ refreshToken }, metadata);
}
@Post('/idp')
@HttpCode(HttpStatus.OK)
@ApiOkResponse({ type: CreatedIdentityProvider })
async addIdentityProvider(
@User() user: RequestUser,
@Body() body: IdProvider,
@Language() language: LanguageEnum,
) {
this.logger.info('/auth - RefreshAccessToken');
const metadata = PackTheMetadata({
customer_id: user.customer_id,
language,
});
return this.authClient.createIdentityProvider(body, metadata);
}
@Get('/idp/:name')
@HttpCode(HttpStatus.OK)
@Redirect()
async loginIdp(
@Body() body: { name: string },
@Req() req: Request,
) {
this.logger.info('/auth - RefreshAccessToken');
const redirectUrl = this.authClient.loginIdp(body.name, req);
return {
url: redirectUrl,
};
}
@Get('/idp/:name/callback')
@HttpCode(HttpStatus.OK)
@ApiOkResponse({ type: AuthRefreshAccessTokenRes })
@Redirect()
@RequireAllPermissions(PERMISSIONS_GROUPS.SNOWFLAKE.permissions.OPEN)
async callbackIdp(
@Param('name') name: string,
@Req() req: Request,
) {
this.logger.info('/auth - RefreshAccessToken');
const redirectUrl = this.authClient.authorizeIdp(name, req);
return {
url: redirectUrl,
};
}
@ApiInternalOnlyEndpoint()
@Post('/sso/snowflake')
@RequireAllPermissions(PERMISSIONS_GROUPS.SNOWFLAKE.permissions.OPEN)
+1 -82
View File
@@ -17,12 +17,10 @@ import {
AuthResetPasswordRequest,
AuthVerifyResetPasswordCodeRequest,
AuthConfirmResetPasswordRequest,
IdProvider,
} from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
import { DucClient } from '../duc/client.config';
import { Metadata } from '@grpc/grpc-js';
import * as client from 'openid-client'
import { Request } from 'express';
@Injectable()
export class AuthClientService implements OnModuleInit {
@@ -180,84 +178,5 @@ export class AuthClientService implements OnModuleInit {
);
}
createIdentityProvider(body: IdProvider, metadata: Metadata) {
return lastValueFrom(
this.identityProviderService.CreateIdentityProvider(body, metadata),
);
}
async loginIdp(name: string, req: Request) {
const idp = await lastValueFrom(
this.identityProviderService.FindIdentityProvider({ name }),
);
const config: client.Configuration = await client.discovery(
new URL(idp.issueUrl),
idp.clientId,
idp.clientSecret,
)
const redirect_uri = `http://localhost:3000/auth/idp/${name}/callback`;
const scope = 'openid email';
const code_verifier: string = client.randomPKCECodeVerifier()
const code_challenge: string =
await client.calculatePKCECodeChallenge(code_verifier)
let state: string;
const parameters: Record<string, string> = {
redirect_uri,
scope,
code_challenge,
code_challenge_method: 'S256',
}
req.session.code_verifier = code_verifier;
if (!config.serverMetadata().supportsPKCE()) {
/**
* We cannot be sure the server supports PKCE so we're going to use state too.
* Use of PKCE is backwards compatible even if the AS doesn't support it which
* is why we're using it regardless. Like PKCE, random state must be generated
* for every redirect to the authorization_endpoint.
*/
state = client.randomState()
parameters.state = state
req.session.state = state;
}
const authUrl = client.buildAuthorizationUrl(config, parameters);
return authUrl;
}
async authorizeIdp(name: string, req: Request) {
const code_verifier_session = req.session.code_verifier;
const state_session = req.session.state;
const url = new URL("http://localhost:3000" + req.url);
const idp = await lastValueFrom(
this.identityProviderService.FindIdentityProvider({ name }),
);
const config: client.Configuration = await client.discovery(
new URL(idp.issueUrl),
idp.clientId,
idp.clientSecret,
)
const tokens: client.TokenEndpointResponse = await client.authorizationCodeGrant(
config,
url,
{
pkceCodeVerifier: code_verifier_session,
expectedState: state_session,
},
)
delete req.session.code_verifier;
delete req.session.state;
console.log('Token Endpoint Response', tokens)
return tokens;
}
}
-16
View File
@@ -1,16 +0,0 @@
import { ApiProperty } from "@nestjs/swagger";
export class CreatedIdentityProvider {
@ApiProperty()
name: string;
@ApiProperty()
clientId: string;
@ApiProperty()
clientSecret: string;
@ApiProperty()
issueUrl: string;
}