瀏覽代碼

storage-node-v2: Update auth-token

Add more fields:
- storageBucketId
- bagId
Shamil Gadelshin 3 年之前
父節點
當前提交
3ba67a2589

+ 2 - 0
storage-node-v2/package.json

@@ -13,10 +13,12 @@
     "@oclif/config": "^1",
     "@oclif/plugin-help": "^3",
     "@polkadot/api": "4.2.1",
+    "@types/base64url": "^2.0.0",
     "@types/express": "4.17.1",
     "@types/multer": "^1.4.5",
     "@types/winston": "^2.4.4",
     "await-lock": "^2.1.0",
+    "base64url": "^3.0.1",
     "blake3": "^2.1.4",
     "express": "4.17.1",
     "express-openapi-validator": "^4.12.4",

+ 45 - 12
storage-node-v2/src/services/helpers/auth.ts

@@ -1,6 +1,7 @@
 import { KeyringPair } from '@polkadot/keyring/types'
-import { stringToU8a, u8aToHex } from '@polkadot/util'
+import { u8aToHex } from '@polkadot/util'
 import { signatureVerify } from '@polkadot/util-crypto'
+import base64url from 'base64url'
 
 export interface TokenRequest {
   dataObjectId: number
@@ -8,23 +9,55 @@ export interface TokenRequest {
   bagId: string
 }
 
+export interface TokenBody {
+  dataObjectId: number
+  storageBucketId: number
+  bagId: string
+  timestamp: number
+}
+
+export interface Token {
+  data: TokenBody
+  signature: string
+}
+
+export function parseToken(tokenString: string): Token {
+  return JSON.parse(base64url.decode(tokenString))
+}
+
 export function verifyTokenSignature(
-  tokenRequest: TokenRequest,
-  signature: string,
+  token: Token,
   account: KeyringPair
 ): boolean {
-  const message = JSON.stringify(tokenRequest)
-  const { isValid } = signatureVerify(message, signature, account.address)
+  const message = JSON.stringify(token.data)
+  const { isValid } = signatureVerify(message, token.signature, account.address)
 
   return isValid
 }
 
-export function signToken(
-  tokenRequest: TokenRequest,
-  account: KeyringPair
-): string {
-  const message = stringToU8a(JSON.stringify(tokenRequest))
-  const signature = account.sign(message)
+export function signToken(tokenBody: TokenBody, account: KeyringPair): string {
+  const message = JSON.stringify(tokenBody)
+  const signature = u8aToHex(account.sign(message))
+
+  const token: Token = {
+    data: tokenBody,
+    signature,
+  }
+
+  return base64url.encode(JSON.stringify(token))
+}
+
+// Throws exceptions on errors.
+export function verifyTokenData(token: Token, data: TokenRequest): void {
+  if (token.data.dataObjectId !== data.dataObjectId) {
+    throw new Error('Unexpected dataObjectId')
+  }
+
+  if (token.data.storageBucketId !== data.storageBucketId) {
+    throw new Error('Unexpected storageBucketId')
+  }
 
-  return u8aToHex(signature)
+  if (token.data.bagId !== data.bagId) {
+    throw new Error('Unexpected bagId')
+  }
 }

+ 11 - 4
storage-node-v2/src/services/webApi/app.ts

@@ -9,7 +9,12 @@ import {
 } from 'express-openapi-validator/dist/framework/types'
 import { KeyringPair } from '@polkadot/keyring/types'
 import { ApiPromise } from '@polkadot/api'
-import { TokenRequest, verifyTokenSignature } from '../helpers/auth'
+import {
+  TokenRequest,
+  verifyTokenSignature,
+  parseToken,
+  verifyTokenData,
+} from '../helpers/auth'
 import { httpLogger } from '../../services/logger'
 
 // Creates web API application.
@@ -97,15 +102,17 @@ function validateUpload(
     scopes: string[],
     schema: OpenAPIV3.SecuritySchemeObject
   ) => {
-    const tokenSignature = req.headers['x-api-key'] as string
+    const tokenString = req.headers['x-api-key'] as string
+    const token = parseToken(tokenString)
 
-    // TODO: token construction
     const sourceTokenRequest: TokenRequest = {
       dataObjectId: parseInt(req.body.dataObjectId),
       storageBucketId: parseInt(req.body.storageBucketId),
       bagId: req.body.bagId,
     }
 
-    return verifyTokenSignature(sourceTokenRequest, tokenSignature, account)
+    verifyTokenData(token, sourceTokenRequest)
+
+    return verifyTokenSignature(token, account)
   }
 }

+ 7 - 3
storage-node-v2/src/services/webApi/controllers/publicApi.ts

@@ -1,6 +1,6 @@
 import * as express from 'express'
 import { acceptPendingDataObjects } from '../../runtime/extrinsics'
-import { TokenRequest, signToken } from '../../helpers/auth'
+import { TokenRequest, TokenBody, signToken } from '../../helpers/auth'
 import { hashFile } from '../../../services/helpers/hashing'
 import { KeyringPair } from '@polkadot/keyring/types'
 import { ApiPromise } from '@polkadot/api'
@@ -56,10 +56,14 @@ export async function authToken(
 ): Promise<void> {
   const account = getAccount(res)
   const tokenRequest = getTokenRequest(req)
-  const signature = signToken(tokenRequest, account)
+  const tokenBody: TokenBody = {
+    timestamp: Date.now(),
+    ...tokenRequest,
+  }
+  const signedToken = signToken(tokenBody, account)
 
   res.status(201).json({
-    token: signature,
+    token: signedToken,
   })
 }
 

+ 12 - 0
yarn.lock

@@ -5012,6 +5012,13 @@
   dependencies:
     "@babel/types" "^7.3.0"
 
+"@types/base64url@^2.0.0":
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/@types/base64url/-/base64url-2.0.0.tgz#3bf4184a53a6bef998fada88d836e37eb0366492"
+  integrity sha512-r+d5HWla1etMB9MdDr/wfzhiWdT6GTlO6Xp96FnSsnsxeOi3ZCz1EJyv7OE7Coc2cw5tGblqahMYNL/KwdP8kQ==
+  dependencies:
+    base64url "*"
+
 "@types/bluebird@^3.5.20":
   version "3.5.33"
   resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.33.tgz#d79c020f283bd50bd76101d7d300313c107325fc"
@@ -8312,6 +8319,11 @@ base64-js@^1.3.1, base64-js@^1.5.1:
   resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
   integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
 
+base64url@*, base64url@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d"
+  integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==
+
 base@^0.11.1:
   version "0.11.2"
   resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"