Source: authorization/basic-authorization.js

/**
 * Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
 */


/**
 * Class used to authorize a mobile user against Oracle Mobile Cloud Service. Callers should use
 * MobileBackend's [BasicAuthorization()]{@link MobileBackend#authorization} property.
 * Derives from {@link Authorization}.
 * @constructor
 * @global
 */
function BasicAuthorization(config, backend, appKey, utils, platform, logger) {

  Authorization.call(this, backend, appKey, utils, platform, logger);

  var HEADERS = utils.HEADERS;

  var _backendId = utils.validateConfiguration(config.backendId);
  var _anonymousToken = utils.validateConfiguration(config.anonymousToken);

  var _authorizedUserName = null;

  var _this = this;

  /**
   * Returns the username of the current authorized user if any, null otherwise.
   * @type {String}
   */
  this.getAuthorizedUserName = function(){
    return _authorizedUserName;
  };


  /**
   * Authenticates a user with the given credentials against the service. The user remains logged in until logout() is called.
   * @param username {String} The username of the credentials.
   * @param password {String} The password of the credentials.
   * @param [successCallback] {Authorization~authenticateSuccessCallback} Optional callback invoked on success (deprecated).
   * @param [errorCallback] {Authorization~authenticateErrorCallback} Optional callback invoked on failure (deprecated).
   * @return {Promise.<NetworkResponse|NetworkResponse>}
   */
  this.authenticate = function (username, password, successCallback, errorCallback) {

    this.logout();

    if (!username || !password) {
      logger.error('Wrong username or password parameter');
      if (errorCallback) {
        errorCallback(400, 'Bad Request');
        return undefined;
      } else {
        return Promise.reject(new NetworkResponse(400, 'Bad Request'));
      }
    }

    var authorizationToken = "Basic " + utils.encodeBase64(username + ":" + password);

    var headers = {};
    headers[HEADERS.AUTHORIZATION] = authorizationToken;
    headers[HEADERS.ORACLE_MOBILE_BACKEND_ID] = _backendId;
    headers[HEADERS.ORACLE_MOBILE_APPLICATION_KEY] = _this._getApplicationKey();
    headers[HEADERS.ORACLE_MOBILE_CLIENT_SDK_INFO] = backend.getClientSDKInfoHeader(utils.MODULE_NAMES.AUTHORIZATION);

    return platform.invokeService({
        url: backend.getPlatformUrl("users/login"),
        method: utils.HTTP_METHODS.GET,
        headers: headers
      })
      .then(invokeServiceSuccess, invokeServiceError);

    function invokeServiceSuccess(response){
      _this._authenticateSuccess(response, authorizationToken);
      _authorizedUserName = username;

      if (successCallback) {
        successCallback(response.statusCode, response.data);
      }
      return response;
    }

    function invokeServiceError(response){
      _this._authenticateError(response);
      if (errorCallback) {
        errorCallback(response.statusCode, response.data);
      } else {
        return Promise.reject(response);
      }
    }
  };

    /**
     * Authenticates an anonymous user against the service. The user remains logged in until logout() is called.
     * @param [successCallback] {Authorization~authenticateSuccessCallback} Optional callback invoked on success (deprecated use promises instead).
     * @param [errorCallback] {Authorization~errorCallback} Optional callback invoked on failure (deprecated use promises instead).
     * @return {Promise.<NetworkResponse|NetworkResponse>}
     */
    this.authenticateAnonymous = function (successCallback, errorCallback) {

    var authorizationToken = 'Basic ' + _anonymousToken;
    var headers = {};
    headers[HEADERS.ORACLE_MOBILE_BACKEND_ID] = _backendId;

    return this._authenticateAnonymousInvoke(authorizationToken,
      headers,
      backend.getPlatformUrl("users/login"),
      utils.HTTP_METHODS.GET)
      .then(invokeServiceSuccess, invokeServiceError);

    function invokeServiceSuccess(response) {
      if (successCallback) {
        successCallback(response.statusCode, response.data);
      }
      return response;
    }

    function invokeServiceError(response) {
      if(errorCallback) {
        errorCallback(response.statusCode, response.data);
      } else {
        return Promise.reject(response);
      }
    }
  };

  this._anonymousTokenResponseConverter = function(response){
    return { orgResponse: response.orgResponse, anonymousAccessToken: response.authorizationToken };
  };


  /**
   * Checks to see if the authorization token is null, undefined, NaN,an empty string (""), 0, or false.
   * @returns {Boolean}
   */
  this.isTokenValid = function () {

    if (this.getAccessToken() !== null && typeof this.getAccessToken() == 'string') {
      logger.info("Authorization token is not null or empty");
      return true;
    }
    else if (this.getAccessToken() == null && typeof this.getAccessToken() !== 'string') {
      logger.info("Authorization token is null and/or empty");
      return false;
    }
  };

  /**
   * For BasicAuth, there is no need to call this function, because the token never expires.
   * This function only exists here because it inherits from the Authorization object, which is also used for other types of authentication in which the token can expire.
   * @param [successCallback] {Authorization~authenticateSuccessCallback} Optional callback invoked on success (deprecated use promises instead).
   * @param [errorCallback] {Authorization~authenticateErrorCallback} Optional callback invoked on failure (deprecated use promises instead).
   * @return {Promise.<NetworkResponse|NetworkResponse>}
   */
  this.refreshToken = function(successCallback, errorCallback) {

    if (!this._getIsAuthorized() && !this.isTokenValid()) {
      if (errorCallback && typeof errorCallback === 'function') {
        errorCallback(401, "Please use the authenticate with username/password combination or authenticateAnonymous function before using refreshToken.");
        return undefined;
      } else {
        return Promise.reject(new NetworkResponse(401, "Please use the authenticate with username/password combination or authenticateAnonymous function before using refreshToken."));
      }
    }
    else if (this._getIsAuthorized() && this.isTokenValid()) {
      logger.error("Authenticated token is valid, you do not need to refresh.");
      if (successCallback && typeof successCallback === 'function') {
        successCallback(200, this.getAccessToken());
      }
      return Promise.resolve(new NetworkResponse(200, this.getAccessToken()));
    }
  };

  /**
   * Logs out the current user and clears credentials and tokens.
   */
  this.logout = function() {
    this._clearState();
  };

  this._getHttpHeaders = function(headers) {
    if (this.getAccessToken() !== null && typeof this.getAccessToken() == "string") {
      headers[HEADERS.AUTHORIZATION] = this.getAccessToken();
    }
    headers[HEADERS.ORACLE_MOBILE_BACKEND_ID] = _backendId;
    headers[HEADERS.ORACLE_MOBILE_APPLICATION_KEY]= _this._getApplicationKey();
  };

  this._getAnonymousHttpHeaders = function (headers) {
    if (this._getAnonymousAccessToken() && typeof this._getAnonymousAccessToken() == "string") {
      headers[HEADERS.AUTHORIZATION] = this._getAnonymousAccessToken();
    }
    headers[HEADERS.ORACLE_MOBILE_BACKEND_ID] = _backendId;
    headers[HEADERS.ORACLE_MOBILE_APPLICATION_KEY] = _this._getApplicationKey();
  };

  var baseClearState = this._clearState;
  this._clearState = function(){
    baseClearState.call(this);
    _authorizedUserName = null;
  }
}

BasicAuthorization.prototype = Object.create(Authorization.prototype);
BasicAuthorization.prototype.constructor = BasicAuthorization;