Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge Feat/mono repo in main #26

Merged
merged 3 commits into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion apps/authentication/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import { AppService } from './app.service';
import { AuthModule } from './auth/auth.module';
import { TerminusModule } from '@nestjs/terminus';
import { HttpModule } from '@nestjs/axios';
import { UserModule } from './user/user.module';
@Module({
imports: [
AuthModule,
UserModule,
ConfigModule.forRoot({
isGlobal: true,
}),
Expand All @@ -17,4 +19,4 @@ import { HttpModule } from '@nestjs/axios';
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
export class AppModule { }
34 changes: 30 additions & 4 deletions apps/authentication/src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@
import { HttpService } from '@nestjs/axios';
import { Body, Controller, Post, UseGuards } from '@nestjs/common';
import { Body, Controller, Get, Param, Patch, Post, Req, Request, UseGuards } from '@nestjs/common';
import { parseJwt } from '../helpers/decodeToken';
import { JwtAuthGuard } from './auth-jwt.guard';
import { AuthService } from './auth.service';
import { AuthDto } from './dto/auth.dto';
import { CA } from './dto/ca.dto';

@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) { }

@Post()
@Post('/verify')
@UseGuards(JwtAuthGuard)
hadleAuth(@Body() body: AuthDto) {
return this.authService.handleAuth(body);
hadleAuth(@Body() body: AuthDto, @Request() req) {
return this.authService.handleAuth(body, req?.headers?.authorization);
}

@Post('/register')
@UseGuards(JwtAuthGuard)
handleRegister(@Body() ca: CA, @Request() req) {
return this.authService.handleRegister(ca, req?.headers?.authorization);
}

@Patch('/:caId/accept')
@UseGuards(JwtAuthGuard)
handleAccept(@Param('caId') caId: string, @Request() req) {
return this.authService.handleConsent(caId, 'accept', req?.headers?.authorization);
}

@Patch('/:caId/reject')
@UseGuards(JwtAuthGuard)
handleReject(@Param('caId') caId: string, @Request() req) {
return this.authService.handleConsent(caId, 'reject', req?.headers?.authorization);
}

@Patch('/:caId/revoke')
@UseGuards(JwtAuthGuard)
handleRevoke(@Param('caId') caId: string, @Request() req) {
return this.authService.handleConsent(caId, 'revoke', req?.headers?.authorization);
}
}
221 changes: 123 additions & 98 deletions apps/authentication/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,129 +1,154 @@
import { HttpService } from '@nestjs/axios';
import { Injectable, InternalServerErrorException } from '@nestjs/common';
import { HttpException, HttpStatus, Injectable, InternalServerErrorException } from '@nestjs/common';
import { lastValueFrom, map } from 'rxjs';
import { parseJwt } from '../helpers/decodeToken';
import { AuthDto } from './dto/auth.dto';
import { CA } from './dto/ca.dto';

@Injectable()
export class AuthService {
constructor(private readonly httpService: HttpService) { }

async handleAuth(authDTO: AuthDto) {
//TODO: add consent artifact processin
async handleAuth(authDTO: AuthDto, token: string) {
try {
// const myHeaders = new Headers();
// myHeaders.append('Content-Type', 'application/json');

// var raw = JSON.stringify({
// "id": "927d81cf-77ee-4528-94d1-2d98a2595740",
// "caId": "036232e5-0ac7-4863-bad2-c70e70ef2d2f",
// "consent_artifact": {
// "id": "036232e5-0ac7-4863-bad2-c70e70ef2d2f",
// "log": {
// "consent_use": {
// "url": "https://sample-log/api/v1/log"
// },
// "data_access": {
// "url": "https://sample-log/api/v1/log"
// }
// },
// "data": "<Valid superset GraphQL query of consented data>",
// "user": {
// "id": "[email protected]"
// },
// "proof": {
// "jws": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjAzNjIzMmU1LTBhYzctNDg2My1iYWQyLWM3MGU3MGVmMmQyZiIsImxvZyI6eyJjb25zZW50X3VzZSI6eyJ1cmwiOiJodHRwczovL3NhbXBsZS1sb2cvYXBpL3YxL2xvZyJ9LCJkYXRhX2FjY2VzcyI6eyJ1cmwiOiJodHRwczovL3NhbXBsZS1sb2cvYXBpL3YxL2xvZyJ9fSwiZGF0YSI6IjxWYWxpZCBzdXBlcnNldCBHcmFwaFFMIHF1ZXJ5IG9mIGNvbnNlbnRlZCBkYXRhPiIsInVzZXIiOnsiaWQiOiJmYXJtZXItMUBnbWFpbC5jb20ifSwiY3JlYXRlZCI6IllZWVktTU0tRERUaGg6bW06c3Nabi5uIiwiZXhwaXJlcyI6IllZWVktTU0tRERUaGg6bW06c3Nabi5uIiwicHVycG9zZSI6IiIsInJldm9rZXIiOnsiaWQiOiJkaWQ6dXNlcjoxMjMiLCJ1cmwiOiJodHRwczovL3NhbXBsZS1yZXZva2VyL2FwaS92MS9yZXZva2UifSwiY29uc3VtZXIiOnsiaWQiOiJkaWQ6Y29uc3VtZXI6MTIzIiwidXJsIjoiaHR0cHM6Ly9zYW1wbGUtY29uc3VtZXIvYXBpL3YxL2NvbnN1bWUifSwicHJvdmlkZXIiOnsiaWQiOiJkaWQ6cHJvaWRlcjoxMjMiLCJ1cmwiOiJodHRwczovL3NhbXBsZS1jb25zdW1lci9hcGkvdjEifSwiY29sbGVjdG9yIjp7ImlkIjoiZGlkOmNvbGxlY3RvcjoxMjMiLCJ1cmwiOiJodHRwczovL2ExMTItMTAzLTIxMi0xNDctMTMwLmluLm5ncm9rLmlvIn0sImZyZXF1ZW5jeSI6eyJ0dGwiOjUsImxpbWl0IjoyfSwicmV2b2NhYmxlIjpmYWxzZSwic2lnbmF0dXJlIjoiIiwidXNlcl9zaWduIjoiIiwiY29sbGVjdG9yX3NpZ24iOiIiLCJ0b3RhbF9xdWVyaWVzX2FsbG93ZWQiOjEwLCJpYXQiOjE2Njk5Mzk1OTYsImV4cCI6MTY3MDM3MTU5NiwiYXVkIjoiZGlkOmNvbnN1bWVyOjEyMyIsImlzcyI6ImNvbnNlbnQtbWFuYWdlciIsInN1YiI6ImZhcm1lci0xQGdtYWlsLmNvbSJ9.UNyoXDgMxbIVaBoK0J7OBX7ybUlZNx309KdbetoeJLqGaZbfFav3rZyoPnQNpQyAFHp8MaNczzlI0JlTSStqJl0E-Z1oGK6M-hREE1261zSxZMAueIgpNEVpNiUH4gRhleTBaKPH0EoZT27ORqZmULb2UMDfw1Gy9RuH7cHzJYdBDmi5fkePhsN8T3Z03OgnUWHHPTxwS4_szS3fLGMmJvUTyrK-UBwkMslajdoWN3vcp4MERv60F8yIk7GqGGkNHEiaLe_g_Zi73KOKDbdWOLapQiO8kwpAyblu6maNF8w4VdIft4zFT4SiloJWxeYNZUeT0ROHscTbdLOaTCn-Ag",
// "type": "RS256",
// "created": "12/2/2022, 12:06:36 AM",
// "proofPurpose": "jwtVerify",
// "verificationMethod": "https://auth.konnect.samagra.io/.well-known/jwks"
// },
// "created": "YYYY-MM-DDThh:mm:ssZn.n",
// "expires": "YYYY-MM-DDThh:mm:ssZn.n",
// "purpose": "",
// "revoker": {
// "id": "did:user:123",
// "url": "https://sample-revoker/api/v1/revoke"
// },
// "consumer": {
// "id": "did:consumer:123",
// "url": "https://sample-consumer/api/v1/consume"
// },
// "provider": {
// "id": "did:proider:123",
// "url": "https://sample-consumer/api/v1"
// },
// "collector": {
// "id": "did:collector:123",
// "url": "https://a112-103-212-147-130.in.ngrok.io"
// },
// "frequency": {
// "ttl": 5,
// "limit": 2
// },
// "revocable": false,
// "signature": "",
// "user_sign": "",
// "collector_sign": "",
// "total_queries_allowed": 10
// },
// "userId": "[email protected]",
// "state": "ACCEPT",
// "created_at": "2022-12-02T00:05:46.090Z",
// "created_by": "API",
// "updated_at": "2022-12-02T00:05:46.090Z",
// "updated_by": null,
// "webhook_url": "https://sample-consumer/api/v1/consume",
// "total_attempts": 0
// });
// const reqOptions = {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json',
// },
// redirect: 'follow',
// };
// fetch('https://api.consent-manager.konnect.samagra.io/verify', reqOptions)
// .then((response) => response.text())
// .then((result) => console.log(result))
// .catch((error) => {
// console.log('error', error);
// throw new InternalServerErrorException(error);
// });

// this.httpService.post(
// 'https://api.consent-manager.konnect.samagra.io/verify',
// raw,
// reqOptions,
// );
const tokenPayload = parseJwt(token?.split(" ")?.[1]);
const userEmail = tokenPayload.email;

const permissionRes = await lastValueFrom(
this.httpService
.post(
`${process.env.AUTH_SELF_URL}/user/checkPermission`,
{
caId: authDTO.caId,
userEmail
}, { headers: { Authorization: token } }
)
.pipe(map((response) => response.data)),
);

if (permissionRes) {
const caRes = await lastValueFrom(
this.httpService
.get(
`${process.env.CONSENT_MANAGER_URI}/${authDTO.caId}/verify`
)
.pipe(map((response) => response.data)),
);
if (!caRes.caId) {
return "An error occured while verifying Consent Artifact";
}

console.log("CA RES---->", caRes)

const responseData = await lastValueFrom(
this.httpService
.post(
process.env.LINK_TO_AUTHORIZATION_SERVICE,
{ consentArtifact: caRes, gql: authDTO.gql }
)
.pipe(map((response) => response.data)),
);

return responseData;

} else {
throw new HttpException({
status: HttpStatus.FORBIDDEN,
error: `You can only access or modify Consents which are associated with you.`,
}, HttpStatus.FORBIDDEN);
}
} catch (err) {
console.log('err: ', err);
if (err?.response?.data || err?.response)
return err?.response?.data || err?.response;
throw new InternalServerErrorException();
}
}

handleRegister = async (data: CA, token: string) => {
try {
const tokenPayload = parseJwt(token?.split(" ")?.[1]);
const userEmail = tokenPayload.email;
let ca = data.consentArtifact
const caRes = await lastValueFrom(
this.httpService
.get(
`${process.env.CONSENT_MANAGER_URI}/${authDTO.caId}/verify`
.post(
`${process.env.CONSENT_MANAGER_URI}/register`,
{ ca }
)
.pipe(map((response) => response.data)),
);
if (!caRes.caId) {
return "An error occured while verifying Consent Artifact";
return "An error occured while creating Consent Artifact";
}

console.log("CA RES---->", caRes)

const responseData = await lastValueFrom(
// Adding registered CA to user's data on FA.
const userRes = await lastValueFrom(
this.httpService
.post(
process.env.LINK_TO_AUTHORIZATION_SERVICE,
{ consentArtifact: caRes, gql: authDTO.gql }
.patch(
`${process.env.AUTH_SELF_URL}/user/updateUserCaIds`,
{
caId: caRes.caId,
userEmail
}, { headers: { Authorization: token } }
)
.pipe(map((response) => response.data)),
);

return responseData;
return caRes;

} catch (err) {
console.log('err: ', err);
if (err?.response?.data)
return err?.response?.data;
throw new InternalServerErrorException();
}
}

handleConsent = async (caId: string, type: string, token: string) => {
try {
const tokenPayload = parseJwt(token?.split(" ")?.[1]);
const userEmail = tokenPayload.email;

const permissionRes = await lastValueFrom(
this.httpService
.post(
`${process.env.AUTH_SELF_URL}/user/checkPermission`,
{
caId,
userEmail
}, { headers: { Authorization: token } }
)
.pipe(map((response) => response.data)),
);

if (permissionRes) {
const caRes = await lastValueFrom(
this.httpService
.patch(
`${process.env.CONSENT_MANAGER_URI}/${caId}/${type}`
)
.pipe(map((response) => response.data)),
);

if (!caRes.caId) {
return "An error occured while performing the requested action";
}

return caRes;

} else {
throw new HttpException({
status: HttpStatus.FORBIDDEN,
error: `You can only access or modify Consents which are associated with you.`,
}, HttpStatus.FORBIDDEN);
}

} catch (err) {
console.log('err: ', err);
if (err?.response)
return err?.response;
throw new InternalServerErrorException;
}
}
}
3 changes: 1 addition & 2 deletions apps/authentication/src/auth/dto/auth.dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export class AuthDto {
caId: string
gql: string;
token: string;
gql: string
}
3 changes: 3 additions & 0 deletions apps/authentication/src/auth/dto/ca.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class CA {
consentArtifact: JSON
}
10 changes: 10 additions & 0 deletions apps/authentication/src/helpers/decodeToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { JwtPayload } from "jsonwebtoken";

export function parseJwt(signedJwtAccessToken: string) {
if (!signedJwtAccessToken) return null;
const base64Payload = signedJwtAccessToken.split('.')[1];
const payloadBuffer = Buffer.from(base64Payload, 'base64');
const updatedJwtPayload: JwtPayload = JSON.parse(payloadBuffer.toString()) as JwtPayload;
const expires = updatedJwtPayload.exp;
return updatedJwtPayload
}
27 changes: 27 additions & 0 deletions apps/authentication/src/user/user.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Body, Controller, Get, Param, Patch, Post, Request } from '@nestjs/common';
import { UserService } from './user.service';
import { ConfigService } from '@nestjs/config';
import { ApiOperation, ApiResponse } from '@nestjs/swagger';

@Controller('user')
export class UserController {
constructor(
private readonly userService: UserService,
private configService: ConfigService,
) { }

@Get('/:email')
getUserDetails(@Param('email') email: string) {
return this.userService.getUserDetails(email);
}

@Patch('/updateUserCaIds')
updateUserCaIds(@Body() data, @Request() req) {
return this.userService.updateUserCaIds(data, req?.headers?.authorization)
}

@Post('/checkPermission')
checkPermission(@Body() data, @Request() req) {
return this.userService.checkPermission(data, req?.headers?.authorization)
}
}
18 changes: 18 additions & 0 deletions apps/authentication/src/user/user.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { UserController } from './user.controller';
import { UserService } from './user.service';
import { TerminusModule } from '@nestjs/terminus';
import { HttpModule } from '@nestjs/axios';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
TerminusModule,
HttpModule,
],
controllers: [UserController],
providers: [UserService],
})
export class UserModule { }
Loading