Skip to content

Commit 22b6d6a

Browse files
author
Steve Hobbs
authored
Migration of React tutorials from /docs (#123)
* Migrated tutorial 01 * Migrated tutorial for sample 02 * Migrated tutorial for sample 03 * Migrated tutorial for sample 04 * Migrated tutorial for sample 05 * Fixed replacement strings
1 parent 48c56b9 commit 22b6d6a

File tree

5 files changed

+919
-54
lines changed

5 files changed

+919
-54
lines changed

01-Login/README.md

Lines changed: 338 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,348 @@ You also need to set the environment variables as explained [previously](#set-th
4242

4343
Execute in command line `sh exec.sh` to run the Docker in Linux, or `.\exec.ps1` to run the Docker in Windows.
4444

45+
## Tutorial
46+
47+
### Create an Authentication Service
48+
49+
Create a service to manage and coordinate user authentication. You can give the service any name. In the examples below, the service is `Auth` and the filename is `Auth.js`.
50+
51+
In the service add an instance of the `auth0.WebAuth` object. When creating that instance, you can specify the following:
52+
53+
- Configuration for your application and domain
54+
- Response type, to show that you need a user's Access Token and an ID Token after authentication
55+
- Audience and scope, specifying that you need an `access_token` that can be used to invoke the [/userinfo endpoint](/api/authentication#get-user-info).
56+
- The URL where you want to redirect your users after authentication.
57+
58+
> **Note:** In this tutorial, the route is `/callback`, which is implemented in the [Add a Callback Component](#add-a-callback-component) step.
59+
60+
Add a `login` method that calls the `authorize` method from auth0.js.
61+
62+
```js
63+
// src/Auth/Auth.js
64+
65+
import auth0 from "auth0-js";
66+
67+
export default class Auth {
68+
auth0 = new auth0.WebAuth({
69+
domain: "YOUR AUTH0 DOMAIN",
70+
clientID: "YOUR AUTH0 CLIENT ID",
71+
redirectUri: "http://localhost:3000/callback",
72+
responseType: "token id_token",
73+
scope: "openid"
74+
});
75+
76+
login() {
77+
this.auth0.authorize();
78+
}
79+
}
80+
```
81+
82+
#### Checkpoint
83+
84+
Try to import the `Auth` service from somewhere in your application. Call the `login` method from the service to see the login page.
85+
For example:
86+
87+
```js
88+
// App.js
89+
import Auth from "./Auth/Auth.js";
90+
91+
const auth = new Auth();
92+
auth.login();
93+
```
94+
95+
## Handle Authentication Tokens
96+
97+
Add more methods to the `Auth` service to handle authentication in the app.
98+
99+
The example below shows the following methods:
100+
101+
- `handleAuthentication`: looks for the result of authentication in the URL hash. Then, the result is processed with the `parseHash` method from auth0.js
102+
- `setSession`: sets the user's Access Token, ID Token, and the Access Token's expiry time
103+
- `logout`: removes the user's tokens and expiry time from browser storage
104+
- `isAuthenticated`: checks whether the expiry time for the user's Access Token has passed
105+
106+
```js
107+
// src/Auth/Auth.js
108+
109+
import history from "../history";
110+
111+
// ...
112+
export default class Auth {
113+
accessToken;
114+
idToken;
115+
expiresAt;
116+
117+
// ...
118+
119+
constructor() {
120+
this.login = this.login.bind(this);
121+
this.logout = this.logout.bind(this);
122+
this.handleAuthentication = this.handleAuthentication.bind(this);
123+
this.isAuthenticated = this.isAuthenticated.bind(this);
124+
this.getAccessToken = this.getAccessToken.bind(this);
125+
this.getIdToken = this.getIdToken.bind(this);
126+
this.renewSession = this.renewSession.bind(this);
127+
}
128+
129+
handleAuthentication() {
130+
this.auth0.parseHash((err, authResult) => {
131+
if (authResult && authResult.accessToken && authResult.idToken) {
132+
this.setSession(authResult);
133+
} else if (err) {
134+
history.replace("/home");
135+
console.log(err);
136+
alert(`Error: ${err.error}. Check the console for further details.`);
137+
}
138+
});
139+
}
140+
141+
getAccessToken() {
142+
return this.accessToken;
143+
}
144+
145+
getIdToken() {
146+
return this.idToken;
147+
}
148+
149+
setSession(authResult) {
150+
// Set isLoggedIn flag in localStorage
151+
localStorage.setItem("isLoggedIn", "true");
152+
153+
// Set the time that the Access Token will expire at
154+
let expiresAt = authResult.expiresIn * 1000 + new Date().getTime();
155+
this.accessToken = authResult.accessToken;
156+
this.idToken = authResult.idToken;
157+
this.expiresAt = expiresAt;
158+
159+
// navigate to the home route
160+
history.replace("/home");
161+
}
162+
163+
renewSession() {
164+
this.auth0.checkSession({}, (err, authResult) => {
165+
if (authResult && authResult.accessToken && authResult.idToken) {
166+
this.setSession(authResult);
167+
} else if (err) {
168+
this.logout();
169+
console.log(err);
170+
alert(
171+
`Could not get a new token (${err.error}: ${err.error_description}).`
172+
);
173+
}
174+
});
175+
}
176+
177+
logout() {
178+
// Remove tokens and expiry time
179+
this.accessToken = null;
180+
this.idToken = null;
181+
this.expiresAt = 0;
182+
183+
// Remove isLoggedIn flag from localStorage
184+
localStorage.removeItem("isLoggedIn");
185+
186+
this.auth0.logout({
187+
returnTo: window.location.origin
188+
});
189+
190+
// navigate to the home route
191+
history.replace("/home");
192+
}
193+
194+
isAuthenticated() {
195+
// Check whether the current time is past the
196+
// access token's expiry time
197+
let expiresAt = this.expiresAt;
198+
return new Date().getTime() < expiresAt;
199+
}
200+
}
201+
```
202+
203+
```js
204+
// src/history.js
205+
206+
import createHistory from "history/createBrowserHistory";
207+
208+
export default createHistory();
209+
```
210+
211+
### Provide a Login Control
212+
213+
Provide a component with controls for the user to log in and log out.
214+
215+
```js
216+
// src/App.js
217+
218+
import React, { Component } from "react";
219+
import { Navbar, Button } from "react-bootstrap";
220+
import "./App.css";
221+
222+
class App extends Component {
223+
goTo(route) {
224+
this.props.history.replace(`/${route}`);
225+
}
226+
227+
login() {
228+
this.props.auth.login();
229+
}
230+
231+
logout() {
232+
this.props.auth.logout();
233+
}
234+
235+
componentDidMount() {
236+
const { renewSession } = this.props.auth;
237+
238+
if (localStorage.getItem("isLoggedIn") === "true") {
239+
renewSession();
240+
}
241+
}
242+
243+
render() {
244+
const { isAuthenticated } = this.props.auth;
245+
246+
return (
247+
<div>
248+
<Navbar fluid>
249+
<Navbar.Header>
250+
<Navbar.Brand>
251+
<a href="#">Auth0 - React</a>
252+
</Navbar.Brand>
253+
<Button
254+
bsStyle="primary"
255+
className="btn-margin"
256+
onClick={this.goTo.bind(this, "home")}
257+
>
258+
Home
259+
</Button>
260+
{!isAuthenticated() && (
261+
<Button
262+
bsStyle="primary"
263+
className="btn-margin"
264+
onClick={this.login.bind(this)}
265+
>
266+
Log In
267+
</Button>
268+
)}
269+
{isAuthenticated() && (
270+
<Button
271+
bsStyle="primary"
272+
className="btn-margin"
273+
onClick={this.logout.bind(this)}
274+
>
275+
Log Out
276+
</Button>
277+
)}
278+
</Navbar.Header>
279+
</Navbar>
280+
</div>
281+
);
282+
}
283+
}
284+
285+
export default App;
286+
```
287+
288+
> **Note:** This example uses Bootstrap styles. You can use any style library you want, or not use one at all.
289+
290+
Depending on whether the user is authenticated or not, they see the **Log In** or **Log Out** button. The `click` events on the buttons make calls to the `Auth` service to let the user log out or log in. When the user clicks the **Log In** button, they are redirected to the login page.
291+
292+
> **Note:** The login page uses the Lock widget. To learn more about Universal Login and the login page, see the [Universal Login documentation](/hosted-pages/login). To customize the look and feel of the Lock widget, see the [Lock customization options documentation](/libraries/lock/v10/customization).
293+
294+
### Add a Callback Component
295+
296+
When you use the login page, your users are taken away from your application. After they authenticate, the users automatically return to your application and a client-side session is set for them.
297+
298+
> **Note:** This example assumes you are using path-based routing with `<BrowserRouter>`. If you are using hash-based routing, you will not be able to specify a dedicated callback route. The URL hash will be used to hold the user's authentication information.
299+
300+
You can select any URL in your application for your users to return to. We recommend creating a dedicated callback route.
301+
If you create a single callback route:
302+
303+
- You don't have to whitelist many, sometimes unknown, callback URLs.
304+
- You can display a loading indicator while the application sets up a client-side session.
305+
306+
Create a component named `CallbackComponent` and add a loading indicator.
307+
308+
> **Note:** To display a loading indicator, you need a loading spinner or another indicator in the `assets` directory. See the downloadable sample for demonstration.
309+
310+
```js
311+
// src/Callback/Callback.js
312+
313+
import React, { Component } from 'react';
314+
import loading from './loading.svg';
315+
316+
class Callback extends Component {
317+
render() {
318+
const style = //...
319+
320+
return (
321+
<div style={style}>
322+
<img src={loading} alt="loading"/>
323+
</div>
324+
);
325+
}
326+
}
327+
328+
export default Callback;
329+
```
330+
331+
After authentication, your users are taken to the `/callback` route. They see the loading indicator while the application sets up a client-side session for them. After the session is set up, the users are redirected to the `/home` route.
332+
333+
### Process the Authentication Result
334+
335+
When a user authenticates at the login page, they are redirected to your application. Their URL contains a hash fragment with their authentication information. The `handleAuthentication` method in the `Auth` service processes the hash.
336+
337+
Call the `handleAuthentication` method after you render the `Callback` route. The method processes the authentication hash fragment when the `Callback` component initializes.
338+
339+
```js
340+
// src/routes.js
341+
342+
import React from "react";
343+
import { Route, Router } from "react-router-dom";
344+
import App from "./App";
345+
import Home from "./Home/Home";
346+
import Callback from "./Callback/Callback";
347+
import Auth from "./Auth/Auth";
348+
import history from "./history";
349+
350+
const auth = new Auth();
351+
352+
const handleAuthentication = (nextState, replace) => {
353+
if (/access_token|id_token|error/.test(nextState.location.hash)) {
354+
auth.handleAuthentication();
355+
}
356+
};
357+
358+
export const makeMainRoutes = () => {
359+
return (
360+
<Router history={history} component={App}>
361+
<div>
362+
<Route path="/" render={props => <App auth={auth} {...props} />} />
363+
<Route path="/home" render={props => <Home auth={auth} {...props} />} />
364+
<Route
365+
path="/callback"
366+
render={props => {
367+
handleAuthentication(props);
368+
return <Callback {...props} />;
369+
}}
370+
/>
371+
</div>
372+
</Router>
373+
);
374+
};
375+
```
376+
45377
## What is Auth0?
46378

47379
Auth0 helps you to:
48380

49-
* Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, among others**, or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**.
50-
* Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**.
51-
* Add support for **[linking different user accounts](https://docs.auth0.com/link-accounts)** with the same user.
52-
* Support for generating signed [Json Web Tokens](https://docs.auth0.com/jwt) to call your APIs and **flow the user identity** securely.
53-
* Analytics of how, when and where users are logging in.
54-
* Pull data from other sources and add it to the user profile, through [JavaScript rules](https://docs.auth0.com/rules).
381+
- Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, among others**, or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**.
382+
- Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**.
383+
- Add support for **[linking different user accounts](https://docs.auth0.com/link-accounts)** with the same user.
384+
- Support for generating signed [Json Web Tokens](https://docs.auth0.com/jwt) to call your APIs and **flow the user identity** securely.
385+
- Analytics of how, when and where users are logging in.
386+
- Pull data from other sources and add it to the user profile, through [JavaScript rules](https://docs.auth0.com/rules).
55387

56388
## Create a Free Auth0 Account
57389

0 commit comments

Comments
 (0)