diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c34f161 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +### Changelog + +All notable changes to this project will be documented in this file. Dates are displayed in UTC. + +Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). + +#### 1.3.0 + +- Change type login and register [`#29`](https://github.com/kinde-oss/kinde-react-native-sdk-0-7x/pull/29) +- feature/force-token-refresh [`#32`](https://github.com/kinde-oss/kinde-react-native-sdk-0-7x/pull/32) \ No newline at end of file diff --git a/__tests__/index.spec.ts b/__tests__/index.spec.ts index 5025035..5ef710c 100644 --- a/__tests__/index.spec.ts +++ b/__tests__/index.spec.ts @@ -287,20 +287,22 @@ describe('KindeSDK', () => { test('[RNStorage] Open authenticate endpoint', async () => { InAppBrowser.isAvailable = jest.fn().mockReturnValue(true); await globalClient.login(); - const URLParsed = Url(`${configuration.issuer}/oauth2/auth`, true); - URLParsed.query['client_id'] = configuration.clientId; - URLParsed.query['redirect_uri'] = configuration.redirectUri; - URLParsed.query['client_secret'] = configuration.clientSecret; - URLParsed.query['scope'] = configuration.scope; - URLParsed.query['grant_type'] = 'authorization_code'; - URLParsed.query['response_type'] = 'code'; - URLParsed.query['start_page'] = 'login'; - URLParsed.query['state'] = configuration.fakeState; - URLParsed.query['code_challenge'] = configuration.fakeCodeChallenge; - URLParsed.query['code_challenge_method'] = 'S256'; + + const urlParmams = new URLSearchParams({ + client_id: configuration.clientId, + redirect_uri: configuration.redirectUri, + client_secret: configuration.clientSecret || '', + scope: configuration.scope, + grant_type: 'authorization_code', + response_type: 'code', + start_page: 'login', + state: configuration.fakeState, + code_challenge: configuration.fakeCodeChallenge, + code_challenge_method: 'S256' + }).toString(); expect(InAppBrowser.openAuth).toHaveBeenCalledWith( - URLParsed.toString(), + `${configuration.issuer}/oauth2/auth?${urlParmams}`, globalClient.redirectUri, { enableDefaultShare: false, @@ -314,19 +316,36 @@ describe('KindeSDK', () => { test('[RNStorage] Open registration endpoint', async () => { InAppBrowser.isAvailable = jest.fn().mockReturnValue(true); await globalClient.register(); - const URLParsed = Url(configuration.authorizationEndpoint, true); - URLParsed.query['client_id'] = configuration.clientId; - URLParsed.query['redirect_uri'] = configuration.redirectUri; - URLParsed.query['client_secret'] = configuration.clientSecret; - URLParsed.query['scope'] = configuration.scope; - URLParsed.query['grant_type'] = 'authorization_code'; - URLParsed.query['response_type'] = 'code'; - URLParsed.query['start_page'] = 'registration'; - URLParsed.query['state'] = configuration.fakeState; - URLParsed.query['code_challenge'] = configuration.fakeCodeChallenge; - URLParsed.query['code_challenge_method'] = 'S256'; + + console.log( + new URLSearchParams({ + client_id: configuration.clientId || '', + redirect_uri: configuration.redirectUri || '', + client_secret: configuration.clientSecret || '', + scope: configuration.scope || '', + grant_type: 'authorization_code', + response_type: 'code', + start_page: 'registration', + state: configuration.fakeState || '', + code_challenge: configuration.fakeCodeChallenge || '', + code_challenge_method: 'S256' + }).toString() + ); expect(InAppBrowser.openAuth).toHaveBeenCalledWith( - URLParsed.toString(), + configuration.authorizationEndpoint + + '?' + + new URLSearchParams({ + client_id: configuration.clientId || '', + redirect_uri: configuration.redirectUri || '', + client_secret: configuration.clientSecret || '', + scope: configuration.scope || '', + grant_type: 'authorization_code', + response_type: 'code', + start_page: 'registration', + state: configuration.fakeState || '', + code_challenge: configuration.fakeCodeChallenge || '', + code_challenge_method: 'S256' + }).toString(), globalClient.redirectUri, { enableDefaultShare: false, @@ -340,10 +359,10 @@ describe('KindeSDK', () => { test('[RNStorage] Logout', async () => { InAppBrowser.isAvailable = jest.fn().mockReturnValue(true); await globalClient.logout(); - const URLParsed = Url(configuration.logoutEndpoint, true); - URLParsed.query['redirect'] = configuration.logoutRedirectUri; expect(InAppBrowser.openAuth).toHaveBeenCalledWith( - URLParsed.toString(), + `${configuration.logoutEndpoint}?${new URLSearchParams({ + redirect: configuration.logoutRedirectUri + }).toString()}`, globalClient.redirectUri, { enableDefaultShare: false, @@ -390,20 +409,23 @@ describe('KindeSDK', () => { test('[RNStorage] Create Organization', async () => { InAppBrowser.isAvailable = jest.fn().mockReturnValue(true); await globalClient.createOrg(); - const URLParsed = Url(configuration.authorizationEndpoint, true); - URLParsed.query['client_id'] = configuration.clientId; - URLParsed.query['redirect_uri'] = configuration.redirectUri; - URLParsed.query['client_secret'] = configuration.clientSecret; - URLParsed.query['scope'] = configuration.scope; - URLParsed.query['grant_type'] = 'authorization_code'; - URLParsed.query['response_type'] = 'code'; - URLParsed.query['start_page'] = 'registration'; - URLParsed.query['state'] = configuration.fakeState; - URLParsed.query['is_create_org'] = true; - URLParsed.query['code_challenge'] = configuration.fakeCodeChallenge; - URLParsed.query['code_challenge_method'] = 'S256'; + + const urlParsed = new URLSearchParams({ + client_id: configuration.clientId || '', + redirect_uri: configuration.redirectUri || '', + client_secret: configuration.clientSecret || '', + scope: configuration.scope || '', + grant_type: 'authorization_code', + response_type: 'code', + start_page: 'registration', + state: configuration.fakeState || '', + is_create_org: true, + code_challenge: configuration.fakeCodeChallenge || '', + code_challenge_method: 'S256' + }).toString(); + expect(InAppBrowser.openAuth).toHaveBeenCalledWith( - URLParsed.toString(), + `${configuration.authorizationEndpoint}?${urlParsed}`, globalClient.redirectUri, { enableDefaultShare: false, @@ -459,20 +481,22 @@ describe('KindeSDK', () => { Constants.executionEnvironment = 'storeClient'; await globalClient.login(); - const URLParsed = Url(`${configuration.issuer}/oauth2/auth`, true); - URLParsed.query['client_id'] = configuration.clientId; - URLParsed.query['redirect_uri'] = configuration.redirectUri; - URLParsed.query['client_secret'] = configuration.clientSecret; - URLParsed.query['scope'] = configuration.scope; - URLParsed.query['grant_type'] = 'authorization_code'; - URLParsed.query['response_type'] = 'code'; - URLParsed.query['start_page'] = 'login'; - URLParsed.query['state'] = configuration.fakeState; - URLParsed.query['code_challenge'] = configuration.fakeCodeChallenge; - URLParsed.query['code_challenge_method'] = 'S256'; + + const urlParsed = new URLSearchParams({ + client_id: configuration.clientId || '', + redirect_uri: configuration.redirectUri || '', + client_secret: configuration.clientSecret || '', + scope: configuration.scope || '', + grant_type: 'authorization_code', + response_type: 'code', + start_page: 'login', + state: configuration.fakeState || '', + code_challenge: configuration.fakeCodeChallenge || '', + code_challenge_method: 'S256' + }).toString(); expect(openAuthSessionAsync).toHaveBeenCalledWith( - URLParsed.toString(), + `${configuration.issuer}/oauth2/auth?${urlParsed}`, globalClient.redirectUri ); }); @@ -481,20 +505,22 @@ describe('KindeSDK', () => { Constants.executionEnvironment = 'storeClient'; await globalClient.register(); - const URLParsed = Url(configuration.authorizationEndpoint, true); - URLParsed.query['client_id'] = configuration.clientId; - URLParsed.query['redirect_uri'] = configuration.redirectUri; - URLParsed.query['client_secret'] = configuration.clientSecret; - URLParsed.query['scope'] = configuration.scope; - URLParsed.query['grant_type'] = 'authorization_code'; - URLParsed.query['response_type'] = 'code'; - URLParsed.query['start_page'] = 'registration'; - URLParsed.query['state'] = configuration.fakeState; - URLParsed.query['code_challenge'] = configuration.fakeCodeChallenge; - URLParsed.query['code_challenge_method'] = 'S256'; + + const urlParsed = new URLSearchParams({ + client_id: configuration.clientId || '', + redirect_uri: configuration.redirectUri || '', + client_secret: configuration.clientSecret || '', + scope: configuration.scope || '', + grant_type: 'authorization_code', + response_type: 'code', + start_page: 'registration', + state: configuration.fakeState || '', + code_challenge: configuration.fakeCodeChallenge || '', + code_challenge_method: 'S256' + }).toString(); expect(openAuthSessionAsync).toHaveBeenCalledWith( - URLParsed.toString(), + `${configuration.authorizationEndpoint}?${urlParsed}`, globalClient.redirectUri ); }); @@ -503,11 +529,11 @@ describe('KindeSDK', () => { Constants.executionEnvironment = 'storeClient'; await globalClient.logout(); - const URLParsed = Url(configuration.logoutEndpoint, true); - URLParsed.query['redirect'] = configuration.logoutRedirectUri; expect(openAuthSessionAsync).toHaveBeenCalledWith( - URLParsed.toString(), + `${configuration.logoutEndpoint}?${new URLSearchParams({ + redirect: configuration.logoutRedirectUri + }).toString()}`, globalClient.redirectUri ); }); @@ -548,21 +574,23 @@ describe('KindeSDK', () => { test('[ExpoStorage] Create Organization', async () => { Constants.executionEnvironment = 'storeClient'; await globalClient.createOrg(); - const URLParsed = Url(configuration.authorizationEndpoint, true); - URLParsed.query['client_id'] = configuration.clientId; - URLParsed.query['redirect_uri'] = configuration.redirectUri; - URLParsed.query['client_secret'] = configuration.clientSecret; - URLParsed.query['scope'] = configuration.scope; - URLParsed.query['grant_type'] = 'authorization_code'; - URLParsed.query['response_type'] = 'code'; - URLParsed.query['start_page'] = 'registration'; - URLParsed.query['state'] = configuration.fakeState; - URLParsed.query['is_create_org'] = true; - URLParsed.query['code_challenge'] = configuration.fakeCodeChallenge; - URLParsed.query['code_challenge_method'] = 'S256'; + + const urlParsed = new URLSearchParams({ + client_id: configuration.clientId || '', + redirect_uri: configuration.redirectUri || '', + client_secret: configuration.clientSecret || '', + scope: configuration.scope || '', + grant_type: 'authorization_code', + response_type: 'code', + start_page: 'registration', + state: configuration.fakeState || '', + is_create_org: true, + code_challenge: configuration.fakeCodeChallenge || '', + code_challenge_method: 'S256' + }).toString(); expect(openAuthSessionAsync).toHaveBeenCalledWith( - URLParsed.toString(), + `${configuration.authorizationEndpoint}?${urlParsed}`, globalClient.redirectUri ); }); diff --git a/package.json b/package.json index 94b215d..95b01b9 100644 --- a/package.json +++ b/package.json @@ -43,11 +43,8 @@ "expo-web-browser": "12.8.2", "expo-secure-store": "^12.1.1", "jwt-decode": "^3.1.2", - "qs": "^6.11.0", "react-native-inappbrowser-reborn": "^3.7.0", - "react-native-keychain": ">= 8.0", - "superagent": "^7.0.2", - "url-parse": "^1.5.10" + "react-native-keychain": ">= 8.0" }, "devDependencies": { "@babel/cli": "^7.0.0", diff --git a/src/SDK/KindeSDK.ts b/src/SDK/KindeSDK.ts index 7bab5a3..0f84787 100644 --- a/src/SDK/KindeSDK.ts +++ b/src/SDK/KindeSDK.ts @@ -188,9 +188,13 @@ class KindeSDK extends runtime.BaseAPI { await this.cleanUp(); if (isRevoke) { - const payload = new AuthorizationCode().buildBaseAuthenticateURL( - this - ); + const payload = new URLSearchParams({ + client_id: this.clientId, + redirect_uri: this.redirectUri, + client_secret: this.clientSecret || '', + scope: this.scope, + grant_type: 'authorization_code' + }); try { await this.request({ @@ -206,10 +210,10 @@ class KindeSDK extends runtime.BaseAPI { } } - const URLParsed = Url(this.logoutEndpoint, true); - URLParsed.query['redirect'] = this.logoutRedirectUri; const response = await openWebBrowser( - URLParsed.toString(), + this.logoutEndpoint + + '?' + + new URLSearchParams({ redirect: this.logoutRedirectUri }), this.redirectUri, authBrowserOptions || this.authBrowserOptions ); @@ -235,10 +239,13 @@ class KindeSDK extends runtime.BaseAPI { checkNotNull(url, 'URL'); - const URLParsed = Url(String(url), true); - const { code, error, error_description } = URLParsed.query; + const params = new URL(url!).searchParams; + + const code = params.get('code'); + const error = params.get('error'); + const errorDescription = params.get('error_description'); if (error) { - const msg = error_description ?? error; + const msg = errorDescription ?? error; throw new UnAuthenticatedException(msg); } checkNotNull(code, 'code'); diff --git a/src/SDK/OAuth/AuthorizationCode.ts b/src/SDK/OAuth/AuthorizationCode.ts index 4945f18..0dde0c1 100644 --- a/src/SDK/OAuth/AuthorizationCode.ts +++ b/src/SDK/OAuth/AuthorizationCode.ts @@ -17,13 +17,11 @@ * @version 1.2.2 */ -import Url from 'url-parse'; import { AdditionalParameters, TokenResponse } from '../../types/KindeSDK'; import KindeSDK from '../KindeSDK'; import Storage from '../Storage'; import { OpenWebInApp, - addAdditionalParameters, generateChallenge, generateRandomString } from '../Utils'; @@ -45,39 +43,37 @@ class AuthorizationCode { additionalParameters: AdditionalParameters = {}, options?: AuthBrowserOptions ): Promise { - const URLParsed = Url(kindeSDK.authorizationEndpoint, true); - const baseInfo = this.buildBaseAuthenticateURL(kindeSDK); - - Object.keys(baseInfo).forEach((k) => { - URLParsed.query[k] = baseInfo[k]; - }); - - URLParsed.query['start_page'] = startPage; - const stateGenerated = generateRandomString(); - URLParsed.query['state'] = stateGenerated; - addAdditionalParameters(URLParsed.query, additionalParameters); Storage.setState(stateGenerated); + + let pkce; if (usePKCE) { - const challenge = generateChallenge(); - URLParsed.query['code_challenge'] = challenge.codeChallenge; - URLParsed.query['code_challenge_method'] = 'S256'; - Storage.setCodeVerifier(challenge.codeVerifier); + const { codeChallenge, codeVerifier } = generateChallenge(); + Storage.setCodeVerifier(codeVerifier); + pkce = { + code_challenge: codeChallenge, + code_challenge_method: 'S256' + }; } - return OpenWebInApp(URLParsed.toString(), kindeSDK, options); - } - buildBaseAuthenticateURL( - kindeSDK: KindeSDK - ): Record { - return { + const urlParams = new URLSearchParams({ client_id: kindeSDK.clientId, redirect_uri: kindeSDK.redirectUri, - client_secret: kindeSDK.clientSecret, + client_secret: kindeSDK.clientSecret || '', scope: kindeSDK.scope, grant_type: 'authorization_code', - response_type: 'code' - }; + response_type: 'code', + start_page: startPage, + state: stateGenerated, + ...(additionalParameters as Record), + ...pkce + }).toString(); + + return OpenWebInApp( + `${kindeSDK.authorizationEndpoint}?${urlParams}`, + kindeSDK, + options + ); } }