mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-22 17:45:10 +00:00
Update api key header
Use more common X-Api-Key header with no prefix Also updates Unauthorized response to include a json error body and simplifies working with new API key via curl and the vscode rest client Signed-off-by: James Taylor <jamest@uk.ibm.com>
This commit is contained in:
parent
c3a34ef559
commit
05f7026e58
5 changed files with 145 additions and 98 deletions
26
README.md
26
README.md
|
|
@ -48,52 +48,60 @@ npm run start:dev
|
||||||
|
|
||||||
## REST API
|
## REST API
|
||||||
|
|
||||||
If everything went well, you can now make basic asset transfer REST calls! For example...
|
If everything went well, you can now make basic asset transfer REST calls!
|
||||||
|
|
||||||
|
The examples below require a `SAMPLE_APIKEY` environment variable which must be set to an API key from the `.env` file created above.
|
||||||
|
|
||||||
|
For example, to use the ORG1_APIKEY...
|
||||||
|
|
||||||
|
```
|
||||||
|
SAMPLE_APIKEY=$(grep ORG1_APIKEY .env | cut -d '=' -f 2-)
|
||||||
|
```
|
||||||
|
|
||||||
### Get all assets...
|
### Get all assets...
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl http://localhost:3000/api/assets
|
curl --header "X-Api-Key: ${SAMPLE_APIKEY}" http://localhost:3000/api/assets
|
||||||
```
|
```
|
||||||
|
|
||||||
### Check whether an asset exists...
|
### Check whether an asset exists...
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl --include --request OPTIONS http://localhost:3000/api/assets/asset7
|
curl --include --header "X-Api-Key: ${SAMPLE_APIKEY}" --request OPTIONS http://localhost:3000/api/assets/asset7
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create an asset...
|
### Create an asset...
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl --include --header "Content-Type: application/json" --header "api-key:Api-Key <apikeyfororg>" --request POST --data '{"id":"asset7","color":"red","size":42,"owner":"Jean","appraisedValue":101}' http://localhost:3000/api/assets
|
curl --include --header "Content-Type: application/json" --header "X-Api-Key: ${SAMPLE_APIKEY}" --request POST --data '{"id":"asset7","color":"red","size":42,"owner":"Jean","appraisedValue":101}' http://localhost:3000/api/assets
|
||||||
```
|
```
|
||||||
|
|
||||||
### Read transaction status...
|
### Read transaction status...
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl --header "api-key:Api-Key <apikeyfororg>" http://localhost:3000/api/transactions/__transaction_id__
|
curl --header "X-Api-Key: ${SAMPLE_APIKEY}" http://localhost:3000/api/transactions/__transaction_id__
|
||||||
```
|
```
|
||||||
|
|
||||||
### Read an asset...
|
### Read an asset...
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl --header "api-key:Api-Key <apikeyfororg>" http://localhost:3000/api/assets/asset7
|
curl --header "X-Api-Key: ${SAMPLE_APIKEY}" http://localhost:3000/api/assets/asset7
|
||||||
```
|
```
|
||||||
|
|
||||||
### Update an asset...
|
### Update an asset...
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl --include --header "Content-Type: application/json" --header "api-key:Api-Key <apikeyfororg>" --request PUT --data '{"id":"asset7","color":"red","size":11,"owner":"Jean","appraisedValue":101}' http://localhost:3000/api/assets/asset7
|
curl --include --header "Content-Type: application/json" --header "X-Api-Key: ${SAMPLE_APIKEY}" --request PUT --data '{"id":"asset7","color":"red","size":11,"owner":"Jean","appraisedValue":101}' http://localhost:3000/api/assets/asset7
|
||||||
```
|
```
|
||||||
|
|
||||||
### Transfer an asset...
|
### Transfer an asset...
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl --include --header "Content-Type: application/json" --header "api-key:Api-Key <apikeyfororg>" --request PATCH --data '[{"op":"replace","path":"/owner","value":"Ashleigh"}]' http://localhost:3000/api/assets/asset7
|
curl --include --header "Content-Type: application/json" --header "X-Api-Key: ${SAMPLE_APIKEY}" --request PATCH --data '[{"op":"replace","path":"/owner","value":"Ashleigh"}]' http://localhost:3000/api/assets/asset7
|
||||||
```
|
```
|
||||||
|
|
||||||
### Delete an asset...
|
### Delete an asset...
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl --include --header "api-key:Api-Key <apikeyfororg>" --request DELETE http://localhost:3000/api/assets/asset7
|
curl --include --header "X-Api-Key: ${SAMPLE_APIKEY}" --request DELETE http://localhost:3000/api/assets/asset7
|
||||||
```
|
```
|
||||||
|
|
|
||||||
84
asset-transfer-basic/rest-api-typescript/demo.http
Normal file
84
asset-transfer-basic/rest-api-typescript/demo.http
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
// Demo file for use with REST Client for Visual Studio Code
|
||||||
|
// See https://github.com/Huachao/vscode-restclient
|
||||||
|
//
|
||||||
|
// Edit the values below to match your environment if required
|
||||||
|
@hostname = localhost
|
||||||
|
@port = {{$dotenv PORT}}
|
||||||
|
@baseUrl = http://{{hostname}}:{{port}}
|
||||||
|
@apiUrl = {{baseUrl}}/api
|
||||||
|
@api-key = {{$dotenv ORG1_APIKEY}}
|
||||||
|
|
||||||
|
### Check the server is ready
|
||||||
|
|
||||||
|
GET {{baseUrl}}/ready HTTP/1.1
|
||||||
|
|
||||||
|
### Check the server is still live
|
||||||
|
|
||||||
|
GET {{baseUrl}}/live HTTP/1.1
|
||||||
|
|
||||||
|
### Get all assets
|
||||||
|
|
||||||
|
GET {{apiUrl}}/assets HTTP/1.1
|
||||||
|
X-Api-Key: {{api-key}}
|
||||||
|
|
||||||
|
### Check if asset exists
|
||||||
|
|
||||||
|
OPTIONS {{apiUrl}}/assets/asset7 HTTP/1.1
|
||||||
|
X-Api-Key: {{api-key}}
|
||||||
|
|
||||||
|
### Create asset
|
||||||
|
|
||||||
|
POST {{apiUrl}}/assets HTTP/1.1
|
||||||
|
content-type: application/json
|
||||||
|
X-Api-Key: {{api-key}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": "asset7",
|
||||||
|
"color": "red",
|
||||||
|
"size": 42,
|
||||||
|
"owner": "Jean",
|
||||||
|
"appraisedValue": 101
|
||||||
|
}
|
||||||
|
|
||||||
|
### Read transaction status
|
||||||
|
|
||||||
|
GET {{apiUrl}}/transactions/__transaction_id__ HTTP/1.1
|
||||||
|
X-Api-Key: {{api-key}}
|
||||||
|
|
||||||
|
### Read asset
|
||||||
|
|
||||||
|
GET {{apiUrl}}/assets/asset7 HTTP/1.1
|
||||||
|
X-Api-Key: {{api-key}}
|
||||||
|
|
||||||
|
### Update asset
|
||||||
|
|
||||||
|
PUT {{apiUrl}}/assets/asset7 HTTP/1.1
|
||||||
|
content-type: application/json
|
||||||
|
X-Api-Key: {{api-key}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": "asset7",
|
||||||
|
"color": "red",
|
||||||
|
"size": 11,
|
||||||
|
"owner": "Jean",
|
||||||
|
"appraisedValue": 101
|
||||||
|
}
|
||||||
|
|
||||||
|
### Transfer asset
|
||||||
|
|
||||||
|
PATCH {{apiUrl}}/assets/asset7 HTTP/1.1
|
||||||
|
content-type: application/json
|
||||||
|
X-Api-Key: {{api-key}}
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"op": "replace",
|
||||||
|
"path": "/owner",
|
||||||
|
"value": "Ashleigh"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
### Delete asset
|
||||||
|
|
||||||
|
DELETE {{apiUrl}}/assets/asset7 HTTP/1.1
|
||||||
|
X-Api-Key: {{api-key}}
|
||||||
|
|
@ -1,24 +1,61 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
import { logger } from './logger';
|
import { logger } from './logger';
|
||||||
|
import passport from 'passport';
|
||||||
|
import { NextFunction, Request, Response } from 'express';
|
||||||
import { HeaderAPIKeyStrategy } from 'passport-headerapikey';
|
import { HeaderAPIKeyStrategy } from 'passport-headerapikey';
|
||||||
|
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
|
||||||
import * as config from './config';
|
import * as config from './config';
|
||||||
|
|
||||||
|
const { UNAUTHORIZED } = StatusCodes;
|
||||||
|
|
||||||
export const fabricAPIKeyStrategy: HeaderAPIKeyStrategy =
|
export const fabricAPIKeyStrategy: HeaderAPIKeyStrategy =
|
||||||
new HeaderAPIKeyStrategy(
|
new HeaderAPIKeyStrategy(
|
||||||
{ header: 'api-key', prefix: 'Api-Key ' },
|
{ header: 'X-API-Key', prefix: '' },
|
||||||
true,
|
false,
|
||||||
function (apikey, done) {
|
function (apikey, done) {
|
||||||
|
logger.debug({ apikey }, 'Checking X-API-Key');
|
||||||
const user: { org: string } = {
|
const user: { org: string } = {
|
||||||
org: '',
|
org: '',
|
||||||
};
|
};
|
||||||
if (apikey === config.org1ApiKey) {
|
if (apikey === config.org1ApiKey) {
|
||||||
user.org = 'Org1';
|
user.org = 'Org1';
|
||||||
logger.info('Organisation set to Org1');
|
logger.debug('Organisation set to Org1');
|
||||||
done(null, user);
|
done(null, user);
|
||||||
|
|
||||||
//todo
|
//todo
|
||||||
//add org2 apikey check
|
//add org2 apikey check
|
||||||
} else {
|
} else {
|
||||||
logger.debug('APIKEY Mismatch');
|
logger.debug({ apikey }, 'No valid X-API-Key');
|
||||||
return done(null, false);
|
return done(null, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const authenticateApiKey = (
|
||||||
|
req: Request,
|
||||||
|
res: Response,
|
||||||
|
next: NextFunction
|
||||||
|
): void => {
|
||||||
|
passport.authenticate(
|
||||||
|
'headerapikey',
|
||||||
|
{ session: false },
|
||||||
|
function (err, user, _info) {
|
||||||
|
if (err) return next(err);
|
||||||
|
if (!user)
|
||||||
|
return res.status(UNAUTHORIZED).json({
|
||||||
|
status: getReasonPhrase(UNAUTHORIZED),
|
||||||
|
reason: 'NO_VALID_APIKEY',
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
});
|
||||||
|
req.logIn(user, { session: false }, (err) => {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
return next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
)(req, res, next);
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ const {
|
||||||
SERVICE_UNAVAILABLE,
|
SERVICE_UNAVAILABLE,
|
||||||
} = StatusCodes;
|
} = StatusCodes;
|
||||||
|
|
||||||
import { fabricAPIKeyStrategy } from './auth';
|
import { authenticateApiKey, fabricAPIKeyStrategy } from './auth';
|
||||||
import passport from 'passport';
|
import passport from 'passport';
|
||||||
export const createServer = async (): Promise<Application> => {
|
export const createServer = async (): Promise<Application> => {
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
@ -98,16 +98,8 @@ export const createServer = async (): Promise<Application> => {
|
||||||
throw new Error('Example error');
|
throw new Error('Example error');
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(
|
app.use('/api/assets', authenticateApiKey, assetsRouter);
|
||||||
'/api/assets',
|
app.use('/api/transactions', authenticateApiKey, transactionsRouter);
|
||||||
passport.authenticate('headerapikey', { session: false }),
|
|
||||||
assetsRouter
|
|
||||||
);
|
|
||||||
app.use(
|
|
||||||
'/api/transactions',
|
|
||||||
passport.authenticate('headerapikey', { session: false }),
|
|
||||||
transactionsRouter
|
|
||||||
);
|
|
||||||
|
|
||||||
// For everything else
|
// For everything else
|
||||||
app.use((_req, res) =>
|
app.use((_req, res) =>
|
||||||
|
|
|
||||||
74
demo.http
74
demo.http
|
|
@ -1,74 +0,0 @@
|
||||||
// Demo file for use with REST Client for Visual Studio Code
|
|
||||||
// See https://github.com/Huachao/vscode-restclient
|
|
||||||
@hostname = localhost
|
|
||||||
@port = 3000
|
|
||||||
@baseUrl = http://{{hostname}}:{{port}}/api
|
|
||||||
|
|
||||||
//Get the apikey from .env file
|
|
||||||
@api-key= Api-Key 295069C9-ABF5-4D2A-A020-2FF9F4E8DF07
|
|
||||||
|
|
||||||
### Get all assets
|
|
||||||
GET {{baseUrl}}/assets HTTP/1.1
|
|
||||||
api-key: {{api-key}}
|
|
||||||
|
|
||||||
### Check if asset exists
|
|
||||||
|
|
||||||
OPTIONS {{baseUrl}}/assets/asset7 HTTP/1.1
|
|
||||||
api-key: {{api-key}}
|
|
||||||
|
|
||||||
### Create asset
|
|
||||||
|
|
||||||
POST {{baseUrl}}/assets HTTP/1.1
|
|
||||||
content-type: application/json
|
|
||||||
api-key: {{api-key}}
|
|
||||||
|
|
||||||
{
|
|
||||||
"id": "asset7",
|
|
||||||
"color": "red",
|
|
||||||
"size": 42,
|
|
||||||
"owner": "Jean",
|
|
||||||
"appraisedValue": 101
|
|
||||||
}
|
|
||||||
|
|
||||||
### Read transaction status
|
|
||||||
|
|
||||||
GET {{baseUrl}}/transactions/__transaction_id__ HTTP/1.1
|
|
||||||
api-key: {{api-key}}
|
|
||||||
|
|
||||||
### Read asset
|
|
||||||
|
|
||||||
GET {{baseUrl}}/assets/asset7 HTTP/1.1
|
|
||||||
api-key: {{api-key}}
|
|
||||||
|
|
||||||
### Update asset
|
|
||||||
|
|
||||||
PUT {{baseUrl}}/assets/asset7 HTTP/1.1
|
|
||||||
content-type: application/json
|
|
||||||
api-key: {{api-key}}
|
|
||||||
|
|
||||||
{
|
|
||||||
"id": "asset7",
|
|
||||||
"color": "red",
|
|
||||||
"size": 11,
|
|
||||||
"owner": "Jean",
|
|
||||||
"appraisedValue": 101
|
|
||||||
}
|
|
||||||
|
|
||||||
### Transfer asset
|
|
||||||
|
|
||||||
PATCH {{baseUrl}}/assets/asset7 HTTP/1.1
|
|
||||||
content-type: application/json
|
|
||||||
api-key: {{api-key}}
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"op": "replace",
|
|
||||||
"path": "/owner",
|
|
||||||
"value": "Ashleigh"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
### Delete asset
|
|
||||||
|
|
||||||
DELETE {{baseUrl}}/assets/asset7 HTTP/1.1
|
|
||||||
api-key: {{api-key}}
|
|
||||||
Loading…
Reference in a new issue