mirror of
https://github.com/dadosfera/maestro.git
synced 2026-11-12 23:49:09 +00:00
186 lines
5.9 KiB
TypeScript
186 lines
5.9 KiB
TypeScript
import {
|
|
BadRequestException,
|
|
Inject,
|
|
Injectable,
|
|
OnModuleInit,
|
|
} from '@nestjs/common';
|
|
import { DucClient } from '../duc/client.config';
|
|
import { ClientGrpc } from '@nestjs/microservices';
|
|
import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Duc';
|
|
import { IdentityProviderProtoService } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/write-service';
|
|
import { lastValueFrom } from 'rxjs';
|
|
import { IdentityProviderRequest } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
|
|
import { Metadata } from '@grpc/grpc-js';
|
|
import { Issuer, generators } from 'openid-client';
|
|
import { SsoSignInDto } from './dto/sso-signin.dto';
|
|
import { CacheService } from 'src/services/cache.service';
|
|
import { CreateIdentityProvider } from './dto/identity-provider.dto';
|
|
import DadosferaLogger from '@dadosfera/dadosfera-logs';
|
|
|
|
@Injectable()
|
|
export class IdentityProviderService implements OnModuleInit {
|
|
private logger: DadosferaLogger;
|
|
private identityProviderService: IdentityProviderProtoService;
|
|
constructor(
|
|
@Inject(DucClient.name) private readonly grpcClient: ClientGrpc,
|
|
private readonly cacheService: CacheService<SsoSignInDto>,
|
|
@Inject(DadosferaLogger)
|
|
private dadosferaLoggger: DadosferaLogger
|
|
) {
|
|
this.logger = dadosferaLoggger.logger;
|
|
}
|
|
|
|
onModuleInit() {
|
|
this.identityProviderService =
|
|
this.grpcClient.getService<IdentityProviderProtoService>(
|
|
ProtoServices.IdentityProviderProtoService,
|
|
);
|
|
}
|
|
|
|
async create(body: IdentityProviderRequest, metadata: Metadata) {
|
|
this.logger.info("Call IdentityProvider GRPC Create")
|
|
return await lastValueFrom(
|
|
this.identityProviderService.Create(body, metadata),
|
|
);
|
|
}
|
|
|
|
async getList(metadata: Metadata) {
|
|
this.logger.info("Call IdentityProvider GRPC GetList")
|
|
return await lastValueFrom(
|
|
this.identityProviderService.GetList({}, metadata),
|
|
);
|
|
}
|
|
|
|
async loginIdentityProvider(id: string, callbackUrl: string) {
|
|
this.logger.info("Call IdentityProvider GRPC FindIdentityProvider with: " + id);
|
|
const idp = await lastValueFrom(
|
|
this.identityProviderService.FindIdentityProvider({ id }),
|
|
);
|
|
|
|
this.logger.info("Discovery issueURL: " + idp.issuerUrl)
|
|
const issuer = await Issuer.discover(idp.issuerUrl);
|
|
const client = new issuer.Client({
|
|
client_id: idp.clientId,
|
|
client_secret: idp.clientSecret,
|
|
redirect_uris: idp.redirectUrls,
|
|
response_types: ['code'],
|
|
});
|
|
|
|
this.logger.info("Generate Challenge")
|
|
const code_verifier: string = generators.codeVerifier();
|
|
const code_challenge: string = generators.codeChallenge(code_verifier);
|
|
|
|
this.logger.info("Generate State")
|
|
const state = generators.state();
|
|
|
|
this.logger.info("Generate Nonce")
|
|
const nonce = generators.nonce();
|
|
|
|
// Using state because it is returned in the callback
|
|
// and we can use it to retrieve the code_verifier and nonce
|
|
this.logger.info("Save Login parameters in redis")
|
|
await this.cacheService.set(state, {
|
|
codeVerifier: code_verifier,
|
|
nonce,
|
|
id: idp.id,
|
|
state,
|
|
clientId: idp.clientId,
|
|
clientSecret: idp.clientSecret,
|
|
issuerUrl: idp.issuerUrl,
|
|
redirectUrls: idp.redirectUrls,
|
|
});
|
|
|
|
this.logger.info("Generate Authorization URL")
|
|
const url = client.authorizationUrl({
|
|
scope: 'openid email',
|
|
response_type: 'code',
|
|
code_challenge,
|
|
code_challenge_method: 'S256',
|
|
state,
|
|
nonce,
|
|
redirect_uri: callbackUrl,
|
|
});
|
|
const idpUrl = url + '&identity_provider=' + idp.name;
|
|
this.logger.info(idpUrl)
|
|
return idpUrl;
|
|
}
|
|
|
|
async getTokenByIdp(code: string, state: string, callbackUrl: string) {
|
|
this.logger.info("Get login parameters in redis")
|
|
const ssoSign = await this.cacheService.get(state);
|
|
|
|
if (!ssoSign) {
|
|
this.logger.info("Login Parameters Not Found")
|
|
throw new BadRequestException('SSO sign-in is expired or not found');
|
|
}
|
|
|
|
this.logger.info("Discovery Issue URL: " + ssoSign.issuerUrl)
|
|
const issuer = await Issuer.discover(ssoSign.issuerUrl);
|
|
const client = new issuer.Client({
|
|
client_id: ssoSign.clientId,
|
|
client_secret: ssoSign.clientSecret,
|
|
redirect_uris: ssoSign.redirectUrls,
|
|
});
|
|
|
|
const params = client.callbackParams(
|
|
`${callbackUrl}?code=${code}&state=${state}`,
|
|
);
|
|
try {
|
|
|
|
this.logger.info("Get Token Set");
|
|
const tokenSet = await client.callback(callbackUrl, params, {
|
|
nonce: ssoSign.nonce,
|
|
code_verifier: ssoSign.codeVerifier,
|
|
state: ssoSign.state
|
|
});
|
|
|
|
this.logger.info("Delete parameters in redis");
|
|
await this.cacheService.delete(ssoSign.state);
|
|
|
|
this.logger.info("Call IdentityProvider GRPC SignInUser");
|
|
return await lastValueFrom(
|
|
this.identityProviderService.SignInUser({
|
|
accessToken: tokenSet.access_token,
|
|
idToken: tokenSet.id_token,
|
|
refreshToken: tokenSet.refresh_token,
|
|
id: ssoSign.id,
|
|
}),
|
|
);
|
|
} catch (error) {
|
|
this.logger.error(error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async deleteIdentityProvider(id: string, metadata: Metadata) {
|
|
this.logger.info("Call IdentityProvider GRPC Delete with: " + id)
|
|
return await lastValueFrom(
|
|
this.identityProviderService.DeleteIdentityProvider({ id }, metadata),
|
|
);
|
|
}
|
|
|
|
async updateIdentityProviders(
|
|
id: string,
|
|
body: CreateIdentityProvider,
|
|
metadata: Metadata,
|
|
) {
|
|
this.logger.info("Call IdentityProvider GRPC Update with: " + id)
|
|
return await lastValueFrom(
|
|
this.identityProviderService.UpdateIdentityProvider(
|
|
{
|
|
id,
|
|
...body,
|
|
},
|
|
metadata,
|
|
),
|
|
);
|
|
}
|
|
|
|
async identityProvidersLinksPerDomain(frontDomain: string) {
|
|
this.logger.info("Call IdentityProvider GRPC LinksPerDomain with: " + frontDomain)
|
|
return await lastValueFrom(
|
|
this.identityProviderService.GetProviderLinksFromDomain({ frontDomain }),
|
|
);
|
|
}
|
|
}
|