Comparing version 0.2.4 to 1.0.0
274
index.js
@@ -17,274 +17,2 @@ /* | ||
*/ | ||
const Promise = require('bluebird'); | ||
const promised_request = Promise.promisify(require('request')); | ||
const jsonwebtoken = require('jsonwebtoken'); | ||
const pem = require('pem'); | ||
const AuthenticationError = require('./lib/AuthenticationError'); | ||
const promisedGetPublicKey = Promise.promisify(pem.getPublicKey); | ||
const wellKnowns = {}; | ||
Object.defineProperties(exports, { | ||
'BYU_JWT_HEADER_CURRENT': { | ||
value: 'x-jwt-assertion', | ||
writable: false | ||
}, | ||
'BYU_JWT_HEADER_ORIGINAL': { | ||
value: 'x-jwt-assertion-original', | ||
writable: false | ||
}, | ||
'cacheWellknowns': { | ||
value: false, | ||
writable: true | ||
}, | ||
'AuthenticationError': { | ||
value: AuthenticationError, | ||
writable: false | ||
}, | ||
'JsonWebTokenError': { | ||
value: jsonwebtoken.JsonWebTokenError, | ||
writable: false | ||
}, | ||
'NotBeforeError': { | ||
value: jsonwebtoken.NotBeforeError, | ||
writable: false | ||
}, | ||
'TokenExpiredError': { | ||
value: jsonwebtoken.TokenExpiredError, | ||
writable: false | ||
}, | ||
}); | ||
exports.getWellKnown = function (wellKnownURL) { | ||
if (wellKnowns.hasOwnProperty(wellKnownURL) && exports.cacheWellknowns) { | ||
return wellKnowns[wellKnownURL].promise; | ||
} | ||
else { | ||
wellKnowns[wellKnownURL] = {}; | ||
const options = { | ||
url: wellKnownURL, | ||
method: 'GET', | ||
headers: { | ||
'User-Agent': 'BYU-JWT-Node-SDK/1.0 (' + process.version + ')' | ||
} | ||
}; | ||
wellKnowns[wellKnownURL].promise = promised_request(options) | ||
.then(function (result) { | ||
wellKnowns[wellKnownURL].openid_configuration = JSON.parse(result.body); | ||
return wellKnowns[wellKnownURL].openid_configuration; | ||
} | ||
); | ||
return wellKnowns[wellKnownURL].promise; | ||
} | ||
}; | ||
// Just return the public key. | ||
exports.getPublicKey = function (wellKnownURL) { | ||
return exports.getWellKnown(wellKnownURL) | ||
.then(function (result) { | ||
return getPublicKeyUtil(result); | ||
} | ||
); | ||
}; | ||
function getPublicKeyUtil(wellKnownResult) { | ||
const openid_configuration = wellKnownResult; | ||
const jwks_uri = openid_configuration.jwks_uri; | ||
algorithms = openid_configuration.id_token_signing_alg_values_supported; | ||
const options = { | ||
url: jwks_uri, | ||
method: 'GET' | ||
}; | ||
return promised_request(options) | ||
.then(function (result) { | ||
const keys = JSON.parse(result.body).keys; | ||
let cert = keys[0].x5c[0]; | ||
//format cert | ||
cert = cert.replace(/(.{64})/g, '$1\n'); | ||
const prefix = '-----BEGIN CERTIFICATE-----\n'; | ||
const postfix = '\n-----END CERTIFICATE-----'; | ||
cert = prefix + cert + postfix; | ||
//extract public key | ||
return promisedGetPublicKey(cert); | ||
}); | ||
} | ||
/** | ||
* @param jwt | ||
* @param wellKnownURL | ||
* @returns {*} | ||
*/ | ||
exports.verifyJWT = function (jwt, wellKnownURL) { | ||
if (process.env.NODE_ENV === 'mock') { | ||
return new Promise.resolve(jsonwebtoken.decode(jwt)); | ||
} | ||
else { | ||
var algorithms; | ||
return exports.getWellKnown(wellKnownURL) | ||
.then(getPublicKeyUtil) | ||
.then(function (result) { | ||
return new Promise(function (resolve, reject) { | ||
const key = result.publicKey; | ||
return jsonwebtoken.verify(jwt, key, {algorithms: algorithms}, function (err, decoded) { | ||
if (err) return reject(err); | ||
resolve(decoded); | ||
}); | ||
}); | ||
}); | ||
} | ||
}; | ||
/** | ||
* @param jwt | ||
* @param wellKnownURL | ||
*/ | ||
exports.jwtDecoded = function (jwt, wellKnownURL) { | ||
return exports.verifyJWT(jwt, wellKnownURL) | ||
.then(function (jwtDecoded) { | ||
const hasResourceOwner = typeof jwtDecoded['http://byu.edu/claims/resourceowner_byu_id'] !== 'undefined'; | ||
jwtDecoded.byu = {}; | ||
jwtDecoded.byu.client = { | ||
byuId: jwtDecoded['http://byu.edu/claims/client_byu_id'], | ||
claimSource: jwtDecoded['http://byu.edu/claims/client_claim_source'], | ||
netId: jwtDecoded['http://byu.edu/claims/client_net_id'], | ||
personId: jwtDecoded['http://byu.edu/claims/client_person_id'], | ||
preferredFirstName: jwtDecoded['http://byu.edu/claims/client_preferred_first_name'], | ||
prefix: jwtDecoded['http://byu.edu/claims/client_name_prefix'], | ||
restOfName: jwtDecoded['http://byu.edu/claims/client_rest_of_name'], | ||
sortName: jwtDecoded['http://byu.edu/claims/client_sort_name'], | ||
subscriberNetId: jwtDecoded['http://byu.edu/claims/client_subscriber_net_id'], | ||
suffix: jwtDecoded['http://byu.edu/claims/client_name_prefix'], | ||
surname: jwtDecoded['http://byu.edu/claims/client_surname'], | ||
surnamePosition: jwtDecoded['http://byu.edu/claims/client_surname_position'] | ||
}; | ||
if (hasResourceOwner) { | ||
jwtDecoded.byu.resourceOwner = { | ||
byuId: jwtDecoded['http://byu.edu/claims/resourceowner_byu_id'], | ||
netId: jwtDecoded['http://byu.edu/claims/resourceowner_net_id'], | ||
personId: jwtDecoded['http://byu.edu/claims/resourceowner_person_id'], | ||
preferredFirstName: jwtDecoded['http://byu.edu/claims/resourceowner_preferred_first_name'], | ||
prefix: jwtDecoded['http://byu.edu/claims/resourceowner_prefix'], | ||
restOfName: jwtDecoded['http://byu.edu/claims/resourceowner_rest_of_name'], | ||
sortName: jwtDecoded['http://byu.edu/claims/resourceowner_sort_name'], | ||
suffix: jwtDecoded['http://byu.edu/claims/resourceowner_suffix'], | ||
surname: jwtDecoded['http://byu.edu/claims/resourceowner_surname'], | ||
surnamePosition: jwtDecoded['http://byu.edu/claims/resourceowner_surname_position'] | ||
}; | ||
} | ||
const webresCheckKey = hasResourceOwner ? 'resourceOwner' : 'client'; | ||
jwtDecoded.byu.webresCheck = { | ||
byuId: jwtDecoded.byu[webresCheckKey].byuId, | ||
netId: jwtDecoded.byu[webresCheckKey].netId, | ||
personId: jwtDecoded.byu[webresCheckKey].personId | ||
}; | ||
jwtDecoded.wso2 = { | ||
apiContext: jwtDecoded['http://wso2.org/claims/apicontext'], | ||
application: { | ||
id: jwtDecoded['http://wso2.org/claims/applicationid'], | ||
name: jwtDecoded['http://wso2.org/claims/applicationname'], | ||
tier: jwtDecoded['http://wso2.org/claims/applicationtier'] | ||
}, | ||
clientId: jwtDecoded['http://wso2.org/claims/client_id'], | ||
endUser: jwtDecoded['http://wso2.org/claims/enduser'], | ||
endUserTenantId: jwtDecoded['http://wso2.org/claims/enduserTenantId'], | ||
keyType: jwtDecoded['http://wso2.org/claims/keytype'], | ||
subscriber: jwtDecoded['http://wso2.org/claims/subscriber'], | ||
tier: jwtDecoded['http://wso2.org/claims/tier'], | ||
userType: jwtDecoded['http://wso2.org/claims/usertype'], | ||
version: jwtDecoded['http://wso2.org/claims/version'] | ||
}; | ||
return jwtDecoded; | ||
}); | ||
}; | ||
/** | ||
* @param headers | ||
* @param wellKnownURL | ||
* @param [basePath] | ||
*/ | ||
exports.authenticate = function validateJWTsFromHeaders(headers, wellKnownURL, basePath) { | ||
const jwtPromises = []; | ||
if (headers[exports.BYU_JWT_HEADER_ORIGINAL]) { | ||
const originalJwt = headers[exports.BYU_JWT_HEADER_ORIGINAL]; | ||
jwtPromises.push(exports.jwtDecoded(originalJwt, wellKnownURL)); | ||
} | ||
if (headers[exports.BYU_JWT_HEADER_CURRENT]) { | ||
const currentJwt = headers[exports.BYU_JWT_HEADER_CURRENT]; | ||
jwtPromises.push(exports.jwtDecoded(currentJwt, wellKnownURL)); | ||
} | ||
// If this came through WSO2, the request should have at least one of these | ||
if (jwtPromises.length === 0) { | ||
return Promise.reject(new AuthenticationError('No expected JWTs found')); | ||
} | ||
return Promise.settle(jwtPromises) | ||
.then(verifiedResults => { | ||
const verifiedJwts = {}; | ||
// Check that they're valid JWTs | ||
const currentJwtIndex = verifiedResults.length > 1 ? 1 : 0; | ||
const currentJwtResult = verifiedResults[currentJwtIndex]._settledValue(); | ||
if (verifiedResults[currentJwtIndex].isFulfilled()) { | ||
verifiedJwts.current = currentJwtResult; | ||
} else if (currentJwtResult instanceof jsonwebtoken.TokenExpiredError) { | ||
throw new AuthenticationError('Expired JWT', currentJwtResult); | ||
} else { | ||
throw new AuthenticationError('Invalid JWT', currentJwtResult); | ||
} | ||
if (verifiedResults.length > 1) { | ||
const originalJwtResult = verifiedResults[0]._settledValue(); | ||
if (verifiedResults[0].isFulfilled()) { | ||
verifiedJwts.original = originalJwtResult; | ||
} else if (originalJwtResult instanceof jsonwebtoken.TokenExpiredError) { | ||
throw new AuthenticationError('Expired Original JWT', originalJwtResult); | ||
} else { | ||
throw new AuthenticationError('Invalid Original JWT', originalJwtResult); | ||
} | ||
} | ||
// Check that user is calling our API and not just reusing a JWT obtained elsewhere | ||
if (basePath && typeof basePath === 'string') { | ||
if (process.env.NODE_ENV !== 'mock') { // To skip this check when testing | ||
const context_from_current_jwt = verifiedJwts.current['http://wso2.org/claims/apicontext']; | ||
if (!context_from_current_jwt.startsWith(basePath)) { | ||
throw new AuthenticationError('Invalid API context in JWT.'); | ||
} | ||
} | ||
} | ||
// For convenience | ||
verifiedJwts.originalJwt = headers[exports.BYU_JWT_HEADER_ORIGINAL] || headers[exports.BYU_JWT_HEADER_CURRENT]; | ||
verifiedJwts.prioritizedClaims = getPrioritizedClaims(verifiedJwts); | ||
return verifiedJwts; | ||
}); | ||
}; | ||
/** | ||
* Returns one of the following claims objects, in order of precedence: | ||
* 1) Original Resource Owner | ||
* 2) Current Resource Owner | ||
* 3) Original Client | ||
* 4) Current Client | ||
*/ | ||
function getPrioritizedClaims(verifiedJwts) { | ||
if (verifiedJwts.original && verifiedJwts.original.byu.resourceOwner) return verifiedJwts.original.byu.resourceOwner; | ||
if (verifiedJwts.current && verifiedJwts.current.byu.resourceOwner) return verifiedJwts.current.byu.resourceOwner; | ||
if (verifiedJwts.original && verifiedJwts.original.byu.client) return verifiedJwts.original.byu.client; | ||
return verifiedJwts.current.byu.client; | ||
} | ||
module.exports = require('./lib') |
@@ -0,0 +0,0 @@ /** |
{ | ||
"name": "byu-jwt", | ||
"version": "0.2.4", | ||
"version": "1.0.0", | ||
"description": "The byu-jwt module provides helpful functions to retrieve a specified BYU .well-known URL and verify BYU signed JWTs.", | ||
@@ -15,6 +15,7 @@ "main": "index.js", | ||
}, | ||
"scripts": { | ||
"test": "mocha test" | ||
}, | ||
"homepage": "https://github.com/byu-oit/byu-jwt-nodejs#readme", | ||
"dependencies": { | ||
"request": "^2.87.0", | ||
"bluebird": "^3.5.1", | ||
"jsonwebtoken": "^8.2.1", | ||
@@ -24,4 +25,7 @@ "pem": "^1.12.5" | ||
"devDependencies": { | ||
"mocha": "^5.2.0" | ||
"aws-sdk": "^2.263.1", | ||
"chai": "^4.1.2", | ||
"mocha": "^5.2.0", | ||
"request": "^2.87.0" | ||
} | ||
} |
371
README.md
# byu-jwt | ||
The *byu-jwt* module provides helpful functions to retrieve a specified BYU *.well-known* URL and verify BYU signed JWTs. | ||
This package provides helpful functions for using validating and using BYU's JWTs. | ||
## Table of Contents | ||
- [API](#api) | ||
- [Constructor](#constructor) | ||
- [Authenticate](#authenticate) | ||
- [Authenticate University API Middleware](#authenticate-university-api-middleware) | ||
- [Decode JWT](#decode-jwt) | ||
- [Get OpenID Configuration](#get-openid-configuration) | ||
- [Get Public Key](#get-public-key) | ||
- [Verify JWT](#verify-jwt) | ||
- [Cache Time to Live](#cache-time-to-live) | ||
- [Static Constants](#static-constants) | ||
- [Testing](#testing) | ||
## API | ||
### JWT Header Names | ||
BYU's API Manager creates an HTTP header that contains a signed JWT(https://jwt.io). The names of the designed BYU signed headers can be referenced here for lookup convenience. | ||
### Constructor | ||
<i>Note: The values of the headers are in lowercase because Node.js converts the headers by convention.</i> | ||
`ByuJWT ([ options ])` | ||
[https://github.com/nodejs/node-v0.x-archive/issues/1954](https://github.com/nodejs/node-v0.x-archive/issues/1954) | ||
[https://nodejs.org/api/http.html#http_response_getheaders](https://nodejs.org/api/http.html#http_response_getheaders) | ||
#### BYU_JWT_HEADER_CURRENT | ||
The property containing the name of the HTTP header that contains the BYU signed JWT sent directly from BYU's API Manager. | ||
**Parameters** | ||
Value is `x-jwt-assertion`. | ||
- *options* - An `object` that defines the options for this instance of the byu-jwt library: | ||
**Example** | ||
| Option | Description | Default | | ||
| ------ | ----------- | ------- | | ||
| basePath | A `string` that the JWT's API context must begin with. This validates that the JWT came from a server that starts with this path. | `""` | | ||
| cacheTTL | The `number` of minutes to cache the OpenID configuration for. | `10` | | ||
| development | A `boolean` then when set to `true` will bypass JWT validation. This cannot be set to `true` when the `NODE_ENV` environment variable is set to `"production"`. Also, when set to `true` expect to see a lot of warning message on your console. | `false` | | ||
The example uses the property to retrieve the header from the request. | ||
**Returns** an instance of the [ByuJWT](#constructor) | ||
```js | ||
const byuJwt = require('byu-jwt'); | ||
... | ||
var current_jwt = req.headers[byuJwt.BYU_JWT_HEADER_CURRENT]; | ||
byuJwt.verifyJWT(current_jwt, 'http://the-wellknown-url.com'); | ||
``` | ||
### Authenticate | ||
#### BYU_JWT_HEADER_ORIGINAL | ||
The property containing the name of the HTTP header that contains the BYU signed JWT forwarded on from a service that received the BYU signed JWT sent directly from BYU's API Manager. | ||
Check the headers to see if the requester is authenticated. | ||
Value is `x-jwt-assertion-original`. | ||
`ByuJWT.prototype.authenticate ( headers )` | ||
**Example** | ||
**Parameters** | ||
The example uses the property to retrieve the header from the request. | ||
- *headers* - An `object` representing the header names and values. This method is looking specifically for two headers: | ||
```js | ||
const byuJwt = require('byu-jwt'); | ||
... | ||
var original_jwt = req.headers[byuJwt.BYU_JWT_HEADER_ORIGINAL]; | ||
byuJwt.verifyJWT(current_jwt, 'http://the-wellknown-url.com'); | ||
``` | ||
1. `x-jwt-assertion` is a header that contains the JWT for the current client. | ||
### cacheWellknowns | ||
2. `x-jwt-assertion-original` is a header that contains the JWT for the original requester. This value should be set if a client is making an authenticated request on behalf of a different client. | ||
A property that can be set to enable or disable caching of the responses from well known URLs. | ||
**Returns** a promise that, if authenticated, resolves to an object with some of these properties: | ||
Defaults to `false`. | ||
- *current* - The current client's [decoded JWT](#decode-jwt). | ||
**Example** | ||
- *original* - The original client's [decoded JWT](#decode-jwt). This property may not be defined. | ||
The example will set the module to cache well known URL responses: | ||
- *originalJWT* - The JWT string provided by the original requester, or if that doesn't exist then of the current client. | ||
```js | ||
const byuJwt = require('byu-jwt'); | ||
byuJwt.cacheWellknowns = true; | ||
``` | ||
- *claims* - A [decoded JWT's](#decode-jwt) primary claim, prioritied in this order: | ||
### AuthenticationError | ||
1. Original resource owner | ||
2. Current resource owner | ||
3. Original client | ||
4. Current client | ||
An error type that inherits from standard Error. Used in **authenticate** function. | ||
### Authenticate University API Middleware | ||
**Example** | ||
A middleware that will check if the request has authentication and will either add the property `verifiedJWTs` to the request or will respond to the request with a `401` or `500` response code. | ||
The example will throw an AuthenticationError and then immediately catch it: | ||
`ByuJWT.prototype.authenticateUAPIMiddleware` | ||
```js | ||
const byuJwt = require('byu-jwt'); | ||
const AuthenticationError= byuJwt.AuthenticationError; | ||
**Parameters** | ||
try { | ||
throw new AuthenticationError('No expected JWTs found')); | ||
} catch (e) { | ||
if (e instanceof AuthenticationError) { | ||
// Do something (send 401 status?) | ||
} else { | ||
// Do something else | ||
} | ||
} | ||
``` | ||
- *req* - The request object. | ||
### JsonWebTokenError, NotBeforeError, and TokenExpiredError | ||
- *res* - The response object. | ||
Exposed error types from [the jsonwebtoken npm package](https://www.npmjs.com/package/jsonwebtoken#errors--codes) that also inherit from standard Error. | ||
- *next* - The next function. | ||
**Example** | ||
**Returns** `undefined` | ||
The example will throw an JsonWebTokenError and then immediately catch it: | ||
```js | ||
const byuJwt = require('byu-jwt'); | ||
const JsonWebTokenError= byuJwt.JsonWebTokenError; | ||
const express = require('express') | ||
const byuJwt = require('byu-jwt')() | ||
try { | ||
throw new JsonWebTokenError('expired jwt')); | ||
} catch (e) { | ||
if (e instanceof JsonWebTokenError) { | ||
// Do something | ||
const app = express() | ||
app.use(byuJwt.authenticateUAPIMiddleware) | ||
const listener = app.listen(3000, err => { | ||
if (err) { | ||
console.error(err.stack) | ||
} else { | ||
// Do something else | ||
console.log('Server listening on port ' + listener.address().port) | ||
} | ||
} | ||
}) | ||
``` | ||
### getWellKnown ( wellKnownURL : string ) : Promise\<object\> | ||
### Decode JWT | ||
Get the response of the specified *.well-known* URL. If *cacheWellKnowns* is set to `true` then it returns the previously retrieved response. | ||
Verify and decode a JWT. | ||
`ByuJWT.prototype.decodeJWT ( jwt )` | ||
**Parameters** | ||
- **wellKnownUrl** - The URL to use to get the well known information. | ||
- *jwt* - A JWT `string` to validate and decode. | ||
**Returns** a promise that resolves to an object. The object is the parsed JSON response from the well known URL. | ||
**Returns** a promise that, if valid, resolves to an object with these properties: | ||
**Example** | ||
- *client* - An object that contains the client claims. It has the following properties: `byuId`, `claimSource`, `netId`, `personId`, `preferredFirstName`, `prefix`, `restofName`, `sortName`, `subscriberNetId`, `suffix`, `surname`, `surnamePosition` | ||
```js | ||
const byuJwt = require('byu-jwt'); | ||
byuJwt.getWellKnown('http://the-wellknown-url.com') | ||
.then(function(wellKnownObject) { | ||
console.log('Response:', wellKnownObject); | ||
}); | ||
``` | ||
- *claims* - The primary claims object, prefering resource owner first and client second. | ||
### getPublicKey ( wellKnownURL : string ) : Promise\<string\> | ||
- *raw* - The raw claims aquired by validating the JWT. | ||
Get the PEM formatted X509 certificate. | ||
- *resourceOwner* - The resource owner claims (if a resource owner is defined). It has the following properties: `byuId`, `netId`, `personId`, `preferredFirstName`, `prefix`, `restofName`, `sortName`, `suffix`, `surname`, `surnamePosition` | ||
**Parameters** | ||
- *wso2*- Claims specific to WSO2.It has the following properties: `apiContext`, `application.id`, `application.name`, `application.tier`, `clientId`, `endUser`, `endUserTenantId`, `keyType`, `subscriber`, `tier`, `userType`, `version` | ||
- **wellKnownUrl** - The URL to use to get the well known information. | ||
### Get OpenId Configuration | ||
**Returns** a promise that resolves a string. | ||
Get the OpenID configuration from the well known url. | ||
**Example** | ||
`ByuJWT.prototype.getOpenIdConfiguration ()` | ||
```js | ||
const byuJwt = require('byu-jwt'); | ||
byuJwt.getPublicKey('http://the-wellknown-url.com') | ||
.then(function(publicKey) { | ||
console.log('Response:', publicKey); | ||
}); | ||
``` | ||
**Parameters** None | ||
### verifyJWT ( jwt : string, wellKnownURL : string ) : Promise\<object\> | ||
**Returns** a promise that resolves to the OpenID configuration. | ||
Verify and decode the signed JWT. | ||
### Get Public Key | ||
**Parameters** | ||
Get the public key for the OpenID configuration. | ||
- **jwt** - The signed JWT. | ||
- **wellKnownUrl** - The URL to use to get the well known information. | ||
`ByuJWT.prototype.getPublicKey ()` | ||
**Returns** a promise that resolves an object. | ||
**Parameters** None | ||
### jwtDecoded( jwt : string, wellKnownURL : string ) : Promise\<object\> | ||
**Returns** a promise that resolves to the public key `string`. | ||
Verifies and decodes the signed JWT and then formats it to provide easier access to important properties within the JWT. | ||
### Verify JWT | ||
Check to see if a JWT is valid. | ||
`ByuJWT.prototype.verifyJWT ( jwt )` | ||
**Parameters** | ||
- **jwt** - The signed JWT. | ||
- **wellKnownUrl** - The URL to use to get the well known information. | ||
- *jwt* - A JWT `string` to verify. | ||
**Returns** a promise that resolves to an object. The object will have many properties, but the most relevant will have the following structure: | ||
**Returns** a promise that resolves to a `boolean`. | ||
### Cache Time to Live | ||
Get or set the cache time to live. The cache only affects how often the OpenID configuration is redownloaded. | ||
```js | ||
{ | ||
byu: { | ||
client: { | ||
byuId: string, | ||
claimSource: string, | ||
netId: string, | ||
personId: string, | ||
preferredFirstName: string, | ||
prefix: string, | ||
restOfName: string, | ||
sortName: string, | ||
subscriberNetId: string, | ||
suffix: string, | ||
surname: string, | ||
surnamePosition: string | ||
}, | ||
resourceOwner: { // only set if resource owner exists | ||
byuId: string, | ||
netId: string, | ||
personId: string, | ||
preferredFirstName: string, | ||
prefix: string, | ||
restOfName: string, | ||
sortName: string, | ||
suffix: string, | ||
surname: string, | ||
surnamePosition: string | ||
}, | ||
webresCheck: { | ||
byuId: string, | ||
netId: string, | ||
personId: string, | ||
} | ||
}, | ||
wso2: { | ||
apiContext: string, | ||
application: { | ||
id: string, | ||
name: string, | ||
tier: string | ||
}, | ||
clientId: string, | ||
endUser: string, | ||
endUserTenantId: string, | ||
keyType: string, | ||
subscriber: string, | ||
tier: string, | ||
userType: string, | ||
version: string | ||
} | ||
} | ||
const byuJwt = require('byu-jwt')() | ||
byuJWT.cacheTTL = 15 // set cache to 15 minutes | ||
``` | ||
**Example** | ||
### Static Constants | ||
```js | ||
const byuJwt = require('byu-jwt'); | ||
The following properties are accessible on the ByuJWT object without needing an instantiated object. | ||
byuJwt.jwtDecoded('ey...gQ', 'http://the-wellknown-url.com') | ||
.then(function(decoded) { | ||
console.log(decoded.byu.client_byu_id); // example output: '123456789' | ||
}); | ||
``` | ||
- *BYU_JWT_HEADER_CURRENT* - The header name for the current JWT. | ||
### authenticate( headers : object, wellKnownURL : string, [optional] basePath : string ) : Promise\<object\> | ||
- *BYU_JWT_HEADER_ORIGINAL* - The header name for the original JWT. | ||
Verifies and decodes the signed JWT and then formats it to provide easier access to important properties within the JWT. | ||
- *AuthenticationError* - A reference to the AuthenticationError constructor. | ||
**Parameters** | ||
- *JsonWebTokenError* - A reference to the JsonWebTokenError constructor. | ||
- **headers** - The headers. An object that looks like: | ||
```js | ||
{ | ||
'x-jwt-assertion': 'ey...gQ' | ||
} | ||
``` | ||
- **wellKnownUrl** - The URL to use to get the well known information. | ||
- **basePath** - (Optional) The base path to compare with API context found in JWT sent from BYU's API manager. | ||
- *NotBeforeError* - A reference to the NotBeforeError constructor. | ||
**Returns** a promise that resolves to an object or rejects with an **AuthenticationError**. The object will have the following structure: | ||
- *TokenExpiredError* - A reference to the TokenExpiredError constructor. | ||
```js | ||
{ | ||
current: { | ||
/* The object returned by running jwtDecoded on current JWT */ | ||
}, | ||
// Only set if we have an original in addition to a current JWT | ||
original: { | ||
/* The object returned by running jwtDecoded on original JWT */ | ||
}, | ||
originalJwt: 'ey...gQ', // Here for convenience in passing it along | ||
prioritizedClaims: { | ||
byuId: string, | ||
netId: string, | ||
personId: string, | ||
preferredFirstName: string, | ||
prefix: string, | ||
restOfName: string, | ||
sortName: string, | ||
suffix: string, | ||
surname: string, | ||
surnamePosition: string | ||
} | ||
} | ||
const ByuJWT = require('byu-jwt') | ||
console.log(ByuJWT.BYU_JWT_HEADER_CURRENT) // "x-jwt-assertion" | ||
``` | ||
**Example** | ||
## Testing | ||
```js | ||
const byuJwt = require('byu-jwt'); | ||
const AuthenticationError = byuJwt.AuthenticationError; | ||
To test this library: | ||
const headers = { | ||
'x-jwt-assertion': 'ey...gQ', | ||
'x-jwt-assertion-original': 'ey...gQ' | ||
} | ||
1. Run `npm install` | ||
byuJwt.authenticate(headers, 'http://the-wellknown-url.com') | ||
.then(function(verifiedJwts) { | ||
console.log(verifiedJwts.originalJwt); // example output: 'ey...gQ' | ||
console.log(verifiedJwts.prioritizedClaims); | ||
/** | ||
* example output: | ||
* { | ||
* byuId: string, | ||
* netId: string, | ||
* personId: string, | ||
* preferredFirstName: string, | ||
* prefix: string, | ||
* restOfName: string, | ||
* sortName: string, | ||
* suffix: string, | ||
* surname: string, | ||
* surnamePosition: string | ||
* } | ||
**/ | ||
}) | ||
.catch(err => { | ||
if (err instanceof AuthenticationError) { | ||
// This error came from authenticate function - Respond with 401 | ||
} else { | ||
// Handle other errors | ||
} | ||
}) | ||
``` | ||
2. Run `awslogin` (https://github.com/byu-oit/awslogin) | ||
###Use in tests | ||
For use in tests (like mocha tests), you can set the environment variable __NODE_ENV__ to `mock`. This will bypass the verifying of the JWT string parameter and simply decode it in **jwtDecoded**. Similarly, this will bypass the verifying of JWTs and basePath checking in **authenticate**. | ||
**Example (snippet)** | ||
```js | ||
it('decode JWT without verifying', function (done) { | ||
process.env.NODE_ENV = 'mock'; | ||
//to run test case capture a jwt and copy in the function invocation below. | ||
byuJwt.jwtDecoded('ey...gQ', 'http://the-wellknown-url.com') | ||
.then(function (jwtDecoded) { | ||
try { | ||
assert.equal(jwtDecoded.byu.client.netId, ''); | ||
done() | ||
} | ||
catch (e) { | ||
console.log(e); | ||
done(e); | ||
} | ||
}) | ||
.catch(function (e) { | ||
console.log(e); | ||
done(e); | ||
}); | ||
}); | ||
``` | ||
Note: Be sure to unset the environment variable for tests run after this test. | ||
3. Run `npm test` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
40871
2
10
593
0
1
4
191
3
- Removedbluebird@^3.5.1
- Removedrequest@^2.87.0
- Removedajv@6.12.6(transitive)
- Removedasn1@0.2.6(transitive)
- Removedassert-plus@1.0.0(transitive)
- Removedasynckit@0.4.0(transitive)
- Removedaws-sign2@0.7.0(transitive)
- Removedaws4@1.13.2(transitive)
- Removedbcrypt-pbkdf@1.0.2(transitive)
- Removedbluebird@3.7.2(transitive)
- Removedcaseless@0.12.0(transitive)
- Removedcombined-stream@1.0.8(transitive)
- Removedcore-util-is@1.0.2(transitive)
- Removeddashdash@1.14.1(transitive)
- Removeddelayed-stream@1.0.0(transitive)
- Removedecc-jsbn@0.1.2(transitive)
- Removedextend@3.0.2(transitive)
- Removedextsprintf@1.3.0(transitive)
- Removedfast-deep-equal@3.1.3(transitive)
- Removedfast-json-stable-stringify@2.1.0(transitive)
- Removedforever-agent@0.6.1(transitive)
- Removedform-data@2.3.3(transitive)
- Removedgetpass@0.1.7(transitive)
- Removedhar-schema@2.0.0(transitive)
- Removedhar-validator@5.1.5(transitive)
- Removedhttp-signature@1.2.0(transitive)
- Removedis-typedarray@1.0.0(transitive)
- Removedisstream@0.1.2(transitive)
- Removedjsbn@0.1.1(transitive)
- Removedjson-schema@0.4.0(transitive)
- Removedjson-schema-traverse@0.4.1(transitive)
- Removedjson-stringify-safe@5.0.1(transitive)
- Removedjsprim@1.4.2(transitive)
- Removedmime-db@1.52.0(transitive)
- Removedmime-types@2.1.35(transitive)
- Removedoauth-sign@0.9.0(transitive)
- Removedperformance-now@2.1.0(transitive)
- Removedpsl@1.15.0(transitive)
- Removedpunycode@2.3.1(transitive)
- Removedqs@6.5.3(transitive)
- Removedrequest@2.88.2(transitive)
- Removedsafer-buffer@2.1.2(transitive)
- Removedsshpk@1.18.0(transitive)
- Removedtough-cookie@2.5.0(transitive)
- Removedtunnel-agent@0.6.0(transitive)
- Removedtweetnacl@0.14.5(transitive)
- Removeduri-js@4.4.1(transitive)
- Removeduuid@3.4.0(transitive)
- Removedverror@1.10.0(transitive)