Skip to content
This repository has been archived by the owner on Oct 24, 2024. It is now read-only.

Commit

Permalink
[configuration-validation] convert to typescript (release 1.0.0) (#879)
Browse files Browse the repository at this point in the history
  • Loading branch information
aarongranick-okta authored Aug 29, 2020
1 parent 91963e5 commit a5880c6
Show file tree
Hide file tree
Showing 13 changed files with 3,829 additions and 2,948 deletions.
11 changes: 0 additions & 11 deletions packages/configuration-validation/.babelrc

This file was deleted.

1 change: 1 addition & 0 deletions packages/configuration-validation/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist
34 changes: 30 additions & 4 deletions packages/configuration-validation/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
// https://eslint.org/docs/user-guide/configuring

module.exports = {
extends: [ 'eslint:recommended' ],
parser: "babel-eslint",
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:jest/recommended',
],
plugins: [
'@typescript-eslint',
'jest'
],
parser: '@typescript-eslint/parser',
env: {
node: true,
es6: true,
jest: true
}
'jest/globals': true
},
overrides: [
{
files: ['test/**/*.ts'],
rules: {
'jest/no-disabled-tests': 'warn',
'jest/no-focused-tests': 'error',
'jest/no-identical-title': 'error',
'jest/prefer-to-have-length': 'warn',
'jest/valid-expect': 'error',
'@typescript-eslint/no-var-requires': 0,
'@typescript-eslint/explicit-function-return-type': 0,
'@typescript-eslint/camelcase': 0,
'@typescript-eslint/no-empty-function': 0,
'@typescript-eslint/no-explicit-any': 0
}
}
]
};
10 changes: 10 additions & 0 deletions packages/configuration-validation/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const presets = ['@babel/preset-env'];
const plugins = [];

// Process typescript when running in jest
if (process.env.NODE_ENV === 'test') {
presets.unshift('@babel/preset-typescript');
plugins.unshift('@babel/plugin-transform-typescript');
}

