Skip to content

Commit

Permalink
fix: switch to x-api-key header authentication [DEV-4062] (#556)
Browse files Browse the repository at this point in the history
* update swagger admin and api options

* generate new swagger files for admin and api

* remove customJs from swagger

* remove user info fetcher since switching to x-api-key

* fix: update playwright tests to use "api-key" for authentication [DEV-4071] (#557)

* update auth.setup.ts and no-auth.setup.ts

* update example.env

* export TEST_USER_API_KEY for CI env

* set x-api-key only for authenticated user tests

* revert changes on no-auth.setup.ts

* skip /admin/swagger

* Update example.env

* update swagger types

* generate swagger

* fix: remaining

* fix incorrect usage way of required

* fix indentation

* generate swagger-admin

* Update swagger-admin.json

* hope this passes

* keep description

---------

Co-authored-by: Ankur Banerjee <[email protected]>
  • Loading branch information
benyam7 and ankurdotb authored Jul 8, 2024
1 parent 93d1f57 commit 01e6ab8
Show file tree
Hide file tree
Showing 19 changed files with 4,045 additions and 3,960 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ jobs:
RESOLVER_URL: ${{ vars.RESOLVER_URL }}
TEST_USER_EMAIL: ${{ secrets.TEST_USER_EMAIL }}
TEST_USER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }}
TEST_USER_API_KEY: ${{ secrets.TEST_USER_API_KEY }}
TESTNET_RPC_URL: ${{ vars.TESTNET_RPC_URL }}
VERIDA_PRIVATE_KEY: ${{ secrets.VERIDA_PRIVATE_KEY }}
CREDS_DECRYPTION_SECRET: ${{ secrets.CREDS_DECRYPTION_SECRET }}
Expand Down
6 changes: 6 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,9 @@ ISSUER_PRIVATE_KEY_HEX="akjvncanv....avoa"
ISSUER_PUBLIC_KEY_HEX="alnvca...dvncioa"
ISSUER_DID="did:cheqd:testnet:afcnoa...adv"
DEFAULT_FEE_PAYER_MNEMONIC="sketch mountain ....."


# TEST_RUNNER
TEST_USER_EMAIL='[email protected]'
TEST_USER_PASSWORD='...'
TEST_USER_API_KEY='caas_...'
4 changes: 4 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ export default defineConfig({
...devices['Desktop Chrome'],
// Use prepared auth state.
storageState: STORAGE_STATE_AUTHENTICATED,
extraHTTPHeaders: {
// Add x-api-key token to all authenticated requests.
'x-api-key': `${process.env.TEST_USER_API_KEY}`,
},
},
dependencies: ['Setup authenticated user'],
},
Expand Down
13 changes: 1 addition & 12 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,6 @@ import { WebhookController } from './controllers/admin/webhook.js';
import { APIKeyController } from './controllers/admin/api-key.js';
import { OrganisationController } from './controllers/admin/organisation.js';

let swaggerOptions = {};
if (process.env.ENABLE_AUTHENTICATION === 'true') {
swaggerOptions = {
customJs: '/static/custom-button.js',
};
}

