node-sp-auth-nocolors
Version:
Unattended SharePoint http authentication with nodejs (Without Colors)
100 lines (78 loc) • 3.46 kB
text/typescript
import * as url from 'url';
import { request } from './../../config';
import * as cookie from 'cookie';
import template = require('lodash.template');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const 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';
import { template as fbaLoginWsfedTemplate } from './../../templates/FbaLoginWsfed';
export class OnpremiseFbaCredentials implements IAuthResolver {
private static CookieCache: Cache = new Cache();
constructor(private _siteUrl: string, private _authOptions: IOnpremiseUserCredentials) { }
public getAuth(): Promise<IAuthResponse> {
const parsedUrl: url.Url = url.parse(this._siteUrl);
const host: string = parsedUrl.host;
const cacheKey = `${host}@${this._authOptions.username}@${this._authOptions.password}`;
const cachedCookie: string = OnpremiseFbaCredentials.CookieCache.get<string>(cacheKey);
if (cachedCookie) {
return Promise.resolve({
headers: {
'Cookie': cachedCookie
}
});
}
const soapBody: string = template(fbaLoginWsfedTemplate)({
username: this._authOptions.username,
password: this._authOptions.password
});
const fbaEndPoint = `${parsedUrl.protocol}//${host}/${consts.FbaAuthEndpoint}`;
return request({
url: fbaEndPoint,
method: 'POST',
headers: {
'Content-Type': 'text/xml; charset=utf-8',
'Content-Length': soapBody.length.toString()
},
body: soapBody
})
.then(response => {
const xmlDoc: any = new xmldoc.XmlDocument(response.body);
if (xmlDoc.name === 'm:error') {
const errorCode: string = xmlDoc.childNamed('m:code').val;
const errorMessage: string = xmlDoc.childNamed('m:message').val;
throw new Error(`${errorCode}, ${errorMessage}`);
}
const errorCode: string =
xmlDoc.childNamed('soap:Body').childNamed('LoginResponse').childNamed('LoginResult').childNamed('ErrorCode').val;
const cookieName: string =
xmlDoc.childNamed('soap:Body').childNamed('LoginResponse').childNamed('LoginResult').childNamed('CookieName').val;
const 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];
}
});
const authCookie = `${cookieName}=${cookieValue}`;
OnpremiseFbaCredentials.CookieCache.set(cacheKey, authCookie, diffSeconds);
return {
headers: {
'Cookie': authCookie
}
};
}) as Promise<IAuthResponse>;
}
}