Answer the question
In order to leave comments, you need to log in
How to implement user authorization on React Redux Node stack?
I can’t understand how to correctly implement authorization, namely, I don’t understand the very scheme of such authorization. Share your experience thanks in advance!
Answer the question
In order to leave comments, you need to log in
jwt will come in handy. ( google )
In general terms: you need to give the user a token. With this token, the user will make requests to your protected api methods (you can leave some methods "without a token").
Login route example (not done in the best way, in terms of callbacks, but what was at hand...):
...
const v4 = require('node-uuid').v4
const jwt = require('jsonwebtoken')
...
router.post('/signin', (req, res, next) => {
// валидация, например...
if (errors) {
return res.status(400).json({ errors })
} else {
// поиск юзера в базе, сравнение хэша и прочие необходимые операции
...
// допустим все ок, нужно ответить токеном
// генерируем необходимые опции и сам токен
const payload = {
_id: user._id,
iss: 'http://localhost:3000',
permissions: 'poll',
}
const options = {
expiresIn: '7d',
jwtid: v4(),
}
const secret = new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64')
jwt.sign(payload, secret, options, (err, token) => {
// отвечаем токеном, для будущих запросов с клиента
return res.json({ data: token })
})
...
})
module.exports = router;
...
const jwt = require('jsonwebtoken')
const Poll = require('../models/poll')
...
const requireToken = (req,res,next) => {
const token = req.headers['x-api-key']
const secret = new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64')
jwt.verify(token, secret, (err, decoded) => {
if (err) {
return res.status(401).json({ error: err.message })
}
req.params.userId = decoded._id
next()
})
}
...
// обратите внимание на requireToken - функция вызывается при каждом обращении к роуту
// то есть при каждом PUT запросе по адресу (например: PUT api/v1/products/1238914)
// будет вызываться requireToken
router.put('/:id', requireToken, (req, res, next) => {
const { productId } = req.body
const userId = req.params.userId
Poll.findById(req.params.id)
.populate({ path: 'products' })
.exec((err, poll) => {
// ... необходимые действия в базе, в процессе успешного зачтения голоса...
}
})
export function login(data) {
return dispatch => {
dispatch({ type: LOGIN_REQUEST })
// request в данном случае - https://github.com/KyleAMathews/superagent-bluebird-promise
return request.post(`${API_ROOT_V1}/auth/signin`)
.send(data)
.then(res => {
if (!res.ok) {
dispatch({ type: LOGIN_FAILURE })
} else {
dispatch({
type: LOGIN_SUCCESS,
data: res.body.data,
})
//сохранение токена в localStorage
localStorage.setItem('cks_token', res.body.data)
}
}, err => {
dispatch({ type: LOGIN_FAILURE })
})
}
}
export function vote(productId, voteId) {
return dispatch => {
dispatch({ type: POLL_VOTE_REQUEST })
return request.put(`${API_ROOT_V1}/api/v1/vote/${voteId}`)
.set('X-API-Key', localStorage.getItem('cks_token')) // установка ТОКЕНА в заголовок 'X-API-Key'
.send({ productId })
.then(res => {
if (!res.ok) {
dispatch({ type: POLL_VOTE_FAILURE })
} else {
dispatch({
type: POLL_VOTE_SUCCESS,
data: normalize(res.body.data, schema.poll),
})
}
}, err => {
dispatch({ type: POLL_VOTE_FAILURE })
})
}
}
import fetch from 'isomorphic-fetch'
...
const defaultHeaders = {
Accept: 'application/json',
'Content-Type': 'application/json',
}
function buildHeaders() {
const authToken = localStorage.getItem('TOKEN')
return { ...defaultHeaders, Authorization: authToken }
}
...
export function httpPost(url, data) {
const body = JSON.stringify(data)
return fetch(url, {
method: 'post',
headers: buildHeaders(),
body: body,
})
.then(... код оработки запроса ...)
}
...
<Provider store={store}>
<Router history={routerHistory}>
{configRoutes(store)} // Роуты создаются функцией, чтобы можно было использовать внутри нее store.getState()
</Router>
</Provider>
...
export default function configRoutes(store) {
function _ensureAuthenticated(nextState, replace, callback) {
const { dispatch } = store
const { session } = store.getState()
const { currentUser } = session
let nextUrl
if (!currentUser && localStorage.getItem('cks.token')) {
dispatch(getCurrentAccount())
} else if (!localStorage.getItem('cks.token')) {
replace('/signin')
}
callback()
}
return (
<Route path='/' component={App}>
<Route path='/signin' component={SigninContainer} />
<Route path='/signup' component={SignupContainer} />
<Route path='/locked' component={AuthenticatedContainer} onEnter={_ensureAuthenticated}>
<Route component={LockedArea}>
<Route path='/locked/a' component={A} />
<Route path='/locked/b/:id' component={B} />
<Route path='/locked/c' component={C} />
</Route>
</Route>
</Route>
)
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question