UNPKG

18.6 kBJavaScriptView Raw
1"use strict";
2var __extends = (this && this.__extends) || function (d, b) {
3 for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
4 function __() { this.constructor = d; }
5 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6};
7var errors_1 = require('./errors');
8var promise_1 = require('./promise');
9/**
10 * @hidden
11 */
12var AuthTokenContext = (function () {
13 function AuthTokenContext(deps, label) {
14 this.label = label;
15 this.storage = deps.storage;
16 }
17 AuthTokenContext.prototype.get = function () {
18 return this.storage.get(this.label);
19 };
20 AuthTokenContext.prototype.store = function (token) {
21 this.storage.set(this.label, token);
22 };
23 AuthTokenContext.prototype.delete = function () {
24 this.storage.delete(this.label);
25 };
26 return AuthTokenContext;
27}());
28exports.AuthTokenContext = AuthTokenContext;
29/**
30 * @hidden
31 */
32var CombinedAuthTokenContext = (function () {
33 function CombinedAuthTokenContext(deps, label) {
34 this.label = label;
35 this.storage = deps.storage;
36 this.tempStorage = deps.tempStorage;
37 }
38 CombinedAuthTokenContext.prototype.get = function () {
39 var permToken = this.storage.get(this.label);
40 var tempToken = this.tempStorage.get(this.label);
41 var token = tempToken || permToken;
42 return token;
43 };
44 CombinedAuthTokenContext.prototype.store = function (token, options) {
45 if (options === void 0) { options = { 'permanent': true }; }
46 if (options.permanent) {
47 this.storage.set(this.label, token);
48 }
49 else {
50 this.tempStorage.set(this.label, token);
51 }
52 };
53 CombinedAuthTokenContext.prototype.delete = function () {
54 this.storage.delete(this.label);
55 this.tempStorage.delete(this.label);
56 };
57 return CombinedAuthTokenContext;
58}());
59exports.CombinedAuthTokenContext = CombinedAuthTokenContext;
60/**
61 * `Auth` handles authentication of a single user, such as signing up, logging
62 * in & out, social provider authentication, etc.
63 *
64 * @featured
65 */
66var Auth = (function () {
67 function Auth(deps,
68 /**
69 * @hidden
70 */
71 options) {
72 if (options === void 0) { options = {}; }
73 this.options = options;
74 this.config = deps.config;
75 this.emitter = deps.emitter;
76 this.authModules = deps.authModules;
77 this.tokenContext = deps.tokenContext;
78 this.userService = deps.userService;
79 this.storage = deps.storage;
80 }
81 Object.defineProperty(Auth.prototype, "passwordResetUrl", {
82 /**
83 * Link the user to this URL for password resets. Only for email/password
84 * authentication.
85 *
86 * Use this if you want to use our password reset forms instead of creating
87 * your own in your app.
88 */
89 get: function () {
90 return this.config.getURL('web') + "/password/reset/" + this.config.get('app_id');
91 },
92 enumerable: true,
93 configurable: true
94 });
95 /**
96 * Check whether the user is logged in or not.
97 *
98 * If an auth token exists in local storage, the user is logged in.
99 */
100 Auth.prototype.isAuthenticated = function () {
101 var token = this.tokenContext.get();
102 if (token) {
103 return true;
104 }
105 return false;
106 };
107 /**
108 * Sign up a user with the given data. Only for email/password
109 * authentication.
110 *
111 * `signup` does not affect local data or the current user until `login` is
112 * called. This means you'll likely want to log in your users manually after
113 * signup.
114 *
115 * If a signup fails, the promise rejects with a [`IDetailedError`
116 * object](/api/client/idetailederror) that contains an array of error codes
117 * from the cloud.
118 *
119 * @param details - The details that describe a user.
120 */
121 Auth.prototype.signup = function (details) {
122 return this.authModules.basic.signup(details);
123 };
124 /**
125 * Attempt to log the user in with the given credentials. For custom & social
126 * logins, kick-off the authentication process.
127 *
128 * After login, the full user is loaded from the cloud and saved in local
129 * storage along with their auth token.
130 *
131 * @note TODO: Better error handling docs.
132 *
133 * @param moduleId
134 * The authentication provider module ID to use with this login.
135 * @param credentials
136 * For email/password authentication, give an email and password. For social
137 * authentication, exclude this parameter. For custom authentication, send
138 * whatever you need.
139 * @param options
140 * Options for this login, such as whether to remember the login and
141 * InAppBrowser window options for authentication providers that make use of
142 * it.
143 */
144 Auth.prototype.login = function (moduleId, credentials, options) {
145 var _this = this;
146 if (options === void 0) { options = {}; }
147 if (typeof options.remember === 'undefined') {
148 options.remember = true;
149 }
150 if (typeof options.inAppBrowserOptions === 'undefined') {
151 options.inAppBrowserOptions = {};
152 }
153 if (typeof options.inAppBrowserOptions.location === 'undefined') {
154 options.inAppBrowserOptions.location = false;
155 }
156 if (typeof options.inAppBrowserOptions.clearcache === 'undefined') {
157 options.inAppBrowserOptions.clearcache = true;
158 }
159 if (typeof options.inAppBrowserOptions.clearsessioncache === 'undefined') {
160 options.inAppBrowserOptions.clearsessioncache = true;
161 }
162 var context = this.authModules[moduleId];
163 if (!context) {
164 throw new Error('Authentication class is invalid or missing:' + context);
165 }
166 return context.authenticate(credentials, options).then(function (r) {
167 _this.storeToken(options, r.token);
168 return _this.userService.load().then(function () {
169 var user = _this.userService.current();
170 user.store();
171 return r;
172 });
173 });
174 };
175 /**
176 * Log the user out of the app.
177 *
178 * This clears the auth token out of local storage and restores the user to
179 * an unauthenticated state.
180 */
181 Auth.prototype.logout = function () {
182 this.tokenContext.delete();
183 var user = this.userService.current();
184 user.unstore();
185 user.clear();
186 };
187 /**
188 * Kick-off the password reset process. Only for email/password
189 * authentication.
190 *
191 * An email will be sent to the user with a short password reset code, which
192 * they can copy back into your app and use the [`confirmPasswordReset()`
193 * method](#confirmPasswordReset).
194 *
195 * @param email - The email address to which to send a code.
196 */
197 Auth.prototype.requestPasswordReset = function (email) {
198 this.storage.set('auth_password_reset_email', email);
199 return this.authModules.basic.requestPasswordReset(email);
200 };
201 /**
202 * Confirm a password reset.
203 *
204 * When the user gives you their password reset code into your app and their
205 * requested changed password, call this method.
206 *
207 * @param code - The password reset code from the user.
208 * @param newPassword - The requested changed password from the user.
209 */
210 Auth.prototype.confirmPasswordReset = function (code, newPassword) {
211 var email = this.storage.get('auth_password_reset_email');
212 return this.authModules.basic.confirmPasswordReset(email, code, newPassword);
213 };
214 /**
215 * Get the raw auth token of the active user from local storage.
216 */
217 Auth.prototype.getToken = function () {
218 return this.tokenContext.get();
219 };
220 /**
221 * @hidden
222 */
223 Auth.prototype.storeToken = function (options, token) {
224 if (options === void 0) { options = { 'remember': true }; }
225 var originalToken = this.authToken;
226 this.authToken = token;
227 this.tokenContext.store(this.authToken, { 'permanent': options.remember });
228 this.emitter.emit('auth:token-changed', { 'old': originalToken, 'new': this.authToken });
229 };
230 /**
231 * @hidden
232 */
233 Auth.getDetailedErrorFromResponse = function (res) {
234 var errors = [];
235 var details = [];
236 try {
237 details = res.body.error.details;
238 }
239 catch (e) { }
240 for (var i = 0; i < details.length; i++) {
241 var detail = details[i];
242 if (detail.error_type) {
243 errors.push(detail.error_type + '_' + detail.parameter);
244 }
245 }
246 return new errors_1.DetailedError('Error creating user', errors);
247 };
248 return Auth;
249}());
250exports.Auth = Auth;
251/**
252 * @hidden
253 */
254var AuthType = (function () {
255 function AuthType(deps) {
256 this.config = deps.config;
257 this.client = deps.client;
258 }
259 AuthType.prototype.parseInAppBrowserOptions = function (opts) {
260 if (!opts) {
261 return '';
262 }
263 var p = [];
264 for (var k in opts) {
265 var v = void 0;
266 if (typeof opts[k] === 'boolean') {
267 v = opts[k] ? 'yes' : 'no';
268 }
269 else {
270 v = opts[k];
271 }
272 p.push(k + "=" + v);
273 }
274 return p.join(',');
275 };
276 AuthType.prototype.inAppBrowserFlow = function (moduleId, data, options) {
277 var _this = this;
278 if (data === void 0) { data = {}; }
279 var deferred = new promise_1.DeferredPromise();
280 if (!window || !window.cordova || !window.cordova.InAppBrowser) {
281 deferred.reject(new Error('InAppBrowser plugin missing'));
282 }
283 else {
284 this.client.post("/auth/login/" + moduleId)
285 .send({
286 'app_id': this.config.get('app_id'),
287 'callback': window.location.href,
288 'data': data
289 })
290 .end(function (err, res) {
291 if (err) {
292 deferred.reject(err);
293 }
294 else {
295 var w_1 = window.cordova.InAppBrowser.open(res.body.data.url, '_blank', _this.parseInAppBrowserOptions(options.inAppBrowserOptions));
296 var onExit_1 = function () {
297 deferred.reject(new Error('InAppBrowser exit'));
298 };
299 var onLoadError_1 = function () {
300 deferred.reject(new Error('InAppBrowser loaderror'));
301 };
302 var onLoadStart = function (data) {
303 if (data.url.slice(0, 20) === 'http://auth.ionic.io') {
304 var queryString = data.url.split('#')[0].split('?')[1];
305 var paramParts = queryString.split('&');
306 var params = {};
307 for (var i = 0; i < paramParts.length; i++) {
308 var part = paramParts[i].split('=');
309 params[part[0]] = part[1];
310 }
311 w_1.removeEventListener('exit', onExit_1);
312 w_1.removeEventListener('loaderror', onLoadError_1);
313 w_1.close();
314 deferred.resolve({
315 'token': params['token'],
316 'signup': Boolean(parseInt(params['signup'], 10))
317 });
318 }
319 };
320 w_1.addEventListener('exit', onExit_1);
321 w_1.addEventListener('loaderror', onLoadError_1);
322 w_1.addEventListener('loadstart', onLoadStart);
323 }
324 });
325 }
326 return deferred.promise;
327 };
328 return AuthType;
329}());
330exports.AuthType = AuthType;
331/**
332 * @hidden
333 */
334var BasicAuth = (function (_super) {
335 __extends(BasicAuth, _super);
336 function BasicAuth() {
337 _super.apply(this, arguments);
338 }
339 BasicAuth.prototype.authenticate = function (data, options) {
340 var deferred = new promise_1.DeferredPromise();
341 if (!data.email || !data.password) {
342 deferred.reject(new Error('email and password are required for basic authentication'));
343 }
344 else {
345 this.client.post('/auth/login')
346 .send({
347 'app_id': this.config.get('app_id'),
348 'email': data.email,
349 'password': data.password
350 })
351 .end(function (err, res) {
352 if (err) {
353 deferred.reject(err);
354 }
355 else {
356 deferred.resolve({
357 'token': res.body.data.token
358 });
359 }
360 });
361 }
362 return deferred.promise;
363 };
364 BasicAuth.prototype.requestPasswordReset = function (email) {
365 var deferred = new promise_1.DeferredPromise();
366 if (!email) {
367 deferred.reject(new Error('Email is required for password reset request.'));
368 }
369 else {
370 this.client.post('/users/password/reset')
371 .send({
372 'app_id': this.config.get('app_id'),
373 'email': email,
374 'flow': 'app'
375 })
376 .end(function (err, res) {
377 if (err) {
378 deferred.reject(err);
379 }
380 else {
381 deferred.resolve();
382 }
383 });
384 }
385 return deferred.promise;
386 };
387 BasicAuth.prototype.confirmPasswordReset = function (email, code, newPassword) {
388 var deferred = new promise_1.DeferredPromise();
389 if (!code || !email || !newPassword) {
390 deferred.reject(new Error('Code, new password, and email are required.'));
391 }
392 else {
393 this.client.post('/users/password')
394 .send({
395 'reset_token': code,
396 'new_password': newPassword,
397 'email': email
398 })
399 .end(function (err, res) {
400 if (err) {
401 deferred.reject(err);
402 }
403 else {
404 deferred.resolve();
405 }
406 });
407 }
408 return deferred.promise;
409 };
410 BasicAuth.prototype.signup = function (data) {
411 var deferred = new promise_1.DeferredPromise();
412 var userData = {
413 'app_id': this.config.get('app_id'),
414 'email': data.email,
415 'password': data.password
416 };
417 // optional details
418 if (data.username) {
419 userData.username = data.username;
420 }
421 if (data.image) {
422 userData.image = data.image;
423 }
424 if (data.name) {
425 userData.name = data.name;
426 }
427 if (data.custom) {
428 userData.custom = data.custom;
429 }
430 this.client.post('/users')
431 .send(userData)
432 .end(function (err, res) {
433 if (err) {
434 deferred.reject(Auth.getDetailedErrorFromResponse(err.response));
435 }
436 else {
437 deferred.resolve();
438 }
439 });
440 return deferred.promise;
441 };
442 return BasicAuth;
443}(AuthType));
444exports.BasicAuth = BasicAuth;
445/**
446 * @hidden
447 */
448var CustomAuth = (function (_super) {
449 __extends(CustomAuth, _super);
450 function CustomAuth() {
451 _super.apply(this, arguments);
452 }
453 CustomAuth.prototype.authenticate = function (data, options) {
454 if (data === void 0) { data = {}; }
455 return this.inAppBrowserFlow('custom', data, options);
456 };
457 return CustomAuth;
458}(AuthType));
459exports.CustomAuth = CustomAuth;
460/**
461 * @hidden
462 */
463var TwitterAuth = (function (_super) {
464 __extends(TwitterAuth, _super);
465 function TwitterAuth() {
466 _super.apply(this, arguments);
467 }
468 TwitterAuth.prototype.authenticate = function (data, options) {
469 if (data === void 0) { data = {}; }
470 return this.inAppBrowserFlow('twitter', data, options);
471 };
472 return TwitterAuth;
473}(AuthType));
474exports.TwitterAuth = TwitterAuth;
475/**
476 * @hidden
477 */
478var FacebookAuth = (function (_super) {
479 __extends(FacebookAuth, _super);
480 function FacebookAuth() {
481 _super.apply(this, arguments);
482 }
483 FacebookAuth.prototype.authenticate = function (data, options) {
484 if (data === void 0) { data = {}; }
485 return this.inAppBrowserFlow('facebook', data, options);
486 };
487 return FacebookAuth;
488}(AuthType));
489exports.FacebookAuth = FacebookAuth;
490/**
491 * @hidden
492 */
493var GithubAuth = (function (_super) {
494 __extends(GithubAuth, _super);
495 function GithubAuth() {
496 _super.apply(this, arguments);
497 }
498 GithubAuth.prototype.authenticate = function (data, options) {
499 if (data === void 0) { data = {}; }
500 return this.inAppBrowserFlow('github', data, options);
501 };
502 return GithubAuth;
503}(AuthType));
504exports.GithubAuth = GithubAuth;
505/**
506 * @hidden
507 */
508var GoogleAuth = (function (_super) {
509 __extends(GoogleAuth, _super);
510 function GoogleAuth() {
511 _super.apply(this, arguments);
512 }
513 GoogleAuth.prototype.authenticate = function (data, options) {
514 if (data === void 0) { data = {}; }
515 return this.inAppBrowserFlow('google', data, options);
516 };
517 return GoogleAuth;
518}(AuthType));
519exports.GoogleAuth = GoogleAuth;
520/**
521 * @hidden
522 */
523var InstagramAuth = (function (_super) {
524 __extends(InstagramAuth, _super);
525 function InstagramAuth() {
526 _super.apply(this, arguments);
527 }
528 InstagramAuth.prototype.authenticate = function (data, options) {
529 if (data === void 0) { data = {}; }
530 return this.inAppBrowserFlow('instagram', data, options);
531 };
532 return InstagramAuth;
533}(AuthType));
534exports.InstagramAuth = InstagramAuth;
535/**
536 * @hidden
537 */
538var LinkedInAuth = (function (_super) {
539 __extends(LinkedInAuth, _super);
540 function LinkedInAuth() {
541 _super.apply(this, arguments);
542 }
543 LinkedInAuth.prototype.authenticate = function (data, options) {
544 if (data === void 0) { data = {}; }
545 return this.inAppBrowserFlow('linkedin', data, options);
546 };
547 return LinkedInAuth;
548}(AuthType));
549exports.LinkedInAuth = LinkedInAuth;