Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
nulltoken committed Oct 4, 2020
1 parent e0f4858 commit c3e4e97
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 48 deletions.
15 changes: 13 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,27 @@
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint", "jest"],
"plugins": [
"@typescript-eslint",
"jest",
"jsdoc"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"prettier/@typescript-eslint",
"plugin:prettier/recommended",
"plugin:jsdoc/recommended",
"plugin:jest/recommended"
],
"rules": {
"no-console": "error"
"no-console": "error",
"jsdoc/require-jsdoc": [
"warn",
{
"publicOnly": true
}
]
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"build": "tsc -p ./tsconfig.build.json",
"cleanup:testresults": "rimraf TestResults",
"prelint": "tsc --noEmit",
"lint": "eslint --cache --cache-location .cache/ --ext=.js,.ts src test",
"lint": "eslint --cache --cache-location .cache/ --ext=.js,.ts src test --max-warnings 0",
"pretest": "yarn cleanup:testresults && yarn lint",
"test": "yarn jest"
},
Expand Down
2 changes: 2 additions & 0 deletions src/lib/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable jsdoc/require-jsdoc */

import { AssertionError } from 'assert';
import type jwt from 'jsonwebtoken';
import isPlainObject from 'lodash.isplainobject';
Expand Down
15 changes: 4 additions & 11 deletions src/lib/http-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,15 @@ import { AddressInfo } from 'net';
* Provides a restartable wrapper for http.CreateServer().
*/
export class HttpServer {
/**
* @callback requestHandler
* @param {IncomingMessage} request The incoming message.
* @param {ServerResponse} response The server response.
*/
// Can't use symbol as an indexer because of https://github.com/microsoft/TypeScript/issues/1863
// Switching to ECMAScript private fields https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/#ecmascript-private-fields
#server: Server;

/**
* Creates a new instance of HttpServer.
*
* @param {requestHandler} requestListener The function that will handle the server's requests.
* @param {RequestListener} requestListener The function that will handle the server's requests.
*/

// Can't use symbol as an indexer because of https://github.com/microsoft/TypeScript/issues/1863
// Switching to ECMAScript private fields https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/#ecmascript-private-fields
#server: Server;

constructor(requestListener: RequestListener) {
this.#server = createServer(requestListener);
}
Expand Down
28 changes: 19 additions & 9 deletions src/lib/jwk-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

/**
* JWK Store library
*
* @module lib/jwk-store
*/

Expand All @@ -37,19 +38,25 @@ export class JWKStore {

/**
* Generates a new random RSA key and adds it into this keystore.
* @param {Number} [size] The size in bits of the new key. Default: 2048.
* @param {String} [kid] The key ID. If omitted, a new random 'kid' will be generated.
* @param {String} [use] The intended use of the key (e.g. 'sig', 'enc'.) Default: 'sig'.
*
* @param {number} [size] The size in bits of the new key. Default: 2048.
* @param {string} [kid] The key ID. If omitted, a new random 'kid' will be generated.
* @param {string} [use] The intended use of the key (e.g. 'sig', 'enc'.) Default: 'sig'.
* @returns {Promise<JWK.Key>} The promise for the generated key.
*/
async generateRSA(size: number, kid?: string, use = 'sig'): Promise<JWK.Key> {
async generateRSA(
size?: number,
kid?: string,
use = 'sig'
): Promise<JWK.Key> {
const key = await this.#store.generate('RSA', size, { kid, use });
this.#keyRotator.add(key);
return key;
}

/**
* Adds a JWK key to this keystore.
*
* @param {JWK.Key} jwk The JWK key to add.
* @returns {Promise<JWK.Key>} The promise for the added key.
*/
Expand All @@ -63,9 +70,10 @@ export class JWKStore {

/**
* Adds a PEM-encoded RSA key to this keystore.
* @param {String} pem The PEM-encoded key to add.
* @param {String} [kid] The key ID. If omitted, a new random 'kid' will be generated.
* @param {String} [use] The intended use of the key (e.g. 'sig', 'enc'.) Default: 'sig'.
*
* @param {string} pem The PEM-encoded key to add.
* @param {string} [kid] The key ID. If omitted, a new random 'kid' will be generated.
* @param {string} [use] The intended use of the key (e.g. 'sig', 'enc'.) Default: 'sig'.
* @returns {Promise<JWK.Key>} The promise for the added key.
*/
async addPEM(pem: string, kid?: string, use = 'sig'): Promise<JWK.Key> {
Expand All @@ -77,7 +85,8 @@ export class JWKStore {
/**
* Gets a key from the keystore in a round-robin fashion.
* If a 'kid' is provided, only keys that match will be taken into account.
* @param {String} [kid] The optional key identifier to match keys against.
*
* @param {string} [kid] The optional key identifier to match keys against.
* @returns {JWK.Key | null} The retrieved key.
*/
get(kid?: string): JWK.Key | null {
Expand All @@ -87,7 +96,8 @@ export class JWKStore {
/**
* Generates a JSON representation of this keystore, which conforms
* to a JWK Set from {I-D.ietf-jose-json-web-key}.
* @param {Boolean} [isPrivate = false] `true` if the private fields
*
* @param {boolean} [isPrivate = false] `true` if the private fields
* of stored keys are to be included.
* @returns {Object} The JSON representation of this keystore.
*/
Expand Down
22 changes: 8 additions & 14 deletions src/lib/oauth2-issuer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,19 @@ import type { Header, Payload, scopesOrTransform } from './types';
*/
export class OAuth2Issuer extends EventEmitter {
/**
* Creates a new instance of HttpServer.
* Sets or returns the issuer URL.
*
* @type {string}
*/

url: string | null;

#keys: JWKStore;

/**
* Creates a new instance of HttpServer.
*/
constructor() {
super();
/**
* Sets or returns the issuer URL.
*
* @type {string}
*/
this.url = null;

this.#keys = new JWKStore();
Expand Down Expand Up @@ -73,7 +73,7 @@ export class OAuth2Issuer extends EventEmitter {
*/
buildToken(
signed: boolean,
kid: string | undefined,
kid?: string,
scopesOrTransform?: scopesOrTransform,
expiresIn = 3600
): string {
Expand Down Expand Up @@ -130,9 +130,6 @@ export class OAuth2Issuer extends EventEmitter {
}
}

/**
* @param key
*/
function getKeyAlg(key: JWK.Key): jwt.Algorithm {
if (key.alg) {
assertIsAlgorithm(key.alg);
Expand All @@ -153,9 +150,6 @@ function getKeyAlg(key: JWK.Key): jwt.Algorithm {
}
}

/**
* @param key
*/
function getSecret(key: JWK.Key): string {
switch (key.kty) {
case 'RSA':
Expand Down
13 changes: 10 additions & 3 deletions src/lib/oauth2-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

/**
* OAuth2 HTTP Server library
*
* @module lib/oauth2-server
*/

Expand Down Expand Up @@ -49,6 +50,7 @@ export class OAuth2Server extends HttpServer {

/**
* Returns the OAuth2Issuer instance used by the server.
*
* @type {OAuth2Issuer}
*/
get issuer(): OAuth2Issuer {
Expand All @@ -57,6 +59,7 @@ export class OAuth2Server extends HttpServer {

/**
* Returns the OAuth2Service instance used by the server.
*
* @type {OAuth2Service}
*/
get service(): OAuth2Service {
Expand All @@ -65,7 +68,8 @@ export class OAuth2Server extends HttpServer {

/**
* Returns a value indicating whether or not the server is listening for connections.
* @type {Boolean}
*
* @type {boolean}
*/
get listening(): boolean {
return super.listening;
Expand All @@ -74,6 +78,7 @@ export class OAuth2Server extends HttpServer {
/**
* Returns the bound address, family name and port where the server is listening,
* or null if the server has not been started.
*
* @returns {AddressInfo} The server bound address information.
*/
address(): AddressInfo {
Expand All @@ -88,8 +93,9 @@ export class OAuth2Server extends HttpServer {

/**
* Starts the server.
* @param {Number} [port] Port number. If omitted, it will be assigned by the operating system.
* @param {String} [host] Host name.
*
* @param {number} [port] Port number. If omitted, it will be assigned by the operating system.
* @param {string} [host] Host name.
* @returns {Promise<void>} A promise that resolves when the server has been started.
*/
async start(port?: number, host?: string): Promise<Server> {
Expand All @@ -105,6 +111,7 @@ export class OAuth2Server extends HttpServer {

/**
* Stops the server.
*
* @returns {Promise} Resolves when the server has been stopped.
*/
async stop(): Promise<void> {
Expand Down
21 changes: 15 additions & 6 deletions src/lib/oauth2-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

/**
* OAuth2 Service library
*
* @module lib/oauth2-service
*/

Expand Down Expand Up @@ -43,6 +44,7 @@ const REVOKE_PATH = '/revoke';
export class OAuth2Service extends EventEmitter {
/**
* Creates a new instance of OAuth2Server.
*
* @param {OAuth2Issuer} oauth2Issuer The OAuth2Issuer instance
* that will be offered through the service.
*/
Expand All @@ -62,6 +64,7 @@ export class OAuth2Service extends EventEmitter {

/**
* Returns the OAuth2Issuer instance bound to this service.
*
* @type {OAuth2Issuer}
*/
get issuer(): OAuth2Issuer {
Expand All @@ -70,12 +73,13 @@ export class OAuth2Service extends EventEmitter {

/**
* Builds a JWT with a key in the keystore. The key will be selected in a round-robin fashion.
* @param {Boolean} signed A value that indicates whether or not to sign the JWT.
*
* @param {boolean} signed A value that indicates whether or not to sign the JWT.
* @param {scopesOrTransform} [scopesOrTransform] A scope, array of scopes,
* or JWT transformation callback.
* @param {Number} [expiresIn] Time in seconds for the JWT to expire. Default: 3600 seconds.
* @param {number} [expiresIn] Time in seconds for the JWT to expire. Default: 3600 seconds.
* @param {IncomingMessage} req The incoming HTTP request.
* @returns {String} The produced JWT.
* @returns {string} The produced JWT.
* @fires OAuth2Service#beforeTokenSigning
*/
buildToken(
Expand All @@ -87,6 +91,7 @@ export class OAuth2Service extends EventEmitter {
this.issuer.once('beforeSigning', (token) => {
/**
* Before token signing event.
*
* @event OAuth2Service#beforeTokenSigning
* @param {object} token The unsigned JWT header and payload.
* @param {object} token.header The JWT header.
Expand All @@ -106,6 +111,7 @@ export class OAuth2Service extends EventEmitter {

/**
* Returns a request handler to be used as a callback for http.createServer().
*
* @type {Function}
*/
get requestHandler(): Express {
Expand Down Expand Up @@ -248,10 +254,11 @@ export class OAuth2Service extends EventEmitter {

/**
* Before token response event.
*
* @event OAuth2Service#beforeResponse
* @param {object} response The response body and status code.
* @param {object} response.body The body of the response.
* @param {Number} response.statusCode The HTTP status code of the response.
* @param {number} response.statusCode The HTTP status code of the response.
* @param {IncomingMessage} req The incoming HTTP request.
*/
this.emit('beforeResponse', tokenEndpointResponse, req);
Expand Down Expand Up @@ -305,10 +312,11 @@ export class OAuth2Service extends EventEmitter {

/**
* Before user info event.
*
* @event OAuth2Service#beforeUserinfo
* @param {object} response The response body and status code.
* @param {object} response.body The body of the response.
* @param {Number} response.statusCode The HTTP status code of the response.
* @param {number} response.statusCode The HTTP status code of the response.
* @param {IncomingMessage} req The incoming HTTP request.
*/
this.emit('beforeUserinfo', userInfoResponse, req);
Expand All @@ -324,10 +332,11 @@ export class OAuth2Service extends EventEmitter {

/**
* Before revoke event.
*
* @event OAuth2Service#beforeRevoke
* @param {object} response The response body and status code.
* @param {object} response.body The body of the response.
* @param {Number} response.statusCode The HTTP status code of the response.
* @param {number} response.statusCode The HTTP status code of the response.
* @param {IncomingMessage} req The incoming HTTP request.
*/
this.emit('beforeRevoke', revokeResponse, req);
Expand Down
5 changes: 3 additions & 2 deletions test/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"rules": {
"prettier/prettier": 0,
"prettier/prettier": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-non-null-assertion": "off"
"@typescript-eslint/no-non-null-assertion": "off",
"jsdoc/require-jsdoc": "off"
}
}

0 comments on commit c3e4e97

Please sign in to comment.