forked from cujojs/rest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoAuth.js
147 lines (125 loc) · 4.72 KB
/
oAuth.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
* Copyright 2012-2013 the original author or authors
* @license MIT, see LICENSE.txt for details
*
* @author Scott Andrews
*/
(function (define, global) {
'use strict';
define(function (require) {
var interceptor, UrlBuilder, pubsub, when;
interceptor = require('../interceptor');
UrlBuilder = require('../UrlBuilder');
pubsub = require('../util/pubsub');
when = require('when');
function defaultOAuthCallback(hash) {
var params, queryString, regex, m;
queryString = hash.indexOf('#') === 0 ? hash.substring(1) : hash;
params = {};
regex = /([^&=]+)=([^&]*)/g;
m = regex.exec(queryString);
do {
params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
m = regex.exec(queryString);
} while (m);
/*jshint camelcase:false */
pubsub.publish(params.state, params.token_type + ' ' + params.access_token);
}
function defaultWindowStrategy(url) {
var w = window.open(url, '_blank', 'width=500,height=400');
return function () {
w.close();
};
}
function authorize(config) {
var state, url, dismissWindow;
return when.promise(function (resolve) {
state = Math.random() * new Date().getTime();
url = new UrlBuilder(config.authorizationUrlBase).build({
'response_type': 'token',
'redirect_uri': config.redirectUrl,
'client_id': config.clientId,
'scope': config.scope,
'state': state
});
dismissWindow = config.windowStrategy(url);
pubsub.subscribe(state, function (authorization) {
dismissWindow();
resolve(authorization);
});
});
}
/**
* OAuth implicit flow support
*
* Authorizes request with the OAuth authorization token. Tokens are
* requested from the authorization server as needed if there isn't a
* token, or the token is expired.
*
* A custom window strategy can be provided to replace the default popup
* window. The window strategy is a function that must accept a URL as an
* argument and returns a function to close and cleanup the window. A
* common custom strategy would be to use an iframe in a dialog.
*
* The callback function must be invoked when the authorization server
* redirects the browser back to the application.
*
* NOTE: Registering a handler to receive the redirect is required and
* outside the scope of this interceptor. The implementer must collect the
* URL fragment and pass it to the callback function on the 'opener', or
* 'parent' window.
*
* @param {Client} [target] client to wrap
* @param {string} [config.token] pre-configured authentication token
* @param {string} config.clientId OAuth clientId
* @param {string} config.scope OAuth scope
* @param {string} config.authorizationUrlBase URL of the authorization server
* @param {string} [config.redirectUrl] callback URL from the authorization server. Will be converted to a fully qualified, absolute URL, if needed. Default's to the window's location or base href.
* @param {Function} [config.windowStrategy] strategy for opening the authorization window, defaults to window.open
* @param {string} [config.oAuthCallbackName='oAuthCallback'] name to register the callback as in global scope
* @param {Function} [config.oAuthCallback] callback function to receive OAuth URL fragment
*
* @returns {Client}
*/
return interceptor({
init: function (config) {
config.redirectUrl = new UrlBuilder(config.redirectUrl).fullyQualify().build();
config.windowStrategy = config.windowStrategy || defaultWindowStrategy;
config.oAuthCallback = config.oAuthCallback || defaultOAuthCallback;
config.oAuthCallbackName = config.oAuthCallbackName || 'oAuthCallback';
global[config.oAuthCallbackName] = config.oAuthCallback;
return config;
},
request: function (request, config) {
request.headers = request.headers || {};
if (config.token) {
request.headers.Authorization = config.token;
return request;
}
else {
return authorize(config).then(function (authorization) {
request.headers.Authorization = config.token = authorization;
return request;
});
}
},
response: function (response, config, client) {
if (response.status.code === 401) {
// token probably expired, reauthorize
return authorize(config).then(function (authorization) {
config.token = authorization;
return client(response.request);
});
}
else if (response.status.code === 403) {
return when.reject(response);
}
return response;
}
});
});
}(
typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); },
typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : void 0
// Boilerplate for AMD and Node
));