Skip to content
Snippets Groups Projects
Commit a8a37603 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Merge branch 'feature/57-token-refresh' into 'develop'

Fixed #57: now refresh jwt token on page refresh

Closes #57

See merge request funkwhale/funkwhale!36
parents 8fa73306 f1557ac4
No related branches found
No related tags found
No related merge requests found
...@@ -46,9 +46,8 @@ v1_patterns += [ ...@@ -46,9 +46,8 @@ v1_patterns += [
include( include(
('funkwhale_api.users.api_urls', 'users'), ('funkwhale_api.users.api_urls', 'users'),
namespace='users')), namespace='users')),
url(r'^token/', url(r'^token/$', jwt_views.obtain_jwt_token, name='token'),
jwt_views.obtain_jwt_token), url(r'^token/refresh/$', jwt_views.refresh_jwt_token, name='token_refresh'),
url(r'^token/refresh/', jwt_views.refresh_jwt_token),
] ]
urlpatterns = [ urlpatterns = [
......
...@@ -62,3 +62,38 @@ def test_can_fetch_data_from_api(client, factories): ...@@ -62,3 +62,38 @@ def test_can_fetch_data_from_api(client, factories):
assert payload['name'] == user.name assert payload['name'] == user.name
assert payload['permissions']['import.launch']['status'] assert payload['permissions']['import.launch']['status']
assert payload['permissions']['settings.change']['status'] assert payload['permissions']['settings.change']['status']
def test_can_get_token_via_api(client, factories):
user = factories['users.User']()
url = reverse('api:v1:token')
payload = {
'username': user.username,
'password': 'test'
}
response = client.post(url, payload)
assert response.status_code == 200
assert '"token":' in response.content.decode('utf-8')
def test_can_refresh_token_via_api(client, factories):
# first, we get a token
user = factories['users.User']()
url = reverse('api:v1:token')
payload = {
'username': user.username,
'password': 'test'
}
response = client.post(url, payload)
assert response.status_code == 200
token = json.loads(response.content.decode('utf-8'))['token']
url = reverse('api:v1:token_refresh')
response = client.post(url,{'token': token})
assert response.status_code == 200
assert '"token":' in response.content.decode('utf-8')
# a different token should be returned
assert token in response.content.decode('utf-8')
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
"dependencies": { "dependencies": {
"dateformat": "^2.0.0", "dateformat": "^2.0.0",
"js-logger": "^1.3.0", "js-logger": "^1.3.0",
"jwt-decode": "^2.2.0",
"lodash": "^4.17.4", "lodash": "^4.17.4",
"semantic-ui-css": "^2.2.10", "semantic-ui-css": "^2.2.10",
"vue": "^2.3.3", "vue": "^2.3.3",
......
import Vue from 'vue' import Vue from 'vue'
import jwtDecode from 'jwt-decode'
import config from '@/config' import config from '@/config'
import logger from '@/logging' import logger from '@/logging'
import router from '@/router' import router from '@/router'
const LOGIN_URL = config.API_URL + 'token/' const LOGIN_URL = config.API_URL + 'token/'
const REFRESH_TOKEN_URL = config.API_URL + 'token/refresh/'
const USER_PROFILE_URL = config.API_URL + 'users/users/me/' const USER_PROFILE_URL = config.API_URL + 'users/users/me/'
export default { export default {
...@@ -13,7 +15,8 @@ export default { ...@@ -13,7 +15,8 @@ export default {
username: '', username: '',
availablePermissions: {}, availablePermissions: {},
profile: null, profile: null,
token: '' token: '',
tokenData: {}
}, },
getters: { getters: {
header: state => { header: state => {
...@@ -32,6 +35,7 @@ export default { ...@@ -32,6 +35,7 @@ export default {
}, },
token: (state, value) => { token: (state, value) => {
state.token = value state.token = value
state.tokenData = jwtDecode(value)
}, },
permission: (state, {key, status}) => { permission: (state, {key, status}) => {
state.availablePermissions[key] = status state.availablePermissions[key] = status
...@@ -70,6 +74,7 @@ export default { ...@@ -70,6 +74,7 @@ export default {
commit('token', jwt) commit('token', jwt)
logger.default.info('Logged back in as ' + username) logger.default.info('Logged back in as ' + username)
dispatch('fetchProfile') dispatch('fetchProfile')
dispatch('refreshToken')
} else { } else {
logger.default.info('Anonymous user') logger.default.info('Anonymous user')
commit('authenticated', false) commit('authenticated', false)
...@@ -90,6 +95,15 @@ export default { ...@@ -90,6 +95,15 @@ export default {
}, (response) => { }, (response) => {
logger.default.info('Error while fetching user profile') logger.default.info('Error while fetching user profile')
}) })
},
refreshToken ({commit, dispatch, state}) {
let resource = Vue.resource(REFRESH_TOKEN_URL)
return resource.save({}, {token: state.token}).then(response => {
logger.default.info('Refreshed auth token')
commit('token', response.data.token)
}, response => {
logger.default.error('Error while refreshing token', response.data)
})
} }
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment