text: "use strict";
  var __extends = (this && this.__extends) || function (d, b) {
      for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
      function __() { this.constructor = d; }
      d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  };
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
      var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
      if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
      else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
      return c > 3 && r && Object.defineProperty(target, key, r), r;
  };
  var __metadata = (this && this.__metadata) || function (k, v) {
      if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
  };
  var __param = (this && this.__param) || function (paramIndex, decorator) {
      return function (target, key) { decorator(target, key, paramIndex); }
  };
  var http_1 = require("@angular/http");
  var core_1 = require("@angular/core");
  var Observable_1 = require("rxjs/Observable");
  require("rxjs/add/observable/fromPromise");
  require("rxjs/add/observable/defer");
  require("rxjs/add/operator/mergeMap");
  var AuthConfigConsts = (function () {
      function AuthConfigConsts() {
      }
      return AuthConfigConsts;
  }());
  AuthConfigConsts.DEFAULT_TOKEN_NAME = 'token';
  AuthConfigConsts.DEFAULT_HEADER_NAME = 'Authorization';
  AuthConfigConsts.HEADER_PREFIX_BEARER = 'Bearer ';
  exports.AuthConfigConsts = AuthConfigConsts;
  var AuthConfigDefaults = {
      headerName: AuthConfigConsts.DEFAULT_HEADER_NAME,
      headerPrefix: null,
      tokenName: AuthConfigConsts.DEFAULT_TOKEN_NAME,
      tokenGetter: function () {
          return (localStorage.getItem(AuthConfigDefaults.tokenName) ||
              sessionStorage.getItem(AuthConfigDefaults.tokenName));
      },
      noJwtError: false,
      noClientCheck: false,
      globalHeaders: [],
      noTokenScheme: false
  };
  /**
   * Sets up the authentication configuration.
   */
  var AuthConfig = (function () {
      function AuthConfig(config) {
          config = config || {};
          this._config = objectAssign({}, AuthConfigDefaults, config);
          if (this._config.headerPrefix) {
              this._config.headerPrefix += ' ';
          }
          else if (this._config.noTokenScheme) {
              this._config.headerPrefix = '';
          }
          else {
              this._config.headerPrefix = AuthConfigConsts.HEADER_PREFIX_BEARER;
          }
          if (config.tokenName && !config.tokenGetter) {
              this._config.tokenGetter = function () {
                  return (localStorage.getItem(config.tokenName) ||
                      sessionStorage.getItem(config.tokenName));
              };
          }
      }
      AuthConfig.prototype.getConfig = function () {
          return this._config;
      };
      return AuthConfig;
  }());
  exports.AuthConfig = AuthConfig;
  var AuthHttpError = (function (_super) {
      __extends(AuthHttpError, _super);
      function AuthHttpError() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      return AuthHttpError;
  }(Error));
  exports.AuthHttpError = AuthHttpError;
  /**
   * Allows for explicit authenticated HTTP requests.
   */
  var AuthHttp = (function () {
      function AuthHttp(options, http, defOpts) {
          var _this = this;
          this.http = http;
          this.defOpts = defOpts;
          this.config = options.getConfig();
          this.tokenStream = new Observable_1.Observable(function (obs) {
              obs.next(_this.config.tokenGetter());
          });
      }
      AuthHttp.prototype.mergeOptions = function (providedOpts, defaultOpts) {
          var newOptions = defaultOpts || new http_1.RequestOptions();
          if (this.config.globalHeaders) {
              this.setGlobalHeaders(this.config.globalHeaders, providedOpts);
          }
          newOptions = newOptions.merge(new http_1.RequestOptions(providedOpts));
          return newOptions;
      };
      AuthHttp.prototype.requestHelper = function (requestArgs, additionalOptions) {
          var options = new http_1.RequestOptions(requestArgs);
          if (additionalOptions) {
              options = options.merge(additionalOptions);
          }
          return this.request(new http_1.Request(this.mergeOptions(options, this.defOpts)));
      };
      AuthHttp.prototype.requestWithToken = function (req, token) {
          if (!this.config.noClientCheck && !tokenNotExpired(undefined, token)) {
              if (!this.config.noJwtError) {
                  return new Observable_1.Observable(function (obs) {
                      obs.error(new AuthHttpError('No JWT present or has expired'));
                  });
              }
          }
          else {
              req.headers.set(this.config.headerName, this.config.headerPrefix + token);
          }
          return this.http.request(req);
      };
      AuthHttp.prototype.setGlobalHeaders = function (headers, request) {
          if (!request.headers) {
              request.headers = new http_1.Headers();
          }
          headers.forEach(function (header) {
              var key = Object.keys(header)[0];
              var headerValue = header[key];
              request.headers.set(key, headerValue);
          });
      };
      AuthHttp.prototype.request = function (url, options) {
          var _this = this;
          if (typeof url === 'string') {
              return this.get(url, options); // Recursion: transform url from String to Request
          }
          // else if ( ! url instanceof Request ) {
          //   throw new Error('First argument must be a url string or Request instance.');
          // }
          // from this point url is always an instance of Request;
          var req = url;
          // Create a cold observable and load the token just in time
          return Observable_1.Observable.defer(function () {
              var token = _this.config.tokenGetter();
              if (token instanceof Promise) {
                  return Observable_1.Observable.fromPromise(token).mergeMap(function (jwtToken) { return _this.requestWithToken(req, jwtToken); });
              }
              else {
                  return _this.requestWithToken(req, token);
              }
          });
      };
      AuthHttp.prototype.get = function (url, options) {
          return this.requestHelper({ body: '', method: http_1.RequestMethod.Get, url: url }, options);
      };
      AuthHttp.prototype.post = function (url, body, options) {
          return this.requestHelper({ body: body, method: http_1.RequestMethod.Post, url: url }, options);
      };
      AuthHttp.prototype.put = function (url, body, options) {
          return this.requestHelper({ body: body, method: http_1.RequestMethod.Put, url: url }, options);
      };
      AuthHttp.prototype.delete = function (url, options) {
          return this.requestHelper({ body: '', method: http_1.RequestMethod.Delete, url: url }, options);
      };
      AuthHttp.prototype.patch = function (url, body, options) {
          return this.requestHelper({ body: body, method: http_1.RequestMethod.Patch, url: url }, options);
      };
      AuthHttp.prototype.head = function (url, options) {
          return this.requestHelper({ body: '', method: http_1.RequestMethod.Head, url: url }, options);
      };
      AuthHttp.prototype.options = function (url, options) {
          return this.requestHelper({ body: '', method: http_1.RequestMethod.Options, url: url }, options);
      };
      return AuthHttp;
  }());
  AuthHttp = __decorate([
      core_1.Injectable(),
      __metadata("design:paramtypes", [AuthConfig, http_1.Http, http_1.RequestOptions])
  ], AuthHttp);
  exports.AuthHttp = AuthHttp;
  /**
   * Helper class to decode and find JWT expiration.
   */
  var JwtHelper = (function () {
      function JwtHelper() {
      }
      JwtHelper.prototype.urlBase64Decode = function (str) {
          var output = str.replace(/-/g, '+').replace(/_/g, '/');
          switch (output.length % 4) {
              case 0: {
                  break;
              }
              case 2: {
                  output += '==';
                  break;
              }
              case 3: {
                  output += '=';
                  break;
              }
              default: {
                  throw 'Illegal base64url string!';
              }
          }
          return this.b64DecodeUnicode(output);
      };
      // credits for decoder goes to https://github.com/atk
      JwtHelper.prototype.b64decode = function (str) {
          var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
          var output = '';
          str = String(str).replace(/=+$/, '');
          if (str.length % 4 == 1) {
              throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");
          }
          for (
          // initialize result and counters
          var bc = 0, bs = void 0, buffer = void 0, idx = 0; 
          // get next character
          buffer = str.charAt(idx++); 
          // character found in table? initialize bit storage and add its ascii value;
          ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
              // and if not first of each 4 characters,
              // convert the first 8 bits to one ascii character
              bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0) {
              // try to find character in table (0-63, not found => -1)
              buffer = chars.indexOf(buffer);
          }
          return output;
      };
      // https://developer.mozilla.org/en/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem
      JwtHelper.prototype.b64DecodeUnicode = function (str) {
          return decodeURIComponent(Array.prototype.map.call(this.b64decode(str), function (c) {
              return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
          }).join(''));
      };
      JwtHelper.prototype.decodeToken = function (token) {
          var parts = token.split('.');
          if (parts.length !== 3) {
              throw new Error('JWT must have 3 parts');
          }
          var decoded = this.urlBase64Decode(parts[1]);
          if (!decoded) {
              throw new Error('Cannot decode the token');
          }
          return JSON.parse(decoded);
      };
      JwtHelper.prototype.getTokenExpirationDate = function (token) {
          var decoded;
          decoded = this.decodeToken(token);
          if (!decoded.hasOwnProperty('exp')) {
              return null;
          }
          var date = new Date(0); // The 0 here is the key, which sets the date to the epoch
          date.setUTCSeconds(decoded.exp);
          return date;
      };
      JwtHelper.prototype.isTokenExpired = function (token, offsetSeconds) {
          var date = this.getTokenExpirationDate(token);
          offsetSeconds = offsetSeconds || 0;
          if (date == null) {
              return false;
          }
          // Token expired?
          return !(date.valueOf() > (new Date().valueOf() + (offsetSeconds * 1000)));
      };
      return JwtHelper;
  }());
  exports.JwtHelper = JwtHelper;
  /**
   * Checks for presence of token and that token hasn't expired.
   * For use with the @CanActivate router decorator and NgIf
   */
  function tokenNotExpired(tokenName, jwt) {
      if (tokenName === void 0) { tokenName = AuthConfigConsts.DEFAULT_TOKEN_NAME; }
      var token = jwt || localStorage.getItem(tokenName) || sessionStorage.getItem(tokenName);
      var jwtHelper = new JwtHelper();
      return token != null && !jwtHelper.isTokenExpired(token);
  }
  exports.tokenNotExpired = tokenNotExpired;
  exports.AUTH_PROVIDERS = [
      {
          provide: AuthHttp,
          deps: [http_1.Http, http_1.RequestOptions],
          useFactory: function (http, options) {
              return new AuthHttp(new AuthConfig(), http, options);
          }
      }
  ];
  function provideAuth(config) {
      return [
          {
              provide: AuthHttp,
              deps: [http_1.Http, http_1.RequestOptions],
              useFactory: function (http, options) {
                  return new AuthHttp(new AuthConfig(config), http, options);
              }
          }
      ];
  }
  exports.provideAuth = provideAuth;
  var hasOwnProperty = Object.prototype.hasOwnProperty;
  var propIsEnumerable = Object.prototype.propertyIsEnumerable;
  function toObject(val) {
      if (val === null || val === undefined) {
          throw new TypeError('Object.assign cannot be called with null or undefined');
      }
      return Object(val);
  }
  function objectAssign(target) {
      var source = [];
      for (var _i = 1; _i < arguments.length; _i++) {
          source[_i - 1] = arguments[_i];
      }
      var from;
      var to = toObject(target);
      var symbols;
      for (var s = 0; s < source.length; s++) {
          from = Object(source[s]);
          for (var key in from) {
              if (hasOwnProperty.call(from, key)) {
                  to[key] = from[key];
              }
          }
          if (Object.getOwnPropertySymbols) {
              symbols = Object.getOwnPropertySymbols(from);
              for (var i = 0; i < symbols.length; i++) {
                  if (propIsEnumerable.call(from, symbols[i])) {
                      to[symbols[i]] = from[symbols[i]];
                  }
              }
          }
      }
      return to;
  }
  /**
   * Module for angular2-jwt
   * @experimental
   */
  var AuthModule = AuthModule_1 = (function () {
      function AuthModule(parentModule) {
          if (parentModule) {
              throw new Error('AuthModule is already loaded. Import it in the AppModule only');
          }
      }
      AuthModule.forRoot = function (config) {
          return {
              ngModule: AuthModule_1,
              providers: [
                  { provide: AuthConfig, useValue: config }
              ]
          };
      };
      return AuthModule;
  }());
  AuthModule = AuthModule_1 = __decorate([
      core_1.NgModule({
          imports: [http_1.HttpModule],
          providers: [AuthHttp, JwtHelper]
      }),
      __param(0, core_1.Optional()), __param(0, core_1.SkipSelf()),
      __metadata("design:paramtypes", [AuthModule])
  ], AuthModule);
  exports.AuthModule = AuthModule;
  var AuthModule_1;
  //# sourceMappingURL=angular2-jwt.js.map