From 691a75eefb06a4a940de36f34ac89294b819de57 Mon Sep 17 00:00:00 2001 From: Eliot Berriot <contact@eliotberriot.com> Date: Sat, 8 Jun 2019 07:23:44 +0200 Subject: [PATCH] Fixed oauth refresh issue on Funkwhale --- package.json | 1 + src/sources/funkwhale.js | 64 ++++++++++++++++++++++++++++++++++------ yarn.lock | 15 ++++++++++ 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 38b42a9..5074829 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "axios": "^0.19.0", + "axios-auth-refresh": "^1.0.7", "core-js": "^2.6.5", "lodash": "^4.17.11", "material-icons": "^0.3.1", diff --git a/src/sources/funkwhale.js b/src/sources/funkwhale.js index dd65091..18ce13c 100644 --- a/src/sources/funkwhale.js +++ b/src/sources/funkwhale.js @@ -1,8 +1,8 @@ import axios from 'axios' +import createAuthRefreshInterceptor from 'axios-auth-refresh'; import moment from 'moment' import Form from '../components/FunkwhaleForm.vue' import get from 'lodash/get' - import {getAbsoluteUrl} from "@/utils" export const SCOPES = "read:profile read:listenings" @@ -37,6 +37,51 @@ export async function createApp(ax, {baseUrl}) { return response } +function getAuthorizationHeader (account, state) { + const token = state.sources.funkwhale.appTokens[`${account.username}@${account.domain}`].access_token + return `Bearer ${token}` + +} + +export function getOauthAxios ({axiosParams, account, store}) { + // an axios instance with autorefreshing for oauth tokens + let client = axios.create(axiosParams || {}) + client.interceptors.request.use(request => { + request.headers['Authorization'] = getAuthorizationHeader(account, store.state) + return request + }) + createAuthRefreshInterceptor(client, (failedRequest) => { + console.log('Request failed, OAuth token probably expired, fetching a new oneā¦') + const refreshToken = store.state.sources.funkwhale.appTokens[`${account.username}@${account.domain}`].refresh_token + const app = store.state.sources.funkwhale.appCredentials[account.domain] + const payload = { + client_id: app.client_id, + client_secret: app.client_secret, + grant_type: "refresh_token", + refresh_token: refreshToken, + } + return client.post( + `/api/v1/oauth/token/`, + asForm(payload), + {headers: {'Content-Type': 'multipart/form-data'}} + ).then((tokenRefreshResponse) => { + store.commit('setRecursiveState', {key: "sources.funkwhale.appTokens", suffix: `${account.username}@${account.domain}`, value: tokenRefreshResponse.data}) + let newHeader = getAuthorizationHeader(account, store.state) + failedRequest.response.config.headers['Authorization'] = newHeader + return Promise.resolve() + }) + }) + return client +} + +function asForm (obj) { + let data = new FormData() + Object.entries(obj).forEach((e) => { + data.set(e[0], e[1]) + }) + return data +} + export default { id: "funkwhale", @@ -76,11 +121,11 @@ export default { code: query.code, redirect_uri: `${baseUrl}/connect/funkwhale/callback` } - let data = new FormData() - Object.entries(payload).forEach((e) => { - data.set(e[0], e[1]) - }) - const response = await ax.post(`https://${domain}/api/v1/oauth/token/`, data, {headers: {'Content-Type': 'multipart/form-data'}}) + const response = await ax.post( + `https://${domain}/api/v1/oauth/token/`, + asForm(payload), + {headers: {'Content-Type': 'multipart/form-data'}} + ) const token = response.data.access_token const client = axios.create({ baseURL: `https://${domain}`, @@ -95,9 +140,10 @@ export default { async fetch ({account, store, results, maxDays}) { results.status = `Fetching listenings...` const token = store.state.sources.funkwhale.appTokens[`${account.username}@${account.domain}`].access_token - const client = axios.create({ - baseURL: `https://${account.domain}`, - headers: {'Authorization': `Bearer ${token}`}, + const client = getOauthAxios({ + axiosParams: {baseURL: `https://${account.domain}`}, + store: store, + account: account }) const dateLimit = moment().subtract(maxDays, 'days') let url = null diff --git a/yarn.lock b/yarn.lock index 27445b2..4900c74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1491,6 +1491,21 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== +axios-auth-refresh@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/axios-auth-refresh/-/axios-auth-refresh-1.0.7.tgz#b9f39131ef39190c753d386746e9aa6e7114212b" + integrity sha512-TQl1tF+MY+iDG93WpiqcnwGb1lvdJLKzi0IN/7hBkYFlpOC6xv4S+cW3QHZOBjKpFWRWqHg9fXd/PDsCvJ3uLA== + dependencies: + axios "^0.18.0" + +axios@^0.18.0: + version "0.18.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3" + integrity sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g== + dependencies: + follow-redirects "1.5.10" + is-buffer "^2.0.2" + axios@^0.19.0: version "0.19.0" resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8" -- GitLab