module.exports = { presets, plugins };
42 changes: 33 additions & 9 deletions packages/configuration-validation/package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
{
"name": "@okta/configuration-validation",
"version": "0.4.3",
"version": "1.0.0",
"description": "Configuration validation support for Okta JavaScript SDKs",
"main": "./dist/lib.js",
"types": "./dist/lib.d.ts",
"files": [
"dist",
"src"
],
"scripts": {
"build": "babel src -d dist",
"lint": "eslint .",
"clean": "rimraf dist",
"build": "tsc",
"lint": "eslint . && tsc -p test",
"prepare": "yarn build",
"test": "yarn lint && yarn test:unit",
"test:unit": "jest test/"
Expand All @@ -32,17 +34,39 @@
},
"homepage": "https://github.com/okta/okta-oidc-js#readme",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-eslint": "^8.1.1",
"babel-preset-env": "^1.7.0",
"@babel/core": "^7.8.0",
"@babel/plugin-transform-typescript": "^7.11.0",
"@babel/preset-env": "^7.8.2",
"@babel/preset-typescript": "^7.10.4",
"@types/jest": "^25.2.3",
"@types/json-schema": "^7.0.5",
"@types/minimatch": "^3.0.3",
"@types/node": "^14.6.1",
"@typescript-eslint/eslint-plugin": "^2.34.0",
"@typescript-eslint/parser": "^2.34.0",
"babel-jest": "^26.3.0",
"deep-extend": "^0.6.0",
"eslint": "^4.7.1",
"jest": "^23.6.0"
"eslint": "^7.7.0",
"eslint-plugin-jest": "^23.20.0",
"jest": "^26.4.2",
"rimraf": "^3.0.2",
"typescript": "^4.0.2"
},
"jest": {
"testEnvironment": "jsdom"
"moduleNameMapper": {
"^@okta/configuration-validation$": "<rootDir>/src/lib"
},
"restoreMocks": true,
"testEnvironment": "jsdom",
"testMatch": [
"**/test/*.{js,ts}"
],
"roots": [
"test"
]
},
"dependencies": {
"@okta/okta-auth-js": "^4.0.0",
"lodash": "^4.17.15"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,33 @@
* See the License for the specific language governing permissions and limitations under the License.
*/

const merge = require('lodash/merge');
class ConfigurationValidationError extends Error {}
import { OktaAuthOptions as BaseOptions } from '@okta/okta-auth-js';

export interface TestingOptions {
disableHttpsCheck?: boolean;
}

// Extend options. Many of these are legacy options and subject to deprecation.
export interface OktaAuthOptions extends BaseOptions {
// legacy: snake case
client_id?: string;
redirect_uri?: string;
response_type?: string;

const configUtil = module.exports;
// legacy: scopes as a space-separated string
scope?: string | string[];

// hoisted: from tokenManager
autoRenew?: boolean;
auto_renew?: boolean;
storage?: string;

// used only by this library
testing?: TestingOptions;
}

import { merge } from 'lodash';
class ConfigurationValidationError extends Error {}

const findDomainURL = 'https://bit.ly/finding-okta-domain';
const findAppCredentialsURL = 'https://bit.ly/finding-okta-app-credentials';
Expand All @@ -27,7 +50,7 @@ const hasProtocol = new RegExp('://');
const hasDomainAdmin = /-admin.(okta|oktapreview|okta-emea).com/;
const endsInPath = new RegExp('/$');

configUtil.buildConfigObject = (config) => {
export const buildConfigObject = (config?: OktaAuthOptions): OktaAuthOptions => {
// See all supported options: https://github.com/okta/okta-auth-js#configuration-reference
// Support for parameters with an underscore will be deprecated in a future release
// camelCase was added 2/11/2019: https://github.com/okta/okta-oidc-js/commit/9b04ada6a01c9d9aca391abf0de3e5ecc9811e64
Expand Down Expand Up @@ -73,7 +96,7 @@ configUtil.buildConfigObject = (config) => {
return normalizedConfig;
}

configUtil.assertIssuer = (issuer, testing = {}) => {
export const assertIssuer = (issuer?: string, testing: TestingOptions = {}): void => {
const copyMessage = 'You can copy your domain from the Okta Developer ' +
'Console. Follow these instructions to find it: ' + findDomainURL;

Expand Down Expand Up @@ -101,31 +124,31 @@ configUtil.assertIssuer = (issuer, testing = {}) => {
}
};

configUtil.assertClientId = (clientId) => {
export const assertClientId = (clientId?: string): void => {
if (!clientId) {
throw new ConfigurationValidationError('Your client ID is missing. ' + copyCredentialsMessage);
} else if (clientId.match(/{clientId}/)) {
throw new ConfigurationValidationError('Replace {clientId} with the client ID of your Application. ' + copyCredentialsMessage);
}
};

configUtil.assertClientSecret = (clientSecret) => {
export const assertClientSecret = (clientSecret?: string): void => {
if (!clientSecret) {
throw new ConfigurationValidationError('Your client secret is missing. ' + copyCredentialsMessage);
} else if (clientSecret.match(/{clientSecret}/)) {
throw new ConfigurationValidationError('Replace {clientSecret} with the client secret of your Application. ' + copyCredentialsMessage);
}
};

configUtil.assertRedirectUri = (redirectUri) => {
export const assertRedirectUri = (redirectUri?: string): void => {
if (!redirectUri) {
throw new ConfigurationValidationError('Your redirect URI is missing.');
} else if (redirectUri.match(/{redirectUri}/)) {
throw new ConfigurationValidationError('Replace {redirectUri} with the redirect URI of your Application.');
}
};

configUtil.assertAppBaseUrl = (appBaseUrl) => {
export const assertAppBaseUrl = (appBaseUrl?: string): void => {
if (!appBaseUrl) {
throw new ConfigurationValidationError('Your appBaseUrl is missing.');
} else if (appBaseUrl.match(/{appBaseUrl}/)) {
Expand Down
119 changes: 119 additions & 0 deletions packages/configuration-validation/test/assert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import {
assertIssuer,
assertClientId,
assertClientSecret,
assertRedirectUri,
assertAppBaseUrl,
} from '@okta/configuration-validation';

const findDomainMessage = 'You can copy your domain from the Okta Developer ' +
'Console. Follow these instructions to find it: https://bit.ly/finding-okta-domain';

const findCredentialsMessage = 'You can copy it from the Okta Developer Console ' +
'in the details for the Application you created. Follow these instructions to ' +
'find it: https://bit.ly/finding-okta-app-credentials';

describe('assertIssuer', () => {
it('should throw if no issuer is provided', () => {
const errorMsg = `Your Okta URL is missing. ${findDomainMessage}`;
expect(() => assertIssuer()).toThrow(errorMsg);
});

it('should throw if an issuer that does not contain https is provided', () => {
const errorMsg = `Your Okta URL must start with https. Current value: http://foo.com. ${findDomainMessage}`;
expect(() => assertIssuer('http://foo.com')).toThrow(errorMsg);
});

it('should not throw if https issuer validation is skipped', () => {
jest.spyOn(console, 'warn').mockImplementation(() => {}); // silence for testing
const errorMsg = `Your Okta URL must start with https. Current value: http://foo.com. ${findDomainMessage}`;
expect(() => {
assertIssuer('http://foo.com', {
disableHttpsCheck: true
})
}).not.toThrow(errorMsg);
/* eslint-disable-next-line no-console */
expect(console.warn).toBeCalledWith('Warning: HTTPS check is disabled. This allows for insecure configurations and is NOT recommended for production use.');
});

it('should throw if an issuer matching {yourOktaDomain} is provided', () => {
const errorMsg = `Replace {yourOktaDomain} with your Okta domain. ${findDomainMessage}`;
expect(() => assertIssuer('https://{yourOktaDomain}')).toThrow(errorMsg);
});

it('should throw if an issuer matching -admin.okta.com is provided', () => {
const errorMsg = 'Your Okta domain should not contain -admin. Current value: ' +
`https://foo-admin.okta.com. ${findDomainMessage}`;
expect(() => assertIssuer('https://foo-admin.okta.com')).toThrow(errorMsg);
});

it('should throw if an issuer matching -admin.oktapreview.com is provided', () => {
const errorMsg = 'Your Okta domain should not contain -admin. Current value: ' +
`https://foo-admin.oktapreview.com. ${findDomainMessage}`;
expect(() => assertIssuer('https://foo-admin.oktapreview.com')).toThrow(errorMsg);
});

it('should throw if an issuer matching -admin.okta-emea.com is provided', () => {
const errorMsg = 'Your Okta domain should not contain -admin. Current value: ' +
`https://foo-admin.okta-emea.com. ${findDomainMessage}`;
expect(() => assertIssuer('https://foo-admin.okta-emea.com')).toThrow(errorMsg);
});
});

describe('assertClientId', () => {
it('should throw if the client_id is not provided', () => {
const errorMsg = `Your client ID is missing. ${findCredentialsMessage}`;
expect(() => assertClientId()).toThrow(errorMsg);
});

it('should throw if a client_id matching {clientId} is provided', () => {
const errorMsg = `Replace {clientId} with the client ID of your Application. ${findCredentialsMessage}`;
expect(() => assertClientId('{clientId}')).toThrow(errorMsg);
});
});

describe('assertClientSecret', () => {
it('should throw if the client_secret is not provided', () => {
const errorMsg = `Your client secret is missing. ${findCredentialsMessage}`;
expect(() => assertClientSecret()).toThrow(errorMsg);
});

it('should throw if a client_secret matching {clientSecret} is provided', () => {
const errorMsg = `Replace {clientSecret} with the client secret of your Application. ${findCredentialsMessage}`;
expect(() => assertClientSecret('{clientSecret}')).toThrow(errorMsg);
});
});

describe('assertRedirectUri', () => {
it('should throw if the redirect_uri is not provided', () => {
const errorMsg = 'Your redirect URI is missing.';
expect(() => assertRedirectUri()).toThrow(errorMsg);
});

it('should throw if a redirect_uri matching {redirectUri} is provided', () => {
const errorMsg = 'Replace {redirectUri} with the redirect URI of your Application.'
expect(() => assertRedirectUri('{redirectUri}')).toThrow(errorMsg);
});
});

describe('assertAppBaseUrl', () => {
it('should throw if the appBaseUrl is not provided', () => {
const errorMsg = 'Your appBaseUrl is missing.';
expect(() => assertAppBaseUrl()).toThrow(errorMsg);
});

it('should throw if a appBaseUrl matching {appBaseUrl} is provided', () => {
const errorMsg = 'Replace {appBaseUrl} with the base URL of your Application.'
expect(() => assertAppBaseUrl('{appBaseUrl}')).toThrow(errorMsg);
});

it('should throw if an appBaseUrl without a protocol is provided', () => {
const errorMsg = 'Your appBaseUrl must contain a protocol (e.g. https://). Current value: foo.example.com.';
expect(() => assertAppBaseUrl('foo.example.com')).toThrow(errorMsg);
});

it('should throw if an appBaseUrl that ends in a slash is provided', () => {
const errorMsg = `Your appBaseUrl must not end in a '/'. Current value: https://foo.example.com/.`;
expect(() => assertAppBaseUrl('https://foo.example.com/')).toThrow(errorMsg);
});
});
Loading

0 comments on commit a5880c6

Please sign in to comment.