Skip to content

Commit 229582f

Browse files
committed
finish token renewal
1 parent 5f6f331 commit 229582f

7 files changed

Lines changed: 395 additions & 74 deletions

File tree

05-Token-Renewal/src/Auth/Auth.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import history from '../history';
44

55
export default class Auth {
66
userProfile;
7+
tokenRenewalTimeout;
78

89
auth0 = new auth0.WebAuth({
910
domain: AUTH_CONFIG.domain,
@@ -21,6 +22,7 @@ export default class Auth {
2122
this.isAuthenticated = this.isAuthenticated.bind(this);
2223
this.getAccessToken = this.getAccessToken.bind(this);
2324
this.getProfile = this.getProfile.bind(this);
25+
this.scheduleRenewal();
2426
}
2527

2628
login() {
@@ -49,6 +51,10 @@ export default class Auth {
4951
localStorage.setItem('access_token', authResult.accessToken);
5052
localStorage.setItem('id_token', authResult.idToken);
5153
localStorage.setItem('expires_at', expiresAt);
54+
55+
// schedule a token renewal
56+
this.scheduleRenewal();
57+
5258
// navigate to the home route
5359
history.replace('/home');
5460
}
@@ -78,6 +84,7 @@ export default class Auth {
7884
localStorage.removeItem('expires_at');
7985
localStorage.removeItem('scopes');
8086
this.userProfile = null;
87+
clearTimeout(this.tokenRenewalTimeout);
8188
// navigate to the home route
8289
history.replace('/home');
8390
}
@@ -90,17 +97,32 @@ export default class Auth {
9097
}
9198

9299
renewToken() {
93-
this.auth0.renewAuth({
94-
audience: AUTH_CONFIG.apiUrl,
95-
redirectUri: 'http://localhost:3001/silent',
96-
usePostMessage: true
97-
}, (err, result) => {
98-
if (err) {
99-
alert(`Could not get a new token using silent authentication (${err.error}).`);
100-
} else {
101-
alert(`Successfully renewed auth!`);
102-
this.setSession(result);
100+
this.auth0.renewAuth(
101+
{
102+
audience: AUTH_CONFIG.apiUrl,
103+
redirectUri: AUTH_CONFIG.silentAuthRedirect,
104+
usePostMessage: true
105+
},
106+
(err, result) => {
107+
if (err) {
108+
alert(
109+
`Could not get a new token using silent authentication (${err.error}).`
110+
);
111+
} else {
112+
this.setSession(result);
113+
alert(`Successfully renewed auth!`);
114+
}
103115
}
104-
});
116+
);
117+
}
118+
119+
scheduleRenewal() {
120+
const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
121+
const delay = expiresAt - Date.now();
122+
if (delay > 0) {
123+
this.tokenRenewalTimeout = setTimeout(() => {
124+
this.renewToken();
125+
}, delay);
126+
}
105127
}
106128
}

05-Token-Renewal/src/Auth/auth0-variables.js.example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ export const AUTH_CONFIG = {
22
domain: '{DOMAIN}',
33
clientId: '{CLIENT_ID}',
44
callbackUrl: 'http://localhost:3000/callback',
5-
apiUrl: '{API_IDENTIFIER}'
5+
apiUrl: '{API_IDENTIFIER}',
6+
silentAuthRedirect: 'http://localhost:3001/silent'
67
}

05-Token-Renewal/src/Home/Home.js

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,38 @@
11
import React, { Component } from 'react';
22

33
class Home extends Component {
4+
getExpiryDate() {
5+
const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
6+
return JSON.stringify(new Date(expiresAt));
7+
}
48
render() {
59
const { isAuthenticated, login } = this.props.auth;
610
return (
711
<div className="container">
8-
{
9-
isAuthenticated() && (
10-
<h4>
11-
You are logged in!
12-
</h4>
13-
)
14-
}
15-
{
16-
!isAuthenticated() && (
17-
<h4>
18-
You are not logged in! Please{' '}
19-
<a style={{cursor:'pointer'}}
20-
onClick={login.bind(this)}
21-
>
22-
Log In
23-
</a>
24-
{' '}to continue.
25-
</h4>
26-
)
27-
}
12+
{isAuthenticated() &&
13+
<div>
14+
<h4>You are logged in!</h4>
15+
<h3>About Your Access Token</h3>
16+
<p>
17+
Your <code>access_token</code> has an expiry date of:{' '}
18+
{this.getExpiryDate()}
19+
</p>
20+
<p>
21+
The token has been scheduled for renewal using silent
22+
authentication, but you can also renew it manually from the navbar
23+
if you don't want to wait. This manual renewal button is really
24+
just for demonstration and you probably won't want such a control
25+
in your actual application.
26+
</p>
27+
</div>}
28+
{!isAuthenticated() &&
29+
<h4>
30+
You are not logged in! Please{' '}
31+
<a style={{ cursor: 'pointer' }} onClick={login.bind(this)}>
32+
Log In
33+
</a>{' '}
34+
to continue.
35+
</h4>}
2836
</div>
2937
);
3038
}

05-Token-Renewal/src/history.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
import createHistory from 'history/createBrowserHistory'
22

3-
export default createHistory({
4-
forceRefresh: true
5-
})
3+
export default createHistory()

05-Token-Renewal/src/routes.js

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { Redirect, Route, BrowserRouter } from 'react-router-dom';
2+
import { Redirect, Route, Router } from 'react-router-dom';
33
import App from './App';
44
import Home from './Home/Home';
55
import Profile from './Profile/Profile';
@@ -13,26 +13,29 @@ const handleAuthentication = (nextState, replace) => {
1313
if (/access_token|id_token|error/.test(nextState.location.hash)) {
1414
auth.handleAuthentication();
1515
}
16-
}
16+
};
1717

1818
export const makeMainRoutes = () => {
1919
return (
20-
<BrowserRouter history={history} component={App}>
21-
<div>
22-
<Route path="/" render={(props) => <App auth={auth} {...props} />} />
23-
<Route path="/home" render={(props) => <Home auth={auth} {...props} />} />
24-
<Route path="/profile" render={(props) => (
25-
!auth.isAuthenticated() ? (
26-
<Redirect to="/home"/>
27-
) : (
28-
<Profile auth={auth} {...props} />
29-
)
30-
)} />
31-
<Route path="/callback" render={(props) => {
20+
<Router history={history} component={App}>
21+
<div>
22+
<Route path="/" render={props => <App auth={auth} {...props} />} />
23+
<Route path="/home" render={props => <Home auth={auth} {...props} />} />
24+
<Route
25+
path="/profile"
26+
render={props =>
27+
!auth.isAuthenticated()
28+
? <Redirect to="/home" />
29+
: <Profile auth={auth} {...props} />}
30+
/>
31+
<Route
32+
path="/callback"
33+
render={props => {
3234
handleAuthentication(props);
33-
return <Callback {...props} />
34-
}}/>
35-
</div>
36-
</BrowserRouter>
35+
return <Callback {...props} />;
36+
}}
37+
/>
38+
</div>
39+
</Router>
3740
);
38-
}
41+
};

0 commit comments

Comments
 (0)