Commit 6806919d authored by Hidde-Jan Jongsma's avatar Hidde-Jan Jongsma

Add creating requests from jwt tokens

parent ddd5d1ca
...@@ -4,6 +4,7 @@ import { ...@@ -4,6 +4,7 @@ import {
Column, Column,
OneToOne, OneToOne,
OneToMany, OneToMany,
Generated,
} from 'typeorm'; } from 'typeorm';
import { randomBytes } from 'crypto'; import { randomBytes } from 'crypto';
import { JolocomWallet } from '../connectors/jolocom/jolocom-wallet.entity'; import { JolocomWallet } from '../connectors/jolocom/jolocom-wallet.entity';
...@@ -23,6 +24,10 @@ export class Organization { ...@@ -23,6 +24,10 @@ export class Organization {
@Column() @Column()
sharedSecret: string; sharedSecret: string;
@Column()
@Generated('uuid')
uuid: string;
@OneToOne( @OneToOne(
() => JolocomWallet, () => JolocomWallet,
wallet => wallet.organization, wallet => wallet.organization,
......
...@@ -10,5 +10,6 @@ import { ConnectorsModule } from 'src/connectors/connectors.module'; ...@@ -10,5 +10,6 @@ import { ConnectorsModule } from 'src/connectors/connectors.module';
imports: [TypeOrmModule.forFeature([Organization]), ConnectorsModule], imports: [TypeOrmModule.forFeature([Organization]), ConnectorsModule],
controllers: [OrganizationsController], controllers: [OrganizationsController],
providers: [OrganizationsService], providers: [OrganizationsService],
exports: [OrganizationsService],
}) })
export class OrganizationsModule {} export class OrganizationsModule {}
...@@ -22,8 +22,9 @@ export class OrganizationsService { ...@@ -22,8 +22,9 @@ export class OrganizationsService {
} }
async findByIdentifier(uuid: string) { async findByIdentifier(uuid: string) {
const results = await this.organizationsRepository.find({ take: 1 }); return this.organizationsRepository.findOne({
return results[0]; uuid,
});
} }
async createFromName(name: string) { async createFromName(name: string) {
...@@ -32,7 +33,10 @@ export class OrganizationsService { ...@@ -32,7 +33,10 @@ export class OrganizationsService {
organization.name = name; organization.name = name;
organization.sharedSecret = Organization.randomSecret(); organization.sharedSecret = Organization.randomSecret();
await this.organizationsRepository.save(organization); await this.organizationsRepository.save(organization);
// TODO: Move to queue if needed.
await this.connectorsService.registerOrganization(organization); await this.connectorsService.registerOrganization(organization);
this.logger.log(`Created organization (id: ${organization.id})`); this.logger.log(`Created organization (id: ${organization.id})`);
return organization; return organization;
} }
......
...@@ -43,8 +43,14 @@ export class CredentialIssueRequest implements CredentialRequest { ...@@ -43,8 +43,14 @@ export class CredentialIssueRequest implements CredentialRequest {
) )
requestor: Organization; requestor: Organization;
static requestType: 'credential-issue-request';
get requestId() { get requestId() {
return `credential-issue-request:${this.uuid}`; return `${CredentialIssueRequest.requestType}:${this.uuid}`;
}
get iss() {
return this.requestor?.uuid;
} }
get issuer() { get issuer() {
......
...@@ -2,6 +2,7 @@ import { Organization } from '../organizations/organization.entity'; ...@@ -2,6 +2,7 @@ import { Organization } from '../organizations/organization.entity';
export interface CredentialRequest { export interface CredentialRequest {
requestId: string; requestId: string;
iss: string;
type: string; type: string;
callbackUrl: string; callbackUrl: string;
requestor: Organization; requestor: Organization;
......
...@@ -35,8 +35,14 @@ export class CredentialVerifyRequest implements CredentialRequest { ...@@ -35,8 +35,14 @@ export class CredentialVerifyRequest implements CredentialRequest {
) )
requestor: Organization; requestor: Organization;
static requestType: 'credential-verify-request';
get requestId() { get requestId() {
return `credential-verify-request:${this.uuid}`; return `${CredentialVerifyRequest.requestType}:${this.uuid}`;
}
get iss() {
return this.requestor?.uuid;
} }
get verifier() { get verifier() {
......
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { RequestsService } from './requests.service'; import { RequestsService } from './requests.service';
import { OrganizationsModule } from '../organizations/organizations.module'; import { OrganizationsModule } from '../organizations/organizations.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { CredentialIssueRequest } from './credential-issue-request.entity';
import { CredentialVerifyRequest } from './credential-verify-request.entity';
@Module({ @Module({
imports: [OrganizationsModule], imports: [
TypeOrmModule.forFeature([CredentialIssueRequest, CredentialVerifyRequest]),
OrganizationsModule,
],
providers: [RequestsService], providers: [RequestsService],
exports: [RequestsService], exports: [RequestsService],
}) })
......
...@@ -11,6 +11,8 @@ import { ...@@ -11,6 +11,8 @@ import {
CredentialIssueRequest, CredentialIssueRequest,
CredentialIssueRequestData, CredentialIssueRequestData,
} from './credential-issue-request.entity'; } from './credential-issue-request.entity';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
export class InvalidRequestJWT extends Error {} export class InvalidRequestJWT extends Error {}
...@@ -18,7 +20,59 @@ const JWT_MAX_AGE = '300s'; ...@@ -18,7 +20,59 @@ const JWT_MAX_AGE = '300s';
@Injectable() @Injectable()
export class RequestsService { export class RequestsService {
constructor(private organizationsService: OrganizationsService) {} constructor(
private organizationsService: OrganizationsService,
@InjectRepository(CredentialIssueRequest)
private issueRequestRepository: Repository<CredentialIssueRequest>,
@InjectRepository(CredentialVerifyRequest)
private verifyRequestRepository: Repository<CredentialVerifyRequest>,
) {}
async findVerifyRequestByIdentifier(uuid: string) {
return this.verifyRequestRepository.findOne({ uuid });
}
async findIssueRequestByIdentifier(uuid: string) {
return this.issueRequestRepository.findOne({ uuid });
}
async findVerifyRequestByRequestId(requestId: string) {
const [type, uuid] = requestId.split(':');
if (type !== CredentialVerifyRequest.requestType || !uuid) {
return null;
}
return this.findVerifyRequestByIdentifier(uuid);
}
async findIssueRequestByRequestId(requestId: string) {
const [type, uuid] = requestId.split(':');
if (type !== CredentialIssueRequest.requestType || !uuid) {
return null;
}
return this.findIssueRequestByIdentifier(uuid);
}
async findRequestByRequestId(requestId: string) {
const [type, uuid] = requestId.split(':');
if (!type || !uuid) {
return null;
}
if (type === CredentialVerifyRequest.requestType) {
return this.findVerifyRequestByIdentifier(uuid);
}
if (type === CredentialIssueRequest.requestType) {
return this.findIssueRequestByIdentifier(uuid);
}
return null;
}
async decodeVerifyRequestToken(jwt: string) { async decodeVerifyRequestToken(jwt: string) {
const { request, requestor } = await this.decodeAndVerifyJwt< const { request, requestor } = await this.decodeAndVerifyJwt<
...@@ -31,8 +85,7 @@ export class RequestsService { ...@@ -31,8 +85,7 @@ export class RequestsService {
verifyRequest.type = request.type; verifyRequest.type = request.type;
verifyRequest.callbackUrl = request.callbackUrl; verifyRequest.callbackUrl = request.callbackUrl;
// TODO: Save to db await this.verifyRequestRepository.save(verifyRequest);
return verifyRequest; return verifyRequest;
} }
...@@ -48,8 +101,7 @@ export class RequestsService { ...@@ -48,8 +101,7 @@ export class RequestsService {
issueRequest.callbackUrl = request.callbackUrl; issueRequest.callbackUrl = request.callbackUrl;
issueRequest.data = request.data; issueRequest.data = request.data;
// TODO: Save to db await this.issueRequestRepository.save(issueRequest);
return issueRequest; return issueRequest;
} }
...@@ -82,6 +134,10 @@ export class RequestsService { ...@@ -82,6 +134,10 @@ export class RequestsService {
throw new Error(`String returned '${request}'. Expecting json object`); throw new Error(`String returned '${request}'. Expecting json object`);
} }
// This is an unsafe casting that creates a runtime exception if the
// casting fails. A more robust solution would be to use the
// class-transformer and class-validator libraries to make sure the object
// is valid.
return { request: (request as unknown) as T, requestor }; return { request: (request as unknown) as T, requestor };
} catch (e) { } catch (e) {
throw new InvalidRequestJWT('Could not decode request JWT'); throw new InvalidRequestJWT('Could not decode request JWT');
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment