project files added
This commit is contained in:
+76
@@ -0,0 +1,76 @@
|
||||
'use strict';
|
||||
|
||||
const isAfter = require('date-fns/isAfter');
|
||||
const parseToken = require('./parse-token');
|
||||
const coreModule = require('./../core');
|
||||
|
||||
/**
|
||||
* Wrapper for the Access Token Object
|
||||
*/
|
||||
module.exports = (config) => {
|
||||
const core = coreModule(config);
|
||||
|
||||
class AccessToken {
|
||||
constructor(token) {
|
||||
this.token = parseToken(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the access token is expired or not
|
||||
*/
|
||||
expired() {
|
||||
return isAfter(new Date(), this.token.expires_at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the access token
|
||||
* @param {Object} params An optional argument for additional API request params.
|
||||
*/
|
||||
async refresh(params) {
|
||||
const options = Object.assign({}, params, {
|
||||
grant_type: 'refresh_token',
|
||||
refresh_token: this.token.refresh_token,
|
||||
});
|
||||
|
||||
const response = await core.request(config.auth.tokenPath, options);
|
||||
|
||||
return new AccessToken(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke access or refresh token
|
||||
* @param {String} tokenType A string containing the type of token to revoke.
|
||||
* Should be either "access_token" or "refresh_token"
|
||||
*/
|
||||
async revoke(tokenType) {
|
||||
const token = tokenType === 'access_token' ? this.token.access_token : this.token.refresh_token;
|
||||
const options = {
|
||||
token,
|
||||
token_type_hint: tokenType,
|
||||
};
|
||||
|
||||
return core.request(config.auth.revokePath, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke both the existing access and refresh tokens
|
||||
*/
|
||||
async revokeAll() {
|
||||
await this.revoke('access_token');
|
||||
await this.revoke('refresh_token');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an OAuth2.AccessToken instance
|
||||
* @param {Object} token An object containing the token object returned from the OAuth2 server.
|
||||
* @returns {AccessToken}
|
||||
*/
|
||||
function createAccessToken(token) {
|
||||
return new AccessToken(token);
|
||||
}
|
||||
|
||||
return {
|
||||
create: createAccessToken,
|
||||
};
|
||||
};
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
const debug = require('debug')('access-token');
|
||||
const isDate = require('date-fns/isDate');
|
||||
const parseISO = require('date-fns/parseISO');
|
||||
const addSeconds = require('date-fns/addSeconds');
|
||||
|
||||
const parseTokenDateProperties = (token) => {
|
||||
const parsedTokenProps = {};
|
||||
|
||||
if ('expires_at' in token) {
|
||||
if (!isDate(token.expires_at)) {
|
||||
parsedTokenProps.expires_at = parseISO(token.expires_at);
|
||||
}
|
||||
} else if ('expires_in' in token) {
|
||||
parsedTokenProps.expires_at = addSeconds(
|
||||
new Date(),
|
||||
Number.parseInt(token.expires_in, 10)
|
||||
);
|
||||
} else {
|
||||
debug('No token expiration property was found. Ignoring date parsing');
|
||||
}
|
||||
|
||||
return Object.assign({}, token, parsedTokenProps);
|
||||
};
|
||||
|
||||
module.exports = parseTokenDateProperties;
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
'use strict';
|
||||
|
||||
const url = require('url');
|
||||
const qs = require('querystring');
|
||||
const coreModule = require('./../core');
|
||||
|
||||
/**
|
||||
* Authorization Code flow implementation
|
||||
*/
|
||||
module.exports = (config) => {
|
||||
const core = coreModule(config);
|
||||
const authorizeUrl = url.resolve(config.auth.authorizeHost, config.auth.authorizePath);
|
||||
|
||||
/**
|
||||
* Redirect the user to the autorization page
|
||||
* @param {String} params.redirectURI A string that represents the registered application URI
|
||||
* where the user is redirected after authentication
|
||||
* @param {String|Array<String>} params.scope A String or array of strings
|
||||
* that represents the application privileges
|
||||
* @param {String} params.state A String that represents an option opaque value used by the client
|
||||
* to main the state between the request and the callback
|
||||
* @return {String} the absolute authorization url
|
||||
*/
|
||||
function authorizeURL(params = {}) {
|
||||
const baseParams = {
|
||||
response_type: 'code',
|
||||
[config.client.idParamName]: config.client.id,
|
||||
};
|
||||
|
||||
if (Array.isArray(params.scope)) {
|
||||
const scope = params.scope.join(',');
|
||||
|
||||
Object.assign(params, { scope });
|
||||
}
|
||||
|
||||
const options = Object.assign({}, baseParams, params);
|
||||
|
||||
return `${authorizeUrl}?${qs.stringify(options)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Access Token Object
|
||||
* @param {String} params.code Authorization code (from previous step)
|
||||
* @param {String} params.redirecURI A string that represents the callback uri
|
||||
* @return {Promise}
|
||||
*/
|
||||
async function getToken(params) {
|
||||
const options = Object.assign({}, params, {
|
||||
grant_type: 'authorization_code',
|
||||
});
|
||||
|
||||
return core.request(config.auth.tokenPath, options);
|
||||
}
|
||||
|
||||
return {
|
||||
authorizeURL,
|
||||
getToken,
|
||||
};
|
||||
};
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
const coreModule = require('./../core');
|
||||
|
||||
/**
|
||||
* Clients credentials flow implementation
|
||||
*/
|
||||
module.exports = (config) => {
|
||||
const core = coreModule(config);
|
||||
|
||||
/**
|
||||
* Returns the Access Token Object
|
||||
* @param {Object} params
|
||||
* @param {String} params.scope A string that represents the application privileges
|
||||
* @return {Promise}
|
||||
*/
|
||||
async function getToken(params) {
|
||||
const options = Object.assign({}, params, {
|
||||
grant_type: 'client_credentials',
|
||||
});
|
||||
|
||||
return core.request(config.auth.tokenPath, options);
|
||||
}
|
||||
|
||||
return {
|
||||
getToken,
|
||||
};
|
||||
};
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
'use strict';
|
||||
|
||||
const coreModule = require('./../core');
|
||||
|
||||
/**
|
||||
* User Password flow implementation
|
||||
*/
|
||||
module.exports = (config) => {
|
||||
const core = coreModule(config);
|
||||
|
||||
/**
|
||||
* Returns the Access Token Object
|
||||
* @param {Object} params
|
||||
* @param {String} params.username A string that represents the registered username
|
||||
* @param {String} params.password A string that represents the registered password
|
||||
* @param {String} params.scope A string that represents the application privileges
|
||||
* @return {Promise}
|
||||
*/
|
||||
async function getToken(params) {
|
||||
const options = Object.assign({}, params, {
|
||||
grant_type: 'password',
|
||||
});
|
||||
|
||||
return core.request(config.auth.tokenPath, options);
|
||||
}
|
||||
|
||||
return {
|
||||
getToken,
|
||||
};
|
||||
};
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
'use strict';
|
||||
|
||||
const Wreck = require('wreck');
|
||||
const querystring = require('querystring');
|
||||
const debug = require('debug')('simple-oauth2:index');
|
||||
const encoding = require('./encoding');
|
||||
|
||||
const defaultHeaders = {
|
||||
Accept: 'application/json',
|
||||
};
|
||||
|
||||
module.exports = (config) => {
|
||||
const httpOptions = Object.assign({}, config.http, {
|
||||
baseUrl: config.auth.tokenHost,
|
||||
headers: Object.assign({}, defaultHeaders, (config.http && config.http.headers)),
|
||||
});
|
||||
|
||||
const wreck = Wreck.defaults(httpOptions);
|
||||
|
||||
async function request(url, params) {
|
||||
let payload = params;
|
||||
const options = {
|
||||
json: true,
|
||||
headers: {},
|
||||
};
|
||||
|
||||
if (config.options.authorizationMethod === 'header') {
|
||||
const basicHeader = encoding.getAuthorizationHeaderToken(
|
||||
config.client.id,
|
||||
config.client.secret
|
||||
);
|
||||
|
||||
debug('Using header authentication. Authorization header set to %s', basicHeader);
|
||||
|
||||
options.headers.Authorization = `Basic ${basicHeader}`;
|
||||
} else {
|
||||
debug('Using body authentication');
|
||||
|
||||
payload = Object.assign({}, payload, {
|
||||
[config.client.idParamName]: config.client.id,
|
||||
[config.client.secretParamName]: config.client.secret,
|
||||
});
|
||||
}
|
||||
|
||||
if (config.options.bodyFormat === 'form') {
|
||||
debug('Using form request format');
|
||||
|
||||
// An example using `form` authorization params in the body is the
|
||||
// GitHub API.
|
||||
options.payload = querystring.stringify(payload);
|
||||
options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
} else {
|
||||
debug('Using json request format');
|
||||
|
||||
// An example using `json` authorization params in the body is the
|
||||
// Amazon Developer Publishing API.
|
||||
options.payload = payload;
|
||||
options.headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
debug('Creating request to: (POST) %s', url);
|
||||
debug('Using options: %j', options);
|
||||
|
||||
const result = await wreck.post(url, options);
|
||||
|
||||
return result.payload;
|
||||
}
|
||||
|
||||
return {
|
||||
request,
|
||||
};
|
||||
};
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
const HEADER_ENCODING_FORMAT = 'base64';
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Encode a single {value} using the application/x-www-form-urlencoded media type
|
||||
* while also applying some additional rules specified by the spec
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc6749#appendix-B
|
||||
*
|
||||
* @param {String} value
|
||||
*/
|
||||
useFormURLEncode(value) {
|
||||
return encodeURIComponent(value).replace(/%20/g, '+');
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the authorization header used to request a valid token
|
||||
* @param {String} clientID
|
||||
* @param {String} clientSecret
|
||||
* @return {String} Authorization header string token
|
||||
*/
|
||||
getAuthorizationHeaderToken(clientID, clientSecret) {
|
||||
const encodedCredentials = `${this.useFormURLEncode(clientID)}:${this.useFormURLEncode(clientSecret)}`;
|
||||
|
||||
return Buffer.from(encodedCredentials).toString(HEADER_ENCODING_FORMAT);
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user