Skip to content

Commit 0cfa6c8

Browse files
committed
Allow using customstate
1 parent cf73454 commit 0cfa6c8

File tree

4 files changed

+24
-6
lines changed

4 files changed

+24
-6
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "js-pkce",
3-
"version": "1.1.2",
3+
"version": "1.1.3",
44
"description": "A package that makes using the OAuth2 PKCE flow easier",
55
"main": "dist/PKCE.js",
66
"types": "dist/PKCE.d.ts",

src/IObject.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default interface IObject {
2+
[key: string]: any;
3+
}

src/PKCE.ts

+12-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Base64 from 'crypto-js/enc-base64';
33
import WordArray from 'crypto-js/lib-typedarrays';
44
import IAuthResponse from './IAuthResponse';
55
import IConfig from './IConfig';
6+
import IObject from './IObject';
67
import ITokenResponse from './ITokenResponse';
78

89
export default class PKCE {
@@ -23,15 +24,15 @@ export default class PKCE {
2324
* @param {object} additionalParams include additional parameters in the query
2425
* @return Promise<string>
2526
*/
26-
public authorizeUrl(additionalParams: object = {}): string {
27+
public authorizeUrl(additionalParams: IObject = {}): string {
2728
const codeChallenge = this.pkceChallengeFromVerifier();
2829

2930
const queryString = new URLSearchParams(
3031
Object.assign(
3132
{
3233
response_type: 'code',
3334
client_id: this.config.client_id,
34-
state: this.getState(),
35+
state: this.getState(additionalParams.state || null),
3536
scope: this.config.requested_scopes,
3637
redirect_uri: this.config.redirect_uri,
3738
code_challenge: codeChallenge,
@@ -50,7 +51,7 @@ export default class PKCE {
5051
* @param {object} additionalParams include additional parameters in the request body
5152
* @return {Promise<ITokenResponse>}
5253
*/
53-
public exchangeForAccessToken(url: string, additionalParams: object = {}): Promise<ITokenResponse> {
54+
public exchangeForAccessToken(url: string, additionalParams: IObject = {}): Promise<ITokenResponse> {
5455
return this.parseAuthResponseUrl(url).then((q) => {
5556
return fetch(this.config.token_endpoint, {
5657
method: 'POST',
@@ -90,9 +91,15 @@ export default class PKCE {
9091
* Get the current state or generate a new one
9192
* @return {string}
9293
*/
93-
private getState(): string {
94+
private getState(explicit: string = null): string {
95+
const stateKey = 'pkce_state';
96+
97+
if (explicit !== null) {
98+
sessionStorage.setItem(stateKey, explicit);
99+
}
100+
94101
if (this.state === '') {
95-
this.state = this.randomStringFromStorage('pkce_state');
102+
this.state = this.randomStringFromStorage(stateKey);
96103
}
97104

98105
return this.state;

tests/PKCE.test.ts

+8
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ describe('Test PKCE authorization url', () => {
3434
expect(url).toContain('&client_id=' + config.client_id);
3535
expect(url).toContain('&test_param=test');
3636
});
37+
38+
it('Should update state from additional params', async () => {
39+
const instance = new PKCE(config);
40+
const url = instance.authorizeUrl({state: 'Anewteststate'});
41+
42+
expect(url).toContain('&state=Anewteststate');
43+
expect(sessionStorage.getItem('pkce_state')).toEqual('Anewteststate');
44+
});
3745
});
3846

3947
describe('Test PKCE exchange code for token', () => {

0 commit comments

Comments
 (0)