ducky/web

Paddy 2015-06-30 Parent:3bdc03963abe Child:9b97c908a706

12:791aec3eb17b Go to Latest

ducky/web/src/helpers/oauth-refresh.js

Update our profile model to use our refresh helper. Update our profile model to send the correct authorization header when making requests, and if the request fails because the OAuth token has expired, try to use the refresh token to obtain a new access token, then retry the request.

History
paddy@11 1 import app from 'ampersand-app'
paddy@11 2 import xhr from 'xhr'
paddy@11 3 import qs from 'qs'
paddy@11 4 import Sync from 'ampersand-sync'
paddy@11 5 import config from '../config'
paddy@11 6
paddy@11 7 const getRefresh = (opts, callback) => {
paddy@11 8 const refreshOpts = {
paddy@11 9 url: config.urlBase + '/token',
paddy@11 10 method: 'POST',
paddy@11 11 headers: {
paddy@11 12 'Content-Type': 'application/x-www-form-urlencoded',
paddy@11 13 'Authorization': 'Basic ' + btoa(config.clientID + ':' + config.clientSecret),
paddy@11 14 },
paddy@11 15 data: qs.stringify({
paddy@11 16 'grant_type': 'refresh_token',
paddy@11 17 'refresh_token': app.me.refresh_token
paddy@11 18 }),
paddy@11 19 }
paddy@11 20 xhr(refreshOpts, function(err, resp, body) {
paddy@11 21 if (resp.statusCode != 200) {
paddy@11 22 callback(err, resp, body)
paddy@11 23 return
paddy@11 24 }
paddy@11 25 if (body && resp.headers['content-type'] == 'application/json') {
paddy@11 26 try {
paddy@11 27 body = JSON.parse(body)
paddy@11 28 } catch (err) {
paddy@11 29 app.trigger('token:refreshError', body)
paddy@11 30 callback(err, resp, body)
paddy@11 31 }
paddy@11 32 }
paddy@11 33 if (body.access_token) {
paddy@11 34 app.me.set(body)
paddy@11 35 } else {
paddy@11 36 app.trigger('token:refreshError', body)
paddy@11 37 }
paddy@11 38 callback(err, resp, body)
paddy@11 39 })
paddy@11 40 }
paddy@11 41
paddy@11 42 const shouldRefreshXHR = (err, resp, body) => {
paddy@11 43 if(body && resp.headers['Content-Type'] == 'application/json') {
paddy@11 44 try {
paddy@11 45 body = JSON.parse(body)
paddy@11 46 } catch (err) {
paddy@11 47 return false
paddy@11 48 }
paddy@11 49 }
paddy@11 50 if (resp.statusCode == 401 && body.errors && body.errors[0]
paddy@11 51 && body.errors[0].header == 'authorization' && body.errors[0].error == 'access_denied') {
paddy@11 52 return true
paddy@11 53 }
paddy@11 54 return false
paddy@11 55 }
paddy@11 56
paddy@11 57 const doRefreshXHR = (opts, callback) => {
paddy@11 58 opts.noRefresh = true
paddy@11 59 getRefresh(opts, function(err, resp, body) {
paddy@11 60 if (body.access_token) {
paddy@11 61 opts.headers['Authorization'] = 'Bearer '+body.access_token
paddy@11 62 xhr(opts, callback)
paddy@11 63 }
paddy@11 64 })
paddy@11 65 }
paddy@11 66
paddy@11 67 const refreshXHR = (opts, callback) => {
paddy@11 68 return xhr(opts, function(err, resp, body) {
paddy@11 69 if (opts.noRefresh || !shouldRefreshXHR(err, resp, body)) {
paddy@11 70 callback(err, resp, body)
paddy@11 71 return
paddy@11 72 }
paddy@11 73 doRefreshXHR(opts, callback)
paddy@11 74 })
paddy@11 75 xhr(opts, callback)
paddy@11 76 }
paddy@11 77
paddy@11 78 const shouldRefreshSync = (resp) => {
paddy@11 79 if (resp && resp.errors && resp.errors[0]
paddy@11 80 && resp.errors[0].header == 'authorization' && resp.errors[0].error == 'access_denied') {
paddy@11 81 return true
paddy@11 82 }
paddy@11 83 return false
paddy@11 84 }
paddy@11 85
paddy@11 86 const doRefreshSync = (action, moc, opts) => {
paddy@11 87 opts.noRefresh = true
paddy@11 88 getRefresh(opts, function(err, resp, body) {
paddy@11 89 if (body.access_token) {
paddy@11 90 Sync(action, moc, opts)
paddy@11 91 }
paddy@11 92 })
paddy@11 93 }
paddy@11 94
paddy@11 95 const refreshSync = (action, moc, opts) => {
paddy@11 96 const oldError = opts.error
paddy@11 97 opts.error = function(resp) {
paddy@11 98 if(opts.noRefresh || !shouldRefreshSync) {
paddy@11 99 oldError(resp)
paddy@11 100 return
paddy@11 101 }
paddy@11 102 doRefreshSync(action, moc, opts)
paddy@11 103 }
paddy@11 104 Sync(action, moc, opts)
paddy@11 105 }
paddy@11 106
paddy@11 107 const refresh = {
paddy@11 108 Sync: refreshSync,
paddy@11 109 XHR: refreshXHR,
paddy@11 110 }
paddy@11 111
paddy@11 112 export default refresh