Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

Commit bd76b40

Browse files
committed
Pull userId from token, fix auth middleware
1 parent 651ee98 commit bd76b40

File tree

5 files changed

+76
-23
lines changed

5 files changed

+76
-23
lines changed

src/middleware/api.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { normalize, Schema } from 'normalizr'
22
import Schemas from './schemas'
33
import axios from 'axios'
44
import decode from 'jwt-decode'
5-
import checkAuth from './check-auth'
65

76
const trim = (token) => token.substring(1, token.length - 1)
87

@@ -72,8 +71,7 @@ export default store => next => action => {
7271
const [ requestType, successType, failureType ] = types
7372
next(actionWith({ type: requestType }))
7473

75-
checkAuth()
76-
.then( () => callApi(callAPI) )
74+
return callApi(callAPI)
7775
.then( response => {
7876
const successAction = actionWith({ response, type: successType })
7977
next(successAction)

src/middleware/check-auth.js

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,68 @@
11
import decode from 'jwt-decode'
22
import fetch from 'isomorphic-fetch'
33
import axios from 'axios'
4+
import { CALL_API } from '../middleware/api'
45

56
const trim = (token) => token.substring(1, token.length - 1)
67
const expiresIn = (token) => Math.round(decode(token).exp - Date.now() / 1000)
78

9+
const API_URL = process.env.API_URL || 'https://api.topcoder.com'
10+
const AUTH0_TOKEN_NAME = process.env.AUTH0_TOKEN_NAME || 'userJWTToken'
11+
12+
// Bind our token refreshes to the same promise chain
813
let refreshPromise = null
914

10-
export default function() {
15+
export default store => next => action => {
16+
17+
// Continue if there is no API call associated
18+
if (typeof action[CALL_API] === 'undefined') {
19+
return next(action)
20+
}
21+
1122
const token = trim(localStorage.userJWTToken)
1223
const expires = expiresIn(token)
1324
const fresh = expires > 60
1425

15-
console.log(token)
16-
26+
// Continue if the token is fresh
1727
if (fresh) {
18-
return Promise.resolve(null)
28+
return next(action)
1929
}
2030

21-
console.log(`Token will expire in ${ expires } seconds. Getting a new one.`)
22-
31+
// If we are already refreshing the token for other actions, append this
32+
// request to the chain
2333
if (refreshPromise) {
24-
return refreshPromise
34+
return refreshPromise = refreshPromise.then( () => next(action) )
2535
}
2636

27-
const API_URL = process.env.API_URL || 'https://api.topcoder.com'
28-
const url = API_URL + '/v3/authorizations/1'
37+
// Configure our fresh request
2938
const config = {
39+
url: API_URL + '/v3/authorizations/1',
3040
headers: {
3141
'Authorization': 'Bearer ' + token
3242
}
3343
}
3444

35-
return refreshPromise = axios.get(url)
36-
.then( res => res.json() )
37-
.then( json => {
38-
if (json.result.status === 200) {
39-
console.log(json.result.content.token)
45+
refreshPromise = axios(config)
46+
.then( res => {
47+
if (res.status === 200) {
48+
// Get token from response
49+
const newToken = '"' + res.data.result.content.token + '"'
50+
51+
// Assign it to local storage
52+
localStorage.setItem(AUTH0_TOKEN_NAME, newToken)
4053

41-
localStorage.setItem('userJWTToken', '"' + json.result.content.token + '"')
54+
// Clear our promise chain
4255
refreshPromise = null
43-
console.log(`Token refreshed. Completing blocked API requests`)
56+
57+
// Continue with our action
4458
next(action)
59+
} else {
60+
throw 'Token refresh failed'
4561
}
4662
})
4763
.catch( (err) => {
4864
refreshPromise = null
4965
})
66+
67+
return refreshPromise
5068
}

src/middleware/check-user.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import decode from 'jwt-decode'
2+
3+
const trim = (token) => token.substring(1, token.length - 1)
4+
5+
export const SET_USER = 'SET_USER'
6+
7+
export default store => next => action => {
8+
if (action.type == SET_USER) {
9+
return next(action)
10+
}
11+
12+
const token = trim(localStorage.userJWTToken)
13+
const tokenUserId = decode(token).userId
14+
const storeUserId = store.getState().user.id
15+
16+
if (!tokenUserId && !storeUserId) {
17+
return null
18+
}
19+
20+
if (!storeUserId) {
21+
next({
22+
type: SET_USER,
23+
user: {
24+
id: tokenUserId
25+
}
26+
})
27+
}
28+
29+
return next(action)
30+
}

src/reducers/index.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
import * as ActionTypes from '../actions'
22
import merge from 'lodash/object/merge'
3-
import {reducer as formReducer} from 'redux-form'
3+
import { reducer as formReducer } from 'redux-form'
44
import { combineReducers } from 'redux'
5+
import { SET_USER } from '../middleware/check-user'
56

67
const defaultState = {
78
profiles: {}
89
}
910

10-
function user(state, action) {
11-
return state || {}
11+
function user(state = {}, action) {
12+
if (action.type == SET_USER) {
13+
state = action.user
14+
}
15+
16+
return state
1217
}
1318

1419
// Updates an entity cache in response to any action with response.entities.

src/store/configureStore.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { createStore, applyMiddleware, compose } from 'redux'
22
import thunk from 'redux-thunk'
3+
import checkUser from '../middleware/check-user'
4+
import checkAuth from '../middleware/check-auth'
35
import api from '../middleware/api'
46
import createLogger from 'redux-logger'
57
import rootReducer from '../reducers'
68

79
const finalCreateStore = compose(
8-
applyMiddleware(thunk, api),
10+
applyMiddleware(thunk, checkUser, checkAuth, api),
911
applyMiddleware(createLogger()),
1012
window.devToolsExtension ? window.devToolsExtension() : f => f
1113
)(createStore)

0 commit comments

Comments
 (0)