New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@bity/oauth2-auth-code-pkce

Package Overview
Dependencies
Maintainers
2
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@bity/oauth2-auth-code-pkce - npm Package Compare versions

Comparing version 2.1.1 to 2.2.0

239

index.js

@@ -64,2 +64,9 @@ /**

};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
;

@@ -129,2 +136,10 @@ ;

export { ErrorInvalidRequest };
var ErrorInvalidToken = /** @class */ (function (_super) {
__extends(ErrorInvalidToken, _super);
function ErrorInvalidToken() {
return _super !== null && _super.apply(this, arguments) || this;
}
return ErrorInvalidToken;
}(ErrorOAuth2));
export { ErrorInvalidToken };
/**

@@ -217,2 +232,11 @@ * Possible authorization grant errors given by the redirection from the

export { ErrorUnsupportedGrantType };
/**
* WWW-Authenticate error object structure for less error prone handling.
*/
var ErrorWWWAuthenticate = /** @class */ (function () {
function ErrorWWWAuthenticate() {
}
return ErrorWWWAuthenticate;
}());
export { ErrorWWWAuthenticate };
export var RawErrorToErrorClassMap = {

@@ -230,3 +254,7 @@ invalid_request: ErrorInvalidRequest,

invalid_json: ErrorInvalidJson,
invalid_token: ErrorInvalidToken,
};
/**
* Translate the raw error strings returned from the server into error classes.
*/
export function toErrorClass(rawError) {

@@ -236,2 +264,25 @@ return new (RawErrorToErrorClassMap[rawError] || ErrorUnknown)();

/**
* A convience function to turn, for example, `Bearer realm="bity.com",
* error="invalid_client"` into `{ realm: "bity.com", error: "invalid_client"
* }`.
*/
export function fromWWWAuthenticateHeaderStringToObject(a) {
var obj = a
.slice("Bearer ".length)
.replace(/"/g, '')
.split(', ')
.map(function (tokens) {
var _a;
var _b = tokens.split('='), k = _b[0], v = _b[1];
return _a = {}, _a[k] = v, _a;
})
.reduce(function (a, c) { return (__assign(__assign({}, a), c)); });
return { realm: obj.realm, error: obj.error };
}
/**
* HTTP headers that we need to access.
*/
var HEADER_AUTHORIZATION = "Authorization";
var HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
/**
* To store the OAuth client's data between websites due to redirection.

@@ -272,10 +323,34 @@ */

/**
* If the state or config are missing, it means the client is in a bad state.
* This should never happen, but the check is there just in case.
* Attach the OAuth logic to all fetch requests and translate errors (either
* returned as json or through the WWW-Authenticate header) into nice error
* classes.
*/
OAuth2AuthCodePKCE.prototype.assertStateAndConfigArePresent = function () {
if (!this.state || !this.config) {
console.error('state:', this.state, 'config:', this.config);
throw new Error('state or config is not set.');
}
OAuth2AuthCodePKCE.prototype.decorateFetchHTTPClient = function (fetch) {
var _this = this;
return function (url, config) {
var rest = [];
for (var _i = 2; _i < arguments.length; _i++) {
rest[_i - 2] = arguments[_i];
}
return _this
.getAccessToken()
.then(function (_a) {
var token = _a.token;
var configNew = Object.assign({}, config);
if (!configNew.headers) {
configNew.headers = {};
}
configNew.headers[HEADER_AUTHORIZATION] = "Bearer " + token.value;
return fetch.apply(void 0, __spreadArrays([url, configNew], rest));
})
.then(function (res) {
if (res.ok) {
return res;
}
if (!res.headers.has(HEADER_WWW_AUTHENTICATE.toLowerCase())) {
return res;
}
return Promise.reject(toErrorClass(fromWWWAuthenticateHeaderStringToObject(res.headers.get(HEADER_WWW_AUTHENTICATE.toLowerCase())).error));
});
};
};

@@ -309,72 +384,2 @@ /**

/**
* Fetch an access token from the remote service. You may pass a custom
* authorization grant code for any reason, but this is non-standard usage.
*/
OAuth2AuthCodePKCE.prototype.exchangeAuthCodeForAccessToken = function (codeOverride) {
var _this = this;
this.assertStateAndConfigArePresent();
var _a = this.state, _b = _a.authorizationCode, authorizationCode = _b === void 0 ? codeOverride : _b, _c = _a.codeVerifier, codeVerifier = _c === void 0 ? '' : _c;
var _d = this.config, clientId = _d.clientId, onInvalidGrant = _d.onInvalidGrant, redirectUrl = _d.redirectUrl;
if (!codeVerifier) {
console.warn('No code verifier is being sent.');
}
else if (!authorizationCode) {
console.warn('No authorization grant code is being passed.');
}
var url = this.config.tokenUrl;
var body = "grant_type=authorization_code&"
+ ("code=" + encodeURIComponent(authorizationCode || '') + "&")
+ ("redirect_uri=" + encodeURIComponent(redirectUrl) + "&")
+ ("client_id=" + encodeURIComponent(clientId) + "&")
+ ("code_verifier=" + codeVerifier);
return fetch(url, {
method: 'POST',
body: body,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function (res) {
var jsonPromise = res.json()
.catch(function (_) { return ({ error: 'invalid_json' }); });
if (!res.ok) {
return jsonPromise.then(function (_a) {
var error = _a.error;
switch (error) {
case 'invalid_grant':
onInvalidGrant(function () { return _this.fetchAuthorizationCode(); });
break;
default:
break;
}
return Promise.reject(toErrorClass(error));
});
}
return jsonPromise.then(function (_a) {
var access_token = _a.access_token, expires_in = _a.expires_in, refresh_token = _a.refresh_token, scope = _a.scope;
var scopes = [];
_this.state.hasAuthCodeBeenExchangedForAccessToken = true;
var accessToken = {
value: access_token,
expiry: (new Date(Date.now() + (parseInt(expires_in) * 1000))).toString()
};
_this.state.accessToken = accessToken;
if (refresh_token) {
var refreshToken = {
value: refresh_token
};
_this.state.refreshToken = refreshToken;
}
if (scope) {
// Multiple scopes are passed and delimited by spaces,
// despite using the singular name "scope".
scopes = scope.split(' ');
_this.state.scopes = scopes;
}
localStorage.setItem(LOCALSTORAGE_STATE, JSON.stringify(_this.state));
return { token: accessToken, scopes: scopes };
});
});
};
/**
* Fetch an authorization grant via redirection. In a sense this function

@@ -503,2 +508,82 @@ * doesn't return because of the redirect behavior (uses `location.replace`).

};
/**
* If the state or config are missing, it means the client is in a bad state.
* This should never happen, but the check is there just in case.
*/
OAuth2AuthCodePKCE.prototype.assertStateAndConfigArePresent = function () {
if (!this.state || !this.config) {
console.error('state:', this.state, 'config:', this.config);
throw new Error('state or config is not set.');
}
};
/**
* Fetch an access token from the remote service. You may pass a custom
* authorization grant code for any reason, but this is non-standard usage.
*/
OAuth2AuthCodePKCE.prototype.exchangeAuthCodeForAccessToken = function (codeOverride) {
var _this = this;
this.assertStateAndConfigArePresent();
var _a = this.state, _b = _a.authorizationCode, authorizationCode = _b === void 0 ? codeOverride : _b, _c = _a.codeVerifier, codeVerifier = _c === void 0 ? '' : _c;
var _d = this.config, clientId = _d.clientId, onInvalidGrant = _d.onInvalidGrant, redirectUrl = _d.redirectUrl;
if (!codeVerifier) {
console.warn('No code verifier is being sent.');
}
else if (!authorizationCode) {
console.warn('No authorization grant code is being passed.');
}
var url = this.config.tokenUrl;
var body = "grant_type=authorization_code&"
+ ("code=" + encodeURIComponent(authorizationCode || '') + "&")
+ ("redirect_uri=" + encodeURIComponent(redirectUrl) + "&")
+ ("client_id=" + encodeURIComponent(clientId) + "&")
+ ("code_verifier=" + codeVerifier);
return fetch(url, {
method: 'POST',
body: body,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function (res) {
var jsonPromise = res.json()
.catch(function (_) { return ({ error: 'invalid_json' }); });
if (!res.ok) {
return jsonPromise.then(function (_a) {
var error = _a.error;
switch (error) {
case 'invalid_grant':
onInvalidGrant(function () { return _this.fetchAuthorizationCode(); });
break;
default:
break;
}
return Promise.reject(toErrorClass(error));
});
}
return jsonPromise.then(function (_a) {
var access_token = _a.access_token, expires_in = _a.expires_in, refresh_token = _a.refresh_token, scope = _a.scope;
var scopes = [];
_this.state.hasAuthCodeBeenExchangedForAccessToken = true;
var accessToken = {
value: access_token,
expiry: (new Date(Date.now() + (parseInt(expires_in) * 1000))).toString()
};
_this.state.accessToken = accessToken;
if (refresh_token) {
var refreshToken = {
value: refresh_token
};
_this.state.refreshToken = refreshToken;
}
if (scope) {
// Multiple scopes are passed and delimited by spaces,
// despite using the singular name "scope".
scopes = scope.split(' ');
_this.state.scopes = scopes;
}
localStorage.setItem(LOCALSTORAGE_STATE, JSON.stringify(_this.state));
return { token: accessToken, scopes: scopes };
});
});
};
OAuth2AuthCodePKCE.prototype.recoverState = function () {

@@ -505,0 +590,0 @@ this.state = JSON.parse(localStorage.getItem(LOCALSTORAGE_STATE) || '{}');

@@ -47,2 +47,3 @@ /**

export type HttpClient = ((...args: any[]) => Promise<any>);
export type URL = string;

@@ -67,2 +68,3 @@

export class ErrorInvalidRequest extends ErrorOAuth2 { }
export class ErrorInvalidToken extends ErrorOAuth2 { }

@@ -88,2 +90,10 @@ /**

/**
* WWW-Authenticate error object structure for less error prone handling.
*/
export class ErrorWWWAuthenticate {
public realm: string;
public error: string;
}
export const RawErrorToErrorClassMap: { [_: string]: any } = {

@@ -101,4 +111,8 @@ invalid_request: ErrorInvalidRequest,

invalid_json: ErrorInvalidJson,
invalid_token: ErrorInvalidToken,
};
/**
* Translate the raw error strings returned from the server into error classes.
*/
export function toErrorClass(rawError: string): ErrorOAuth2 {

@@ -109,2 +123,26 @@ return new (RawErrorToErrorClassMap[rawError] || ErrorUnknown)();

/**
* A convience function to turn, for example, `Bearer realm="bity.com",
* error="invalid_client"` into `{ realm: "bity.com", error: "invalid_client"
* }`.
*/
export function fromWWWAuthenticateHeaderStringToObject(
a: string
): ErrorWWWAuthenticate {
const obj = a
.slice("Bearer ".length)
.replace(/"/g, '')
.split(', ')
.map(tokens => { const [k,v] = tokens.split('='); return {[k]:v}; })
.reduce((a, c) => ({ ...a, ...c}));
return { realm: obj.realm, error: obj.error };
}
/**
* HTTP headers that we need to access.
*/
const HEADER_AUTHORIZATION = "Authorization";
const HEADER_WWW_AUTHENTICATE= "WWW-Authenticate";
/**
* To store the OAuth client's data between websites due to redirection.

@@ -152,10 +190,35 @@ */

/**
* If the state or config are missing, it means the client is in a bad state.
* This should never happen, but the check is there just in case.
* Attach the OAuth logic to all fetch requests and translate errors (either
* returned as json or through the WWW-Authenticate header) into nice error
* classes.
*/
private assertStateAndConfigArePresent() {
if (!this.state || !this.config) {
console.error('state:', this.state, 'config:', this.config);
throw new Error('state or config is not set.');
}
public decorateFetchHTTPClient(fetch: HttpClient): HttpClient {
return (url: string, config: any, ...rest) => {
return this
.getAccessToken()
.then(({ token }: AccessContext) => {
const configNew: any = Object.assign({}, config);
if (!configNew.headers) {
configNew.headers = {};
}
configNew.headers[HEADER_AUTHORIZATION] = `Bearer ${token.value}`;
return fetch(url, configNew, ...rest);
})
.then((res) => {
if (res.ok) {
return res;
}
if (!res.headers.has(HEADER_WWW_AUTHENTICATE.toLowerCase())) {
return res;
}
return Promise.reject(toErrorClass(
fromWWWAuthenticateHeaderStringToObject(
res.headers.get(HEADER_WWW_AUTHENTICATE.toLowerCase())
).error
));
});
};
}

@@ -196,84 +259,2 @@

/**
* Fetch an access token from the remote service. You may pass a custom
* authorization grant code for any reason, but this is non-standard usage.
*/
private exchangeAuthCodeForAccessToken(
codeOverride?: string
): Promise<AccessContext> {
this.assertStateAndConfigArePresent();
const {
authorizationCode = codeOverride,
codeVerifier = ''
} = this.state;
const { clientId, onInvalidGrant, redirectUrl } = this.config;
if (!codeVerifier) {
console.warn('No code verifier is being sent.');
} else if (!authorizationCode) {
console.warn('No authorization grant code is being passed.');
}
const url = this.config.tokenUrl;
const body = `grant_type=authorization_code&`
+ `code=${encodeURIComponent(authorizationCode || '')}&`
+ `redirect_uri=${encodeURIComponent(redirectUrl)}&`
+ `client_id=${encodeURIComponent(clientId)}&`
+ `code_verifier=${codeVerifier}`;
return fetch(url, {
method: 'POST',
body,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(res => {
const jsonPromise = res.json()
.catch(_ => ({ error: 'invalid_json' }));
if (!res.ok) {
return jsonPromise.then(({ error }: any) => {
switch (error) {
case 'invalid_grant':
onInvalidGrant(() => this.fetchAuthorizationCode());
break;
default:
break;
}
return Promise.reject(toErrorClass(error));
});
}
return jsonPromise.then(({ access_token, expires_in, refresh_token, scope }) => {
let scopes = [];
this.state.hasAuthCodeBeenExchangedForAccessToken = true;
const accessToken: AccessToken = {
value: access_token,
expiry: (new Date(Date.now() + (parseInt(expires_in) * 1000))).toString()
};
this.state.accessToken = accessToken;
if (refresh_token) {
const refreshToken: RefreshToken = {
value: refresh_token
};
this.state.refreshToken = refreshToken;
}
if (scope) {
// Multiple scopes are passed and delimited by spaces,
// despite using the singular name "scope".
scopes = scope.split(' ');
this.state.scopes = scopes;
}
localStorage.setItem(LOCALSTORAGE_STATE, JSON.stringify(this.state));
return { token: accessToken, scopes };
});
});
}
/**
* Fetch an authorization grant via redirection. In a sense this function

@@ -419,2 +400,96 @@ * doesn't return because of the redirect behavior (uses `location.replace`).

/**
* If the state or config are missing, it means the client is in a bad state.
* This should never happen, but the check is there just in case.
*/
private assertStateAndConfigArePresent() {
if (!this.state || !this.config) {
console.error('state:', this.state, 'config:', this.config);
throw new Error('state or config is not set.');
}
}
/**
* Fetch an access token from the remote service. You may pass a custom
* authorization grant code for any reason, but this is non-standard usage.
*/
private exchangeAuthCodeForAccessToken(
codeOverride?: string
): Promise<AccessContext> {
this.assertStateAndConfigArePresent();
const {
authorizationCode = codeOverride,
codeVerifier = ''
} = this.state;
const { clientId, onInvalidGrant, redirectUrl } = this.config;
if (!codeVerifier) {
console.warn('No code verifier is being sent.');
} else if (!authorizationCode) {
console.warn('No authorization grant code is being passed.');
}
const url = this.config.tokenUrl;
const body = `grant_type=authorization_code&`
+ `code=${encodeURIComponent(authorizationCode || '')}&`
+ `redirect_uri=${encodeURIComponent(redirectUrl)}&`
+ `client_id=${encodeURIComponent(clientId)}&`
+ `code_verifier=${codeVerifier}`;
return fetch(url, {
method: 'POST',
body,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(res => {
const jsonPromise = res.json()
.catch(_ => ({ error: 'invalid_json' }));
if (!res.ok) {
return jsonPromise.then(({ error }: any) => {
switch (error) {
case 'invalid_grant':
onInvalidGrant(() => this.fetchAuthorizationCode());
break;
default:
break;
}
return Promise.reject(toErrorClass(error));
});
}
return jsonPromise.then(({ access_token, expires_in, refresh_token, scope }) => {
let scopes = [];
this.state.hasAuthCodeBeenExchangedForAccessToken = true;
const accessToken: AccessToken = {
value: access_token,
expiry: (new Date(Date.now() + (parseInt(expires_in) * 1000))).toString()
};
this.state.accessToken = accessToken;
if (refresh_token) {
const refreshToken: RefreshToken = {
value: refresh_token
};
this.state.refreshToken = refreshToken;
}
if (scope) {
// Multiple scopes are passed and delimited by spaces,
// despite using the singular name "scope".
scopes = scope.split(' ');
this.state.scopes = scopes;
}
localStorage.setItem(LOCALSTORAGE_STATE, JSON.stringify(this.state));
return { token: accessToken, scopes };
});
});
}
private recoverState(): this {

@@ -421,0 +496,0 @@ this.state = JSON.parse(localStorage.getItem(LOCALSTORAGE_STATE) || '{}');

@@ -157,2 +157,9 @@ module.exports =

};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -223,2 +230,10 @@ ;

exports.ErrorInvalidRequest = ErrorInvalidRequest;
var ErrorInvalidToken = /** @class */ (function (_super) {
__extends(ErrorInvalidToken, _super);
function ErrorInvalidToken() {
return _super !== null && _super.apply(this, arguments) || this;
}
return ErrorInvalidToken;
}(ErrorOAuth2));
exports.ErrorInvalidToken = ErrorInvalidToken;
/**

@@ -311,2 +326,11 @@ * Possible authorization grant errors given by the redirection from the

exports.ErrorUnsupportedGrantType = ErrorUnsupportedGrantType;
/**
* WWW-Authenticate error object structure for less error prone handling.
*/
var ErrorWWWAuthenticate = /** @class */ (function () {
function ErrorWWWAuthenticate() {
}
return ErrorWWWAuthenticate;
}());
exports.ErrorWWWAuthenticate = ErrorWWWAuthenticate;
exports.RawErrorToErrorClassMap = {

@@ -324,3 +348,7 @@ invalid_request: ErrorInvalidRequest,

invalid_json: ErrorInvalidJson,
invalid_token: ErrorInvalidToken,
};
/**
* Translate the raw error strings returned from the server into error classes.
*/
function toErrorClass(rawError) {

@@ -331,2 +359,26 @@ return new (exports.RawErrorToErrorClassMap[rawError] || ErrorUnknown)();

/**
* A convience function to turn, for example, `Bearer realm="bity.com",
* error="invalid_client"` into `{ realm: "bity.com", error: "invalid_client"
* }`.
*/
function fromWWWAuthenticateHeaderStringToObject(a) {
var obj = a
.slice("Bearer ".length)
.replace(/"/g, '')
.split(', ')
.map(function (tokens) {
var _a;
var _b = tokens.split('='), k = _b[0], v = _b[1];
return _a = {}, _a[k] = v, _a;
})
.reduce(function (a, c) { return (__assign(__assign({}, a), c)); });
return { realm: obj.realm, error: obj.error };
}
exports.fromWWWAuthenticateHeaderStringToObject = fromWWWAuthenticateHeaderStringToObject;
/**
* HTTP headers that we need to access.
*/
var HEADER_AUTHORIZATION = "Authorization";
var HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
/**
* To store the OAuth client's data between websites due to redirection.

@@ -367,10 +419,34 @@ */

/**
* If the state or config are missing, it means the client is in a bad state.
* This should never happen, but the check is there just in case.
* Attach the OAuth logic to all fetch requests and translate errors (either
* returned as json or through the WWW-Authenticate header) into nice error
* classes.
*/
OAuth2AuthCodePKCE.prototype.assertStateAndConfigArePresent = function () {
if (!this.state || !this.config) {
console.error('state:', this.state, 'config:', this.config);
throw new Error('state or config is not set.');
}
OAuth2AuthCodePKCE.prototype.decorateFetchHTTPClient = function (fetch) {
var _this = this;
return function (url, config) {
var rest = [];
for (var _i = 2; _i < arguments.length; _i++) {
rest[_i - 2] = arguments[_i];
}
return _this
.getAccessToken()
.then(function (_a) {
var token = _a.token;
var configNew = Object.assign({}, config);
if (!configNew.headers) {
configNew.headers = {};
}
configNew.headers[HEADER_AUTHORIZATION] = "Bearer " + token.value;
return fetch.apply(void 0, __spreadArrays([url, configNew], rest));
})
.then(function (res) {
if (res.ok) {
return res;
}
if (!res.headers.has(HEADER_WWW_AUTHENTICATE.toLowerCase())) {
return res;
}
return Promise.reject(toErrorClass(fromWWWAuthenticateHeaderStringToObject(res.headers.get(HEADER_WWW_AUTHENTICATE.toLowerCase())).error));
});
};
};

@@ -404,72 +480,2 @@ /**

/**
* Fetch an access token from the remote service. You may pass a custom
* authorization grant code for any reason, but this is non-standard usage.
*/
OAuth2AuthCodePKCE.prototype.exchangeAuthCodeForAccessToken = function (codeOverride) {
var _this = this;
this.assertStateAndConfigArePresent();
var _a = this.state, _b = _a.authorizationCode, authorizationCode = _b === void 0 ? codeOverride : _b, _c = _a.codeVerifier, codeVerifier = _c === void 0 ? '' : _c;
var _d = this.config, clientId = _d.clientId, onInvalidGrant = _d.onInvalidGrant, redirectUrl = _d.redirectUrl;
if (!codeVerifier) {
console.warn('No code verifier is being sent.');
}
else if (!authorizationCode) {
console.warn('No authorization grant code is being passed.');
}
var url = this.config.tokenUrl;
var body = "grant_type=authorization_code&"
+ ("code=" + encodeURIComponent(authorizationCode || '') + "&")
+ ("redirect_uri=" + encodeURIComponent(redirectUrl) + "&")
+ ("client_id=" + encodeURIComponent(clientId) + "&")
+ ("code_verifier=" + codeVerifier);
return fetch(url, {
method: 'POST',
body: body,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function (res) {
var jsonPromise = res.json()
.catch(function (_) { return ({ error: 'invalid_json' }); });
if (!res.ok) {
return jsonPromise.then(function (_a) {
var error = _a.error;
switch (error) {
case 'invalid_grant':
onInvalidGrant(function () { return _this.fetchAuthorizationCode(); });
break;
default:
break;
}
return Promise.reject(toErrorClass(error));
});
}
return jsonPromise.then(function (_a) {
var access_token = _a.access_token, expires_in = _a.expires_in, refresh_token = _a.refresh_token, scope = _a.scope;
var scopes = [];
_this.state.hasAuthCodeBeenExchangedForAccessToken = true;
var accessToken = {
value: access_token,
expiry: (new Date(Date.now() + (parseInt(expires_in) * 1000))).toString()
};
_this.state.accessToken = accessToken;
if (refresh_token) {
var refreshToken = {
value: refresh_token
};
_this.state.refreshToken = refreshToken;
}
if (scope) {
// Multiple scopes are passed and delimited by spaces,
// despite using the singular name "scope".
scopes = scope.split(' ');
_this.state.scopes = scopes;
}
localStorage.setItem(exports.LOCALSTORAGE_STATE, JSON.stringify(_this.state));
return { token: accessToken, scopes: scopes };
});
});
};
/**
* Fetch an authorization grant via redirection. In a sense this function

@@ -598,2 +604,82 @@ * doesn't return because of the redirect behavior (uses `location.replace`).

};
/**
* If the state or config are missing, it means the client is in a bad state.
* This should never happen, but the check is there just in case.
*/
OAuth2AuthCodePKCE.prototype.assertStateAndConfigArePresent = function () {
if (!this.state || !this.config) {
console.error('state:', this.state, 'config:', this.config);
throw new Error('state or config is not set.');
}
};
/**
* Fetch an access token from the remote service. You may pass a custom
* authorization grant code for any reason, but this is non-standard usage.
*/
OAuth2AuthCodePKCE.prototype.exchangeAuthCodeForAccessToken = function (codeOverride) {
var _this = this;
this.assertStateAndConfigArePresent();
var _a = this.state, _b = _a.authorizationCode, authorizationCode = _b === void 0 ? codeOverride : _b, _c = _a.codeVerifier, codeVerifier = _c === void 0 ? '' : _c;
var _d = this.config, clientId = _d.clientId, onInvalidGrant = _d.onInvalidGrant, redirectUrl = _d.redirectUrl;
if (!codeVerifier) {
console.warn('No code verifier is being sent.');
}
else if (!authorizationCode) {
console.warn('No authorization grant code is being passed.');
}
var url = this.config.tokenUrl;
var body = "grant_type=authorization_code&"
+ ("code=" + encodeURIComponent(authorizationCode || '') + "&")
+ ("redirect_uri=" + encodeURIComponent(redirectUrl) + "&")
+ ("client_id=" + encodeURIComponent(clientId) + "&")
+ ("code_verifier=" + codeVerifier);
return fetch(url, {
method: 'POST',
body: body,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function (res) {
var jsonPromise = res.json()
.catch(function (_) { return ({ error: 'invalid_json' }); });
if (!res.ok) {
return jsonPromise.then(function (_a) {
var error = _a.error;
switch (error) {
case 'invalid_grant':
onInvalidGrant(function () { return _this.fetchAuthorizationCode(); });
break;
default:
break;
}
return Promise.reject(toErrorClass(error));
});
}
return jsonPromise.then(function (_a) {
var access_token = _a.access_token, expires_in = _a.expires_in, refresh_token = _a.refresh_token, scope = _a.scope;
var scopes = [];
_this.state.hasAuthCodeBeenExchangedForAccessToken = true;
var accessToken = {
value: access_token,
expiry: (new Date(Date.now() + (parseInt(expires_in) * 1000))).toString()
};
_this.state.accessToken = accessToken;
if (refresh_token) {
var refreshToken = {
value: refresh_token
};
_this.state.refreshToken = refreshToken;
}
if (scope) {
// Multiple scopes are passed and delimited by spaces,
// despite using the singular name "scope".
scopes = scope.split(' ');
_this.state.scopes = scopes;
}
localStorage.setItem(exports.LOCALSTORAGE_STATE, JSON.stringify(_this.state));
return { token: accessToken, scopes: scopes };
});
});
};
OAuth2AuthCodePKCE.prototype.recoverState = function () {

@@ -600,0 +686,0 @@ this.state = JSON.parse(localStorage.getItem(exports.LOCALSTORAGE_STATE) || '{}');

{
"name": "@bity/oauth2-auth-code-pkce",
"version": "2.1.1",
"version": "2.2.0",
"description": "An OAuth 2.0 client that ONLY supports Authorization Code flow with PKCE support.",

@@ -5,0 +5,0 @@ "main": "index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc