ducky/web
2015-07-07
Parent:9b97c908a706
ducky/web/src/helpers/oauth-refresh.js
Remove local-storage wrapper, minor updates to Me model. No longer use our local-storage helper (remove it entirely), as we're no longer going to be a Chrome app. So let's just always rely on localStorage. Update our Me URL to use the nginx-fronted URL. Add an email property to our Me model, to keep track of the email we logged in with. This is mostly used for setting up our subscription, and should be deprecated in the future.
| 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@18 | 9 url: config.urlBase + '/auth/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@18 | 98 if(opts.noRefresh || !shouldRefreshSync(resp)) { |
| 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 |