|
| 1 | +# Spotify Authorization With React + React-Router |
| 2 | + |
| 3 | +This is an example application demonstrating authenticating a user |
| 4 | +[against the Spotify Web API][sag], using [React][r] and [React-Router][rr] |
| 5 | +and [Redux][rx] and [React-Router-Redux][rrr]. |
| 6 | + |
| 7 | +## Similarities to Spotify's [Web Auth Examples][wae] |
| 8 | + |
| 9 | +This example is a variation on the `authorization_code` demo from Spotify's |
| 10 | +[Web Auth Examples][wae]. The main difference is the client code; whereas their |
| 11 | +example is contained in one `index.html` file, this example shows how to do the |
| 12 | +same thing with React and React-Router. |
| 13 | + |
| 14 | +The other difference is the updated server code. Instead of using `request` |
| 15 | +directly (and XHR in the browser), this example interfaces with Spotify through |
| 16 | +the [Spotify Web API Node Module][swn] (and [Spotify Web Api Client][swj] in the |
| 17 | +browser). It also uses fun ES6 goodness. I opened a [pull request][spr] with |
| 18 | +them to update their server code to what you see here. |
| 19 | + |
| 20 | +## Client Code Structure |
| 21 | + |
| 22 | +The client code is built with [React][r] and [React-Router][rr] and [Redux][rx] |
| 23 | +and [React-Router-Redux][rrr]. phew! |
| 24 | + |
| 25 | +The only real config this requires is in `client/index.js`: |
| 26 | + |
| 27 | +~~~js |
| 28 | +class Root extends Component { |
| 29 | + render() { |
| 30 | + return ( |
| 31 | + <Provider store={store}> |
| 32 | + <Router history={hashHistory}> |
| 33 | + <Route path="/" component={App}> |
| 34 | + <IndexRoute component={Login} /> |
| 35 | + <Route path="/user/:accessToken/:refreshToken" component={User} /> |
| 36 | + <Route path="/error/:errorMsg" component={Error} /> |
| 37 | + </Route> |
| 38 | + </Router> |
| 39 | + </Provider> |
| 40 | + ); |
| 41 | + } |
| 42 | +} |
| 43 | +~~~ |
| 44 | + |
| 45 | +Here, we initialize redux with our store, initialize react router with its |
| 46 | +history object. Everything else is a fairly traditional React app - the |
| 47 | +components are in `client/components`, the actions are in `client/actions`, |
| 48 | +and the reducer is in `client/reducers`. |
| 49 | + |
| 50 | +## Server Code Structure |
| 51 | + |
| 52 | +Under the `server` directory are two files `app.js` and `routes.js`. `app.js` |
| 53 | +handles all the setup, and all the routes are in, well, `routes.js`. |
| 54 | + |
| 55 | +## Application Flow |
| 56 | + |
| 57 | +The basic flow is this: client hits `/login`, gets redirected to Spotify's auth |
| 58 | +url, then gets redirected to `/callback`. If all is good and dandy, we send the |
| 59 | +client to `/#/user/${access_token}/${refresh_token}` which triggers the User |
| 60 | +page to load via React-Router. If all ain't good, we redirect the client to |
| 61 | +`/#/error/${error message}` which triggers the Error page to load via |
| 62 | +React-Router. |
| 63 | + |
| 64 | +Once the client has the tokens, it requests information from spotify directly |
| 65 | +through use of the [Spotify Web API Client][swj]. This happens in |
| 66 | +`client/actions`, and the resulting data is interpreted through our reducer. |
| 67 | +Once the client has the data, `User.js` defines how it renders. |
| 68 | + |
| 69 | +## Set Up |
| 70 | + |
| 71 | +Make sure you create your application, get your id and secret, and register |
| 72 | +your callback url - `localhost:3000/callback` is what I used - by following |
| 73 | +[Spotify's Getting Started Guide][sgs]. |
| 74 | + |
| 75 | +## Running |
| 76 | + |
| 77 | +The first thing you'll need to do is set your applications client id, client |
| 78 | +secret, and callback url. You can do this via the environment variables |
| 79 | +`client_id`, `client_secret`, and `redirect_uri`. Or by typing them into the |
| 80 | +code in `server/routes.js`. Fun tip: because we're using [Better NPM Run][bnr], |
| 81 | +you can set these in your `package.json` - head over there to see an example. |
| 82 | + |
| 83 | +There are three scripts - `start`, `dev`, and `build`. |
| 84 | + |
| 85 | +To run the production bundle: |
| 86 | + |
| 87 | +~~~bash |
| 88 | +$ npm run build |
| 89 | +$ npm start |
| 90 | +~~~ |
| 91 | + |
| 92 | +To run in dev mode (with hot reloading, and un-minified source maps): |
| 93 | + |
| 94 | +~~~bash |
| 95 | +$ npm run dev |
| 96 | +~~~ |
| 97 | + |
| 98 | +## Further Reading |
| 99 | + |
| 100 | +The application structure is a simplified version of my |
| 101 | +[React + Redux + Webpack Boilerplate][bp] for better ease of understanding. |
| 102 | +It can certainly be awesome-ified (and maybe a little more complicated) by |
| 103 | +doing some of the fun tricks in there. |
| 104 | + |
| 105 | + - [Spotify's Getting Started Guide][sgs] |
| 106 | + - [Spotify's Web API Authorization Guide][sag] |
| 107 | + - [Spotify Web API Node][swn] |
| 108 | + - [Spotify Web API JS/Client][swj] |
| 109 | + - [Spotify's Web API Auth Exampls][wae] |
| 110 | + - [My Pull Request enhancing Spotify's examples][spr] |
| 111 | + - [React Router][rr] |
| 112 | + - [React Router Redux][rrr] |
| 113 | + - [React][r] |
| 114 | + - [Redux][rx] |
| 115 | + - [Better NPM Run][bnr] |
| 116 | + - [React + Redux + Webpack Boilerplate][bp] |
| 117 | + |
| 118 | +[sgs]: https://developer.spotify.com/web-api/tutorial/ |
| 119 | +[sag]: https://developer.spotify.com/web-api/authorization-guide/ |
| 120 | +[swn]: https://github.com/JMPerez/spotify-web-api-node |
| 121 | +[swj]: https://github.com/JMPerez/spotify-web-api-js |
| 122 | +[wae]: https://github.com/spotify/web-api-auth-examples |
| 123 | +[spr]: https://github.com/spotify/web-api-auth-examples/pull/7 |
| 124 | +[rr]: https://github.com/rackt/react-router |
| 125 | +[rrr]: https://github.com/rackt/react-router-redux |
| 126 | +[r]: https://facebook.github.io/react/ |
| 127 | +[rx]: http://redux.js.org/ |
| 128 | +[bnr]: https://www.npmjs.com/package/better-npm-run |
| 129 | +[bp]: https://github.com/kauffecup/react-redux-webpack-boilerplate |
0 commit comments