class App {
public express: express.Application;

Expand Down Expand Up @@ -109,11 +102,7 @@ class App {
this.express.use(auth.handleError);
this.express.use(async (req, res, next) => await auth.accessControl(req, res, next));

this.express.use(
'/swagger',
swaggerUi.serveFiles(swaggerAPIDocument, swaggerOptions),
swaggerUi.setup(swaggerAPIDocument, swaggerOptions)
);
this.express.use('/swagger', swaggerUi.serveFiles(swaggerAPIDocument), swaggerUi.setup(swaggerAPIDocument));
if (process.env.STRIPE_ENABLED === 'true') {
this.express.use(
'/admin/swagger',
Expand Down
4 changes: 2 additions & 2 deletions src/controllers/admin/api-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class APIKeyController {
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/APIKeyCreateResponseBody'
* $ref: '#/components/schemas/APIKeyResponse'
* 400:
* $ref: '#/components/schemas/APIKeyCreateUnsuccessfulResponseBody'
* 401:
Expand Down Expand Up @@ -230,7 +230,7 @@ export class APIKeyController {
* @openapi
*
* /admin/api-key/revoke:
* delete:
* post:
* summary: Revoke an existing API key
* description: Revoke an existing API key
* tags: [API Key]
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/admin/prices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class PriceController {
* schema:
* type: string
* description: The product id. If passed - returns filtered by this product list of prices.
* required: false
*
* responses:
* 200:
* description: A list of prices
Expand Down
4 changes: 0 additions & 4 deletions src/controllers/admin/product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,18 @@ export class ProductController {
* schema:
* type: boolean
* description: If setup to true - returns the list of products with prices inside. Default - true
* required: false
* - in: query
* name: limit
* schema:
* type: integer
* minimum: 1
* maximum: 100
* description: Restrict the response to only include items from 1 to 100. Default - 10
* required: false
* - in: query
* name: cursor
* schema:
* type: string
* description: Cursor for pagination, this only goes forward, i.e., Stripe's equivalent of 'starting_after'
* required: false
* responses:
* 200:
* description: A list of products
Expand Down Expand Up @@ -141,7 +138,6 @@ export class ProductController {
* schema:
* type: boolean
* description: If setup to true - returns the product with prices inside. Default - true
* required: false
* responses:
* 200:
* description: A product
Expand Down
42 changes: 21 additions & 21 deletions src/controllers/admin/subscriptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,30 +488,30 @@ export class SubscriptionController {
* @openapi
*
* /admin/subscription/resume:
* post:
* summary: Resume a subscription
* description: Resumes an existing subscription
* tags: [Subscription]
* requestBody:
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SubscriptionResumeRequestBody'
* responses:
* 200:
* description: The request was successful.
* post:
* summary: Resume a subscription
* description: Resumes an existing subscription
* tags: [Subscription]
* requestBody:
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SubscriptionResumeResponseBody'
* 400:
* $ref: '#/components/schemas/InvalidRequest'
* 401:
* $ref: '#/components/schemas/UnauthorizedError'
* 500:
* $ref: '#/components/schemas/InternalError'
* 404:
* $ref: '#/components/schemas/NotFoundError'
* $ref: '#/components/schemas/SubscriptionResumeRequestBody'
* responses:
* 200:
* description: The request was successful.
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/SubscriptionResumeResponseBody'
* 400:
* $ref: '#/components/schemas/InvalidRequest'
* 401:
* $ref: '#/components/schemas/UnauthorizedError'
* 500:
* $ref: '#/components/schemas/InternalError'
* 404:
* $ref: '#/components/schemas/NotFoundError'
*/
@validate
@syncOne
Expand Down
8 changes: 4 additions & 4 deletions src/controllers/api/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ export class AccountController {
* description: The request was successful.
* content:
* application/json:
* idToken:
* type: string
* schema:
* $ref: '#/components/schemas/QueryIdTokenResponseBody'
* 400:
* $ref: '#/components/schemas/InvalidRequest'
* 401:
Expand Down Expand Up @@ -396,8 +396,8 @@ export class AccountController {
* description: The request was successful.
* content:
* application/json:
* idToken:
* type: string
* schema:
* $ref: '#/components/schemas/QueryIdTokenResponseBody'
* 400:
* $ref: '#/components/schemas/InvalidRequest'
* 401:
Expand Down
2 changes: 1 addition & 1 deletion src/middleware/auth/auth-gaurd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class APIGuard {
private userInfoFetcher: IUserInfoFetcher;
private oauthProvider: IOAuthProvider;
private static bearerTokenIdentifier = 'Bearer';
private pathSkip = ['/swagger', '/static', '/logto', '/account/bootstrap', '/admin/webhook'];
private pathSkip = ['/swagger', '/admin/swagger', '/static', '/logto', '/account/bootstrap', '/admin/webhook'];

constructor(authRuleRepository: AuthRuleRepository, oauthProvider: IOAuthProvider) {
this.authRuleRepository = authRuleRepository;
Expand Down
2 changes: 1 addition & 1 deletion src/middleware/auth/user-info-fetcher/swagger-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class SwaggerUserInfoFetcher extends UserInfoHelper implements IUserInfoF
// If the user is not authenticated - return error
if (!request.user.isAuthenticated) {
return response.status(StatusCodes.UNAUTHORIZED).json({
error: "Unauthorized error: Seems like you are not authenticated. Please follow the authentication process using 'LogIn' button",
error: "Unauthorized error: Seems like you are not authenticated. Please follow the authentication process using 'Authorize' button",
} satisfies UnsuccessfulResponseBody);
}
// Tries to get customerId from the logTo user structure
Expand Down
14 changes: 14 additions & 0 deletions src/static/swagger-admin-options.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,19 @@
{
"name": "API Key"
}
],
"components": {
"securitySchemes": {
"ApiKeyAuth": {
"type": "apiKey",
"name": "x-api-key",
"in": "header"
}
}
},
"security": [
{
"ApiKeyAuth": []
}
]
}
Loading

0 comments on commit 01e6ab8

Please sign in to comment.