Skip to content

Commit

Permalink
fix: adjusts restoreOriginalUri warning & issue with routing samples
Browse files Browse the repository at this point in the history
OKTA-500147
<<<Jenkins Check-In of Tested SHA: 9f2a625 for eng_productivity_ci_bot_okta@okta.com>>>
Artifact: okta-react
Files changed count: 27
PR Link: #239
  • Loading branch information
jaredperreault-okta authored and eng-prod-CI-bot-okta committed Jun 30, 2022
1 parent 5d50adc commit 5afc5ef
Show file tree
Hide file tree
Showing 27 changed files with 685 additions and 16 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# 6.6.0

- [#239](https://github.com/okta/okta-react/pull/239)
- Fixes `Two custom restoreOriginalUri callbacks are detected` warning, will only fire once on `<Security>` didMount
- Fixes react-router v6 routing samples, no longer calls `/authorize` on page load with valid, active session

# 6.5.0

### Others
Expand Down
2 changes: 1 addition & 1 deletion samples/routing/react-router-dom-v5-hash/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import Routes from './components/Routes';
const oktaAuth = new OktaAuth({
issuer: process.env.ISSUER,
clientId: process.env.SPA_CLIENT_ID,
redirectUri: window.location.origin + '/login/callback'
redirectUri: window.location.origin + '/'
});

function App() {
Expand Down
2 changes: 1 addition & 1 deletion samples/routing/react-router-dom-v6-hash/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import Routes from './components/Routes';
const oktaAuth = new OktaAuth({
issuer: process.env.ISSUER,
clientId: process.env.SPA_CLIENT_ID,
redirectUri: window.location.origin + '/login/callback'
redirectUri: window.location.origin + '/'
});

function App() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* See the License for the specific language governing permissions and limitations under the License.
*/

import React from 'react';
import React, { useEffect } from 'react';
import { useOktaAuth } from '@okta/okta-react';
import { toRelativeUrl } from '@okta/okta-auth-js';
import { Outlet } from 'react-router-dom';
Expand All @@ -20,15 +20,19 @@ import Loading from './Loading';
export const RequiredAuth: React.FC = () => {
const { oktaAuth, authState } = useOktaAuth();

if (oktaAuth.token.isLoginRedirect()) {
return (<Loading />);
}
useEffect(() => {
if (!authState) {
return;
}

if (!authState || !authState?.isAuthenticated) {
const originalUri = toRelativeUrl(window.location.href, window.location.origin);
oktaAuth.setOriginalUri(originalUri);
oktaAuth.signInWithRedirect();
if (!authState?.isAuthenticated) {
const originalUri = toRelativeUrl(window.location.href, window.location.origin);
oktaAuth.setOriginalUri(originalUri);
oktaAuth.signInWithRedirect();
}
}, [oktaAuth, !!authState, authState?.isAuthenticated]);

if (!authState || !authState?.isAuthenticated) {
return (<Loading />);
}

Expand Down
18 changes: 13 additions & 5 deletions samples/routing/react-router-dom-v6/src/components/SecureRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* See the License for the specific language governing permissions and limitations under the License.
*/

import React from 'react';
import React, { useEffect } from 'react';
import { useOktaAuth } from '@okta/okta-react';
import { toRelativeUrl } from '@okta/okta-auth-js';
import { Outlet } from 'react-router-dom';
Expand All @@ -19,11 +19,19 @@ import Loading from './Loading';
export const RequiredAuth: React.FC = () => {
const { oktaAuth, authState } = useOktaAuth();

if (!authState || !authState?.isAuthenticated) {
const originalUri = toRelativeUrl(window.location.href, window.location.origin);
oktaAuth.setOriginalUri(originalUri);
oktaAuth.signInWithRedirect();
useEffect(() => {
if (!authState) {
return;
}

if (!authState?.isAuthenticated) {
const originalUri = toRelativeUrl(window.location.href, window.location.origin);
oktaAuth.setOriginalUri(originalUri);
oktaAuth.signInWithRedirect();
}
}, [oktaAuth, !!authState, authState?.isAuthenticated]);

if (!authState || !authState?.isAuthenticated) {
return (<Loading />);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Security.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const Security: React.FC<{
restoreOriginalUri(oktaAuth as OktaAuth, originalUri);
}) as ((oktaAuth: OktaAuth, originalUri?: string) => Promise<void>);

}, [oktaAuth, restoreOriginalUri]);
}, []); // empty array, only check on component mount

React.useEffect(() => {
if (!oktaAuth) {
Expand Down
24 changes: 24 additions & 0 deletions test/apps/v6-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
13 changes: 13 additions & 0 deletions test/apps/v6-app/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>
26 changes: 26 additions & 0 deletions test/apps/v6-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "@okta/test.app.v6-app",
"private": true,
"version": "0.0.0",
"scripts": {
"prestart": "vite build",
"start": "vite preview --port 8080",
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "6.3.0",
"@okta/okta-auth-js": "*",
"@okta/okta-react": "*"
},
"devDependencies": {
"@types/react": "^17.0.33",
"@types/react-dom": "^17.0.10",
"@vitejs/plugin-react": "^1.3.2",
"typescript": "^4.5.4",
"vite": "^2.8.0"
}
}
24 changes: 24 additions & 0 deletions test/apps/v6-app/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.App {
text-align: center;
}

.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 80px;
}

.App-header {
background-color: #222;
height: 150px;
padding: 20px;
color: white;
}

.App-intro {
font-size: large;
}

@keyframes App-logo-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
70 changes: 70 additions & 0 deletions test/apps/v6-app/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*!
* Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*/

import * as React from 'react';
import { Route, Routes, useNavigate } from 'react-router-dom';
import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js';
import { Security, LoginCallback } from '@okta/okta-react';
import { SecureRoute } from './SecureRoute';
import Home from './Home';
import Protected from './Protected';
import CustomLogin from './CustomLogin';
import WidgetLogin from './WidgetLogin';
import SessionTokenLogin from './SessionTokenLogin';

const App: React.FC<{
oktaAuth: OktaAuth;
customLogin: boolean;
baseUrl: string;
}> = ({ oktaAuth, customLogin, baseUrl }) => {
const navigate = useNavigate();

const onAuthRequired = async () => {
navigate('/login');
};

const onAuthResume = async () => {
navigate('/widget-login');
};

const restoreOriginalUri = async (_oktaAuth: OktaAuth, originalUri: string) => {
navigate(toRelativeUrl(originalUri || '/', window.location.origin));
};

return (
<React.StrictMode>
<Security
oktaAuth={oktaAuth}
onAuthRequired={customLogin ? onAuthRequired : undefined}
restoreOriginalUri={restoreOriginalUri}
>
<Routes>
<Route path='/login' element={<CustomLogin />} />
<Route path='/widget-login' element={<WidgetLogin baseUrl={baseUrl} />} />
<Route path='/sessionToken-login' element={<SessionTokenLogin />} />
<Route path='/protected' element={<SecureRoute />}>
<Route path='' element={<Protected />} />
</Route>
<Route path='/implicit/callback' element={<LoginCallback />} />
<Route path='/pkce/callback' element={<LoginCallback
onAuthResume={ onAuthResume }
loadingElement={ <p id='login-callback-loading'>Loading...</p> }
/>}/>
<Route path='/' element={<Home />} />
</Routes>
</Security>
<a href="/?pkce=1">PKCE Flow</a> | <a href="/">Implicit Flow</a>
</React.StrictMode>
);
};

export default App;
26 changes: 26 additions & 0 deletions test/apps/v6-app/src/CustomLogin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*!
* Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*/

import * as React from 'react';
import { useOktaAuth } from '@okta/okta-react';

const CustomLogin: React.FC = () => {
const { oktaAuth } = useOktaAuth();

React.useEffect(() => {
oktaAuth.signInWithRedirect();
}, [oktaAuth]);

return null;
};

export default CustomLogin;
58 changes: 58 additions & 0 deletions test/apps/v6-app/src/Home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*!
* Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*/

// implement with "useOktaAuth" hook
import * as React from 'react';
import { Link } from 'react-router-dom';
import { useOktaAuth } from '@okta/okta-react';

const Home: React.FC = () => {
const { oktaAuth, authState } = useOktaAuth();
const [renewMessage, setRenewMessage] = React.useState('');

const login = async () => oktaAuth.signInWithRedirect({ originalUri: '/protected' });
const logout = async () => oktaAuth.signOut();
const renewToken = (tokenName: string) => async () => {
oktaAuth.tokenManager.renew(tokenName)
.then(() => setRenewMessage(`Token ${tokenName} was renewed`))
.catch(e => setRenewMessage(`Error renewing ${tokenName}: ${e}`));
}

if (!authState) {
return null;
}

const button = authState.isAuthenticated ?
<button id="logout-button" onClick={logout}>Logout</button> :
<button id="login-button" onClick={login}>Login</button>;

const pkce = oktaAuth.isPKCE();

return (
<div>
<div id="login-flow">{ pkce ? 'PKCE' : 'implicit'}</div>
<hr/>
<Link to='/'>Home</Link><br/>
<Link to='/protected'>Protected</Link><br/>
<Link to='/sessionToken-login'>Session Token Login</Link><br/>
<Link to='/widget-login'>Widget Login</Link><br/>
{button}
{ authState.isAuthenticated ? <button id="renew-id-token-button" onClick={renewToken('idToken')}>Renew ID Token</button> : null }
{ authState.isAuthenticated ? <button id="renew-access-token-button" onClick={renewToken('accessToken')}>Renew Access Token</button> : null }
<div id="renew-message">
{ renewMessage }
</div>
</div>
);
};

export default Home;
42 changes: 42 additions & 0 deletions test/apps/v6-app/src/Protected.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*!
* Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*/

// implement with "withOktaAuth" HOC
import * as React from 'react';
import { OktaAuth } from '@okta/okta-auth-js';
import { withOktaAuth } from '@okta/okta-react';

const Protected: React.FC<{ oktaAuth: OktaAuth }> = ({ oktaAuth }) => {
const [userInfo, setUserInfo] = React.useState('');

React.useEffect(() => {
const fetchUser = async () => {
const claims = await oktaAuth.getUser();
const userinfo = JSON.stringify(claims, null, 4);
setUserInfo(userinfo);
};

fetchUser();
}, [oktaAuth]);

const logout = async () => oktaAuth.signOut();

return (
<div>
<div> Protected! </div>
{userInfo && <pre id="userinfo-container"> {userInfo} </pre>}
<button id="logout-button" onClick={logout}>Logout</button>
</div>
);
};

export default withOktaAuth(Protected);
Loading

0 comments on commit 5afc5ef

Please sign in to comment.