Skip to content

Commit

Permalink
Merge pull request #109 from logion-network/feature/asymetric-jwt
Browse files Browse the repository at this point in the history
feat: create/verify JWT token with node key/peer id pair.
  • Loading branch information
benoitdevos authored Apr 1, 2022
2 parents 29fe911 + 24dfb8e commit 4da3370
Show file tree
Hide file tree
Showing 18 changed files with 544 additions and 286 deletions.
7 changes: 4 additions & 3 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
WS_PROVIDER_URL=wss://example.org:9944
NODE_TLS_REJECT_UNAUTHORIZED=0
# the base64-encoded version of "change-me-please":
JWT_SECRET=Y2hhbmdlLW1lLXBsZWFzZQ==
JWT_ISSUER=example.org
# Replace this value with the node key of the related validator node
JWT_SECRET=1c482e5368b84abe08e1a27d0670d303351989b3aa281cb1abfc2f48e4530b57
# Replace this value with the base58-encoded peer id of the related validator node
JWT_ISSUER=12D3KooWDCuGU7WY3VaWjBS1E44x4EnmTgK3HRxWFqYG3dqXDfP1
JWT_TTL_SEC=3600
# Alice
OWNER=5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
node-version: [16.x]
steps:
- name: Checkout
uses: actions/checkout@v2
Expand Down
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Build backend
FROM logionnetwork/logion-backend-calc:v1 AS calc
FROM node:14 AS build-backend
FROM node:16 AS build-backend
WORKDIR /tmp/logion-backend
COPY . .
COPY --from=calc /tmp/calc/pkg calc/pkg
RUN yarn install
RUN yarn build

# Backend image
FROM logionnetwork/logion-backend-base:v1
FROM logionnetwork/logion-backend-base:v2

COPY --from=build-backend /tmp/logion-backend/dist dist
COPY --from=build-backend /tmp/logion-backend/node_modules node_modules
Expand All @@ -18,8 +18,8 @@ COPY --from=build-backend /tmp/logion-backend/calc/pkg calc/pkg
ENV NODE_ENV=production
ENV WS_PROVIDER_URL=ws://localhost:9944
ENV NODE_TLS_REJECT_UNAUTHORIZED=0
ENV JWT_SECRET=Y2hhbmdlLW1lLXBsZWFzZQ==
ENV JWT_ISSUER=localhost
ENV JWT_SECRET=1c482e5368b84abe08e1a27d0670d303351989b3aa281cb1abfc2f48e4530b57
ENV JWT_ISSUER=12D3KooWDCuGU7WY3VaWjBS1E44x4EnmTgK3HRxWFqYG3dqXDfP1
ENV JWT_TTL_SEC=3600
ENV PORT=8080
ENV TYPEORM_CONNECTION=postgres
Expand Down
2 changes: 1 addition & 1 deletion docker/base/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Import pre-built calc
FROM logionnetwork/logion-backend-calc:v1 AS calc

FROM node:14
FROM node:16
RUN apt-get update && apt-get -y --no-install-recommends install postgresql-client ; rm -rf /var/lib/apt/lists/*
WORKDIR /usr/share/logion-backend
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@
"express-fileupload": "^1.2.1",
"express-oas-generator": "^1.0.41",
"inversify": "^6.0.1",
"jsonwebtoken": "^8.5.1",
"jose": "^4.6.0",
"logion-api": "^0.1.1",
"mongoose": "^6.1.6",
"mongoose-to-swagger": "^1.4.0",
"node-fetch": "3.1.1",
"nodemailer": "^6.7.2",
"openapi-typescript": "5.1.0",
"peer-id": "^0.16.0",
"pg": "^8.7.1",
"pug": "^3.0.2",
"source-map-support": "^0.5.21",
Expand All @@ -57,7 +58,6 @@
"@types/express": "^4.17.13",
"@types/express-fileupload": "^1.2.2",
"@types/jasmine": "^3.10.3",
"@types/jsonwebtoken": "^8.5.8",
"@types/node": "^17.0.9",
"@types/nodemailer": "^6.4.4",
"@types/pug": "^2.0.6",
Expand All @@ -76,7 +76,7 @@
"typescript": "^4.5.4"
},
"engines": {
"node": ">=14"
"node": ">=16"
},
"workspaces": [
"calc/pkg"
Expand Down
2 changes: 2 additions & 0 deletions src/logion/container/app.container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { MailService } from "../services/mail.service";
import { DirectoryService } from "../services/directory.service";
import { VaultTransferRequestController } from '../controllers/vaulttransferrequest.controller';
import { VaultTransferRequestFactory, VaultTransferRequestRepository } from '../model/vaulttransferrequest.model';
import { NodeAuthorizationService } from "../services/nodeauthorization.service";

let container = new Container({ defaultScope: "Singleton" });
container.bind(AuthenticationService).toSelf();
Expand Down Expand Up @@ -72,6 +73,7 @@ container.bind(MailService).toSelf()
container.bind(DirectoryService).toSelf()
container.bind(VaultTransferRequestRepository).toSelf();
container.bind(VaultTransferRequestFactory).toSelf();
container.bind(NodeAuthorizationService).toSelf();

// Controllers are stateful so they must not be injected with singleton scope
container.bind(ApplicationErrorController).toSelf().inTransientScope();
Expand Down
34 changes: 17 additions & 17 deletions src/logion/controllers/locrequest.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export class LocRequestController extends ApiController {
@HttpPost('')
@Async()
async createLocRequest(createLocRequestView: CreateLocRequestView): Promise<LocRequestView> {
const authenticatedUser = this.authenticationService.authenticatedUser(this.request);
const authenticatedUser = await this.authenticationService.authenticatedUser(this.request);
authenticatedUser.require(user => user.is(createLocRequestView.requesterAddress) || user.isNodeOwner());
const description: LocRequestDescription = {
requesterAddress: createLocRequestView.requesterAddress,
Expand Down Expand Up @@ -238,7 +238,7 @@ export class LocRequestController extends ApiController {
@HttpPut('')
@Async()
async fetchRequests(specificationView: FetchLocRequestsSpecificationView): Promise<FetchLocRequestsResponseView> {
this.authenticationService.authenticatedUserIsOneOf(this.request, specificationView.requesterAddress, specificationView.ownerAddress)
await this.authenticationService.authenticatedUserIsOneOf(this.request, specificationView.requesterAddress, specificationView.ownerAddress)
const specification: FetchLocRequestsSpecification = {
expectedRequesterAddress: specificationView.requesterAddress,
expectedOwnerAddress: specificationView.ownerAddress,
Expand Down Expand Up @@ -287,7 +287,7 @@ export class LocRequestController extends ApiController {
async getLocRequest(_body: any, requestId: string): Promise<LocRequestView> {
try {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
this.authenticationService.authenticatedUserIsOneOf(this.request,
await this.authenticationService.authenticatedUserIsOneOf(this.request,
request.requesterAddress, request.ownerAddress);
const userIdentity = await this.findUserIdentity(request);
return this.toView(request, userIdentity);
Expand Down Expand Up @@ -366,7 +366,7 @@ export class LocRequestController extends ApiController {
@Async()
async rejectLocRequest(rejectLocRequestView: RejectLocRequestView, requestId: string) {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
await this.authenticationService.authenticatedUser(this.request)
await (await this.authenticationService.authenticatedUser(this.request))
.requireNodeOwner();
request.reject(rejectLocRequestView.rejectReason!, moment());
await this.locRequestRepository.save(request)
Expand All @@ -386,7 +386,7 @@ export class LocRequestController extends ApiController {
@Async()
async acceptLocRequest(_ignoredBody: any, requestId: string) {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
await this.authenticationService.authenticatedUser(this.request)
await (await this.authenticationService.authenticatedUser(this.request))
.requireNodeOwner();
request.accept(moment());
await this.locRequestRepository.save(request)
Expand All @@ -406,7 +406,7 @@ export class LocRequestController extends ApiController {
@Async()
async addFile(addFileView: AddFileView, requestId: string): Promise<AddFileResultView> {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
const submitter = this.authenticationService.authenticatedUser(this.request)
const submitter = (await this.authenticationService.authenticatedUser(this.request))
.require(user => user.isNodeOwner() || user.is(request.requesterAddress), "Only LOC owner or requester can submit a file")
.address

Expand Down Expand Up @@ -457,7 +457,7 @@ export class LocRequestController extends ApiController {
@SendsResponse()
async downloadFile(_body: any, requestId: string, hash: string): Promise<void> {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
this.authenticationService.authenticatedUser(this.request)
await (await this.authenticationService.authenticatedUser(this.request))
.require(user => user.isNodeOwner() || user.is(request.requesterAddress), "Only LOC owner or requester can download a file")

const file = request.getFile(hash);
Expand Down Expand Up @@ -486,7 +486,7 @@ export class LocRequestController extends ApiController {
@Async()
async deleteFile(_body: any, requestId: string, hash: string): Promise<void> {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
const userCheck = this.authenticationService.authenticatedUser(this.request);
const userCheck = await this.authenticationService.authenticatedUser(this.request);
userCheck.require(user => user.isNodeOwner() || user.is(request.requesterAddress), "Only LOC owner or requester can delete a file")

const file = request.removeFile(userCheck.address, hash);
Expand All @@ -511,7 +511,7 @@ export class LocRequestController extends ApiController {
@SendsResponse()
async confirmFile(_body: any, requestId: string, hash: string) {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
await this.authenticationService.authenticatedUser(this.request)
await (await this.authenticationService.authenticatedUser(this.request))
.requireNodeOwner();

request.confirmFile(hash);
Expand All @@ -533,7 +533,7 @@ export class LocRequestController extends ApiController {
@SendsResponse()
async closeLoc(_body: any, requestId: string) {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
await this.authenticationService.authenticatedUser(this.request)
await (await this.authenticationService.authenticatedUser(this.request))
.requireNodeOwner();

request.preClose();
Expand All @@ -559,7 +559,7 @@ export class LocRequestController extends ApiController {
@SendsResponse()
async voidLoc(body: VoidLocView, requestId: string) {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
await this.authenticationService.authenticatedUser(this.request)
await (await this.authenticationService.authenticatedUser(this.request))
.requireNodeOwner();

request.preVoid(body.reason!);
Expand All @@ -581,7 +581,7 @@ export class LocRequestController extends ApiController {
@SendsResponse()
async addLink(addLinkView: AddLinkView, requestId: string): Promise<void> {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
await this.authenticationService.authenticatedUser(this.request)
await (await this.authenticationService.authenticatedUser(this.request))
.requireNodeOwner();
const targetRequest = requireDefined(await this.locRequestRepository.findById(addLinkView.target!));
request.addLink({
Expand All @@ -607,7 +607,7 @@ export class LocRequestController extends ApiController {
@Async()
async deleteLink(_body: any, requestId: string, target: string): Promise<void> {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
const userCheck = this.authenticationService.authenticatedUser(this.request);
const userCheck = await this.authenticationService.authenticatedUser(this.request);
await userCheck.requireNodeOwner();

request.removeLink(userCheck.address, target);
Expand All @@ -630,7 +630,7 @@ export class LocRequestController extends ApiController {
@SendsResponse()
async confirmLink(_body: any, requestId: string, target: string) {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
await this.authenticationService.authenticatedUser(this.request)
await (await this.authenticationService.authenticatedUser(this.request))
.requireNodeOwner();

request.confirmLink(target);
Expand All @@ -652,7 +652,7 @@ export class LocRequestController extends ApiController {
@SendsResponse()
async addMetadata(addMetadataView: AddMetadataView, requestId: string): Promise<void> {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
const submitter = this.authenticationService.authenticatedUser(this.request)
const submitter = (await this.authenticationService.authenticatedUser(this.request))
.require(user => user.isNodeOwner() || user.is(request.requesterAddress), "Only LOC owner or requester can submit metadata")
.address
const name = requireLength(addMetadataView, "name", 3, 255)
Expand All @@ -677,7 +677,7 @@ export class LocRequestController extends ApiController {
@Async()
async deleteMetadata(_body: any, requestId: string, name: string): Promise<void> {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
const userCheck = this.authenticationService.authenticatedUser(this.request);
const userCheck = await this.authenticationService.authenticatedUser(this.request);
userCheck.require(user => user.isNodeOwner() || user.is(request.requesterAddress), "Only LOC owner or requester can delete metadata")

const decodedName = decodeURIComponent(name);
Expand All @@ -702,7 +702,7 @@ export class LocRequestController extends ApiController {
@SendsResponse()
async confirmMetadata(_body: any, requestId: string, name: string) {
const request = requireDefined(await this.locRequestRepository.findById(requestId));
await this.authenticationService.authenticatedUser(this.request)
await (await this.authenticationService.authenticatedUser(this.request))
.requireNodeOwner();

const decodedName = decodeURIComponent(name);
Expand Down
10 changes: 5 additions & 5 deletions src/logion/controllers/protectionrequest.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export class ProtectionRequestController extends ApiController {
@Async()
@HttpPost('')
async createProtectionRequest(body: CreateProtectionRequestView): Promise<ProtectionRequestView> {
this.authenticationService.authenticatedUserIs(this.request, body.requesterAddress);
await this.authenticationService.authenticatedUserIs(this.request, body.requesterAddress);
const request = this.protectionRequestFactory.newProtectionRequest({
id: uuid(),
description: {
Expand Down Expand Up @@ -122,7 +122,7 @@ export class ProtectionRequestController extends ApiController {
@Async()
@HttpPut('')
async fetchProtectionRequests(body: FetchProtectionRequestsSpecificationView): Promise<FetchProtectionRequestsResponseView> {
this.authenticationService.authenticatedUserIsOneOf(this.request,
await this.authenticationService.authenticatedUserIsOneOf(this.request,
body.requesterAddress,
this.authenticationService.nodeOwner);
const specification = new FetchProtectionRequestsSpecification({
Expand Down Expand Up @@ -182,7 +182,7 @@ export class ProtectionRequestController extends ApiController {
@Async()
@HttpPost('/:id/reject')
async rejectProtectionRequest(body: RejectProtectionRequestView, id: string): Promise<ProtectionRequestView> {
this.authenticationService.authenticatedUser(this.request)
(await this.authenticationService.authenticatedUser(this.request))
.require(user => user.isNodeOwner());
const request = requireDefined(await this.protectionRequestRepository.findById(id));
request.reject(body.rejectReason!, moment());
Expand All @@ -207,7 +207,7 @@ export class ProtectionRequestController extends ApiController {
@Async()
@HttpPost('/:id/accept')
async acceptProtectionRequest(body: AcceptProtectionRequestView, id: string): Promise<ProtectionRequestView> {
this.authenticationService.authenticatedUser(this.request)
(await this.authenticationService.authenticatedUser(this.request))
.require(user => user.isNodeOwner());
if(body.locId === undefined || body.locId === null) {
throw badRequest("Missing LOC ID");
Expand Down Expand Up @@ -253,7 +253,7 @@ export class ProtectionRequestController extends ApiController {
authorizeUsers.push(protectionRequests[0].addressToRecover);
}
authorizeUsers.push(protectionRequests[0].requesterAddress!);
this.authenticationService.authenticatedUserIsOneOf(this.request, ...authorizeUsers)
await this.authenticationService.authenticatedUserIsOneOf(this.request, ...authorizeUsers)
return {
recoveryAccount: this.adapt(recovery),
accountToRecover: this.adapt(protectionRequests[0]),
Expand Down
Loading

0 comments on commit 4da3370

Please sign in to comment.