diff --git a/src/index.js b/src/index.js
index 8f8c4da6ab9a9df18085b9f0b332fa93cca42ebf..c7b4cbff8a2a38faf4ac89fd20e68255552fb952 100644
--- a/src/index.js
+++ b/src/index.js
@@ -41,6 +41,10 @@ const fileStorage = {
 
 const { callMicroservice } = require('./utils/microservices')
 
+const {
+  authenticatedCall: makeOAuthCall,
+} = require('./utils/authenticatedCall')
+
 const createJWT = authentication.token.create
 const verifyJWT = authentication.token.verify
 
@@ -70,5 +74,6 @@ module.exports = {
   connectToJobQueue,
 
   callMicroservice,
+  makeOAuthCall,
   WaxToDocxConverter,
 }
diff --git a/src/utils/__tests__/authenticatedCall.test.js b/src/utils/__tests__/authenticatedCall.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..58c2a1fd6a1033565e766348e986390732493670
--- /dev/null
+++ b/src/utils/__tests__/authenticatedCall.test.js
@@ -0,0 +1,16 @@
+const axios = require('axios')
+const { authenticatedCall } = require('../authenticatedCall')
+
+jest.mock('../getAuthTokens.js', () => {
+  return jest.fn(() => 'token')
+})
+
+jest.mock('axios')
+
+describe('Authenticated call', () => {
+  it('calls provider with auth', async () => {
+    axios.mockResolvedValue(true)
+    const res = await authenticatedCall('123', 'lulu', {})
+    expect(res).toBe(true)
+  })
+})
diff --git a/src/utils/authenticatedCall.js b/src/utils/authenticatedCall.js
new file mode 100644
index 0000000000000000000000000000000000000000..10d8ccd41e2cbc3cccb9af0237e3fe9700fc6650
--- /dev/null
+++ b/src/utils/authenticatedCall.js
@@ -0,0 +1,19 @@
+const makeCall = require('./makeCall')
+const getAuthTokens = require('./getAuthTokens')
+
+const authenticatedCall = async (userId, providerLabel, callParameters) => {
+  try {
+    if (!callParameters) throw new Error(`Call parameters are required`)
+
+    const accessToken = await getAuthTokens(userId, providerLabel)
+
+    return makeCall(callParameters, accessToken)
+  } catch (e) {
+    throw new Error(e)
+  }
+}
+
+module.exports = {
+  authenticatedCall,
+  getAuthTokens,
+}
diff --git a/src/utils/getAuthTokens.js b/src/utils/getAuthTokens.js
new file mode 100644
index 0000000000000000000000000000000000000000..626662667c55f018809684dc6826d89cb1f638ad
--- /dev/null
+++ b/src/utils/getAuthTokens.js
@@ -0,0 +1,97 @@
+const config = require('config')
+const axios = require('axios')
+
+const { Identity } = require('../models')
+
+const getAuthTokens = async (userId, providerLabel) => {
+  try {
+    const providerUserIdentity = await Identity.findOne({
+      userId,
+      provider: providerLabel,
+    })
+
+    if (!providerUserIdentity) {
+      throw new Error(`identity for provider ${providerLabel} does not exist`)
+    }
+
+    const {
+      oauthAccessToken,
+      oauthAccessTokenExpiration,
+      oauthRefreshToken,
+      oauthRefreshTokenExpiration,
+    } = providerUserIdentity
+
+    const accessTokenExpired = oauthAccessTokenExpiration < new Date().getTime()
+
+    if (!accessTokenExpired) {
+      return oauthAccessToken
+    }
+
+    const refreshTokenExpired =
+      oauthRefreshTokenExpiration < new Date().getTime()
+
+    if (refreshTokenExpired) {
+      throw new Error(
+        `refresh token for provider ${providerLabel} expired, authorization flow should (provider login) be followed by the user`,
+      )
+    }
+
+    const integrations =
+      config.has('integrations') && config.get('integrations')
+
+    if (!integrations) {
+      throw new Error('Integrations are undefined in config')
+    }
+
+    const externalProvider = integrations[providerLabel]
+
+    if (!externalProvider) {
+      throw new Error(
+        `Integration ${providerLabel} configuration is undefined `,
+      )
+    }
+
+    const { tokenUrl, clientId } = integrations[providerLabel]
+
+    if (!tokenUrl) {
+      throw new Error(`Integration ${providerLabel} tokenUrl is undefined `)
+    }
+
+    if (!clientId) {
+      throw new Error(`Integration ${providerLabel} clientId is undefined `)
+    }
+
+    const tokenData = new URLSearchParams({
+      grant_type: 'refresh_token',
+      refresh_token: oauthRefreshToken,
+      client_id: clientId,
+    })
+
+    const { data } = await axios({
+      method: 'post',
+      url: tokenUrl,
+
+      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+      data: tokenData.toString(),
+    })
+
+    /* eslint-disable camelcase */
+    const { access_token, expires_in, refresh_token, refresh_expires_in } = data
+
+    await Identity.patchAndFetchById(providerUserIdentity.id, {
+      oauthAccessToken: access_token,
+      oauthRefreshToken: refresh_token,
+      oauthAccessTokenExpiration:
+        new Date().getTime() + 1000 * parseInt(expires_in, 10),
+      oauthRefreshTokenExpiration:
+        new Date().getTime() + 1000 * parseInt(refresh_expires_in, 10),
+    })
+
+    return access_token
+    /* eslint-enable camelcase */
+  } catch (e) {
+    throw new Error(e)
+  }
+}
+
+module.exports = getAuthTokens
diff --git a/src/utils/makeCall.js b/src/utils/makeCall.js
new file mode 100644
index 0000000000000000000000000000000000000000..4a8047cb9f676e0612c79c54ec6cb3bc750bbe87
--- /dev/null
+++ b/src/utils/makeCall.js
@@ -0,0 +1,19 @@
+const axios = require('axios')
+const clone = require('lodash/clone')
+
+const makeCall = async (callParameters, token) => {
+  const axiosParams = clone(callParameters)
+  const { headers } = axiosParams
+
+  if (!headers) {
+    axiosParams.headers = {
+      authorization: `Bearer ${token}`,
+    }
+  } else {
+    axiosParams.headers.authorization = `Bearer ${token}`
+  }
+
+  return axios(axiosParams)
+}
+
+module.exports = makeCall
diff --git a/src/utils/microservices.js b/src/utils/microservices.js
index 7fb8ac915b638bad057c548730d502acda095adf..642dc1975a19c36c1f9b9b1d1cfa6515190e3704 100644
--- a/src/utils/microservices.js
+++ b/src/utils/microservices.js
@@ -1,5 +1,4 @@
-const axios = require('axios')
-const clone = require('lodash/clone')
+const makeCall = require('./makeCall')
 
 const getAccessToken = require('./getAccessToken')
 
@@ -32,24 +31,9 @@ const callMicroservice = async (serviceName, callParameters) => {
         `communication parameters needed for calling ${serviceName} microservice`,
       )
 
-    const makeCall = async token => {
-      const axiosParams = clone(callParameters)
-      const { headers } = axiosParams
-
-      if (!headers) {
-        axiosParams.headers = {
-          authorization: `Bearer ${token}`,
-        }
-      } else {
-        axiosParams.headers.authorization = `Bearer ${token}`
-      }
-
-      return axios(axiosParams)
-    }
-
     const accessToken = await getAccessToken(serviceName)
 
-    return makeCall(accessToken).catch(async err => {
+    return makeCall(callParameters, accessToken).catch(async err => {
       const { response } = err
 
       if (!response) {
@@ -61,7 +45,7 @@ const callMicroservice = async (serviceName, callParameters) => {
 
       if (status === 401 && msg === 'expired token') {
         const freshToken = await getAccessToken(serviceName, true)
-        return makeCall(freshToken)
+        return makeCall(callParameters, freshToken)
       }
 
       throw new Error(err)