All files / src/auth/resolvers OnpremiseFbaCredentials.ts

30.23% Statements 13/43
0% Branches 0/12
0% Functions 0/5
30.95% Lines 13/42
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 1111x 1x 1x 1x 1x 1x 1x 1x   1x         1x 1x   1x   1x                                                                                                                                                                                      
import * as Promise from 'bluebird';
import * as _ from 'lodash';
import * as util from 'util';
import * as fs from 'fs';
import * as path from 'path';
import * as url from 'url';
import * as request from 'request-promise';
import * as cookie from 'cookie';
 
let xmldoc: any = require('xmldoc');
 
import { IAuthResolver } from './../IAuthResolver';
import { IOnpremiseUserCredentials } from './../IAuthOptions';
import { IAuthResponse } from './../IAuthResponse';
import { Cache } from './../../utils/Cache';
import * as consts from './../../Consts';
 
export class OnpremiseFbaCredentials implements IAuthResolver {
 
  private static CookieCache: Cache = new Cache();
 
  constructor(private _siteUrl: string, private _authOptions: IOnpremiseUserCredentials) { }
 
  public getAuth(): Promise<IAuthResponse> {
 
    let parsedUrl: url.Url = url.parse(this._siteUrl);
    let host: string = parsedUrl.host;
    let cacheKey: string = util.format('%s@%s', host, this._authOptions.username);
    let cachedCookie: string = OnpremiseFbaCredentials.CookieCache.get<string>(cacheKey);
 
    if (cachedCookie) {
      return Promise.resolve({
        headers: {
          'Cookie': cachedCookie
        }
      });
    }
 
    let soapBody: string = _.template(
      fs.readFileSync(
        path.join(__dirname, '..', '..', '..', 'templates', 'fba_login_wsfed.tmpl')
      ).toString()
    )({
      username: this._authOptions.username,
      password: this._authOptions.password
    });
 
    let fbaEndPoint = `${parsedUrl.protocol}//${host}/${consts.FbaAuthEndpoint}`;
 
    return request({
      url: fbaEndPoint,
      method: 'POST',
      headers: {
        'Content-Type': 'text/xml; charset=utf-8',
        'Content-Length': soapBody.length
      },
      body: soapBody,
      json: false,
      simple: false,
      strictSSL: false,
      transform: (body: any, response: any, resolveWithFullResponse: any) => {
        return response;
      }
    } as any)
      .then((response: any) => {
 
        let xmlDoc: any = new xmldoc.XmlDocument(response.body);
 
        if (xmlDoc.name === 'm:error') {
          let errorCode: string = xmlDoc.childNamed('m:code').val;
          let errorMessage: string = xmlDoc.childNamed('m:message').val;
          throw new Error(`${errorCode}, ${errorMessage}`);
        }
 
        let errorCode: string =
          xmlDoc.childNamed('soap:Body').childNamed('LoginResponse').childNamed('LoginResult').childNamed('ErrorCode').val;
        let cookieName: string =
          xmlDoc.childNamed('soap:Body').childNamed('LoginResponse').childNamed('LoginResult').childNamed('CookieName').val;
        let diffSeconds: number = parseInt(
          xmlDoc.childNamed('soap:Body').childNamed('LoginResponse').childNamed('LoginResult').childNamed('TimeoutSeconds').val,
          null
        );
        let cookieValue: string;
 
        if (errorCode === 'PasswordNotMatch') {
          throw new Error(`Password doesn't not match`);
        }
        if (errorCode !== 'NoError') {
          throw new Error(errorCode);
        }
 
        (response.headers['set-cookie'] || []).forEach((headerCookie: string) => {
          if (headerCookie.indexOf(cookieName) !== -1) {
            cookieValue = cookie.parse(headerCookie)[cookieName];
          }
        });
 
        let authCookie = `${cookieName}=${cookieValue}`;
 
        OnpremiseFbaCredentials.CookieCache.set(cacheKey, authCookie, diffSeconds);
 
        return {
          headers: {
            'Cookie': authCookie
          }
        };
 
      }) as Promise<IAuthResponse>;
  };
}