-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
Copy pathnetlify-auth.js
169 lines (153 loc) · 4.57 KB
/
netlify-auth.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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import trim from 'lodash/trim';
import trimEnd from 'lodash/trim';
const NETLIFY_API = 'https://api.netlify.com';
const AUTH_ENDPOINT = 'auth';
class NetlifyError {
constructor(err) {
this.err = err;
}
toString() {
return this.err && this.err.message;
}
}
const PROVIDERS = {
github: {
width: 960,
height: 600,
},
gitlab: {
width: 960,
height: 600,
},
bitbucket: {
width: 960,
height: 500,
},
email: {
width: 500,
height: 400,
},
};
class Authenticator {
constructor(config = {}) {
this.site_id = config.site_id || null;
this.base_url = trimEnd(config.base_url, '/') || NETLIFY_API;
this.auth_endpoint = trim(config.auth_endpoint, '/') || AUTH_ENDPOINT;
}
handshakeCallback(options, cb) {
const fn = e => {
if (e.data === 'authorizing:' + options.provider && e.origin === this.base_url) {
window.removeEventListener('message', fn, false);
window.addEventListener('message', this.authorizeCallback(options, cb), false);
return this.authWindow.postMessage(e.data, e.origin);
}
};
return fn;
}
authorizeCallback(options, cb) {
const fn = e => {
if (e.origin !== this.base_url) {
return;
}
if (e.data.indexOf('authorization:' + options.provider + ':success:') === 0) {
const data = JSON.parse(
e.data.match(new RegExp('^authorization:' + options.provider + ':success:(.+)$'))[1],
);
window.removeEventListener('message', fn, false);
this.authWindow.close();
cb(null, data);
}
if (e.data.indexOf('authorization:' + options.provider + ':error:') === 0) {
const err = JSON.parse(
e.data.match(new RegExp('^authorization:' + options.provider + ':error:(.+)$'))[1],
);
window.removeEventListener('message', fn, false);
this.authWindow.close();
cb(new NetlifyError(err));
}
};
return fn;
}
getSiteID() {
if (this.site_id) {
return this.site_id;
}
const host = document.location.host.split(':')[0];
return host === 'localhost' ? 'cms.netlify.com' : host;
}
authenticate(options, cb) {
const { provider } = options;
const siteID = this.getSiteID();
if (!provider) {
return cb(
new NetlifyError({
message: 'You must specify a provider when calling netlify.authenticate',
}),
);
}
if (!siteID) {
return cb(
new NetlifyError({
message:
"You must set a site_id with netlify.configure({site_id: 'your-site-id'}) to make authentication work from localhost",
}),
);
}
const conf = PROVIDERS[provider] || PROVIDERS.github;
const left = screen.width / 2 - conf.width / 2;
const top = screen.height / 2 - conf.height / 2;
window.addEventListener('message', this.handshakeCallback(options, cb), false);
let url = `${this.base_url}/${this.auth_endpoint}?provider=${
options.provider
}&site_id=${siteID}`;
if (options.scope) {
url += '&scope=' + options.scope;
}
if (options.login === true) {
url += '&login=true';
}
if (options.beta_invite) {
url += '&beta_invite=' + options.beta_invite;
}
if (options.invite_code) {
url += '&invite_code=' + options.invite_code;
}
this.authWindow = window.open(
url,
'Netlify Authorization',
`width=${conf.width}, height=${conf.height}, top=${top}, left=${left}`,
);
this.authWindow.focus();
}
refresh(options, cb) {
const { provider, refresh_token } = options;
const siteID = this.getSiteID();
const onError = cb || Promise.reject.bind(Promise);
if (!provider || !refresh_token) {
return onError(
new NetlifyError({
message: 'You must specify a provider and refresh token when calling netlify.refresh',
}),
);
}
if (!siteID) {
return onError(
new NetlifyError({
message:
"You must set a site_id with netlify.configure({site_id: 'your-site-id'}) to make token refresh work from localhost",
}),
);
}
const url = `${this.base_url}/${
this.auth_endpoint
}/refresh?provider=${provider}&site_id=${siteID}&refresh_token=${refresh_token}`;
const refreshPromise = fetch(url, { method: 'POST', body: '' }).then(res => res.json());
// Return a promise if a callback wasn't provided
if (!cb) {
return refreshPromise;
}
// Otherwise, use the provided callback.
refreshPromise.then(data => cb(null, data)).catch(cb);
}
}
export default Authenticator;