mongodb-stitch
Version:
[](https://gitter.im/mongodb/stitch?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
388 lines • 19.5 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "bson", "../../internal/common/StitchErrorUtils", "../../internal/net/Headers", "../../internal/net/Method", "../../internal/net/Stream", "../../internal/net/StitchAuthDocRequest", "../../internal/net/StitchAuthRequest", "../../internal/net/StitchDocRequest", "../../StitchClientError", "../../StitchClientErrorCode", "../../StitchError", "../../StitchRequestError", "../../StitchRequestErrorCode", "../../StitchServiceError", "../../StitchServiceErrorCode", "../providers/internal/StitchAuthResponseCredential", "./AccessTokenRefresher", "./AuthInfo", "./JWT", "./models/ApiAuthInfo", "./models/ApiCoreUserProfile", "./models/StoreAuthInfo"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var bson_1 = require("bson");
var StitchErrorUtils_1 = require("../../internal/common/StitchErrorUtils");
var Headers_1 = __importDefault(require("../../internal/net/Headers"));
var Method_1 = __importDefault(require("../../internal/net/Method"));
var Stream_1 = __importDefault(require("../../internal/net/Stream"));
var StitchAuthDocRequest_1 = require("../../internal/net/StitchAuthDocRequest");
var StitchAuthRequest_1 = require("../../internal/net/StitchAuthRequest");
var StitchDocRequest_1 = require("../../internal/net/StitchDocRequest");
var StitchClientError_1 = __importDefault(require("../../StitchClientError"));
var StitchClientErrorCode_1 = require("../../StitchClientErrorCode");
var StitchError_1 = __importDefault(require("../../StitchError"));
var StitchRequestError_1 = __importDefault(require("../../StitchRequestError"));
var StitchRequestErrorCode_1 = require("../../StitchRequestErrorCode");
var StitchServiceError_1 = __importDefault(require("../../StitchServiceError"));
var StitchServiceErrorCode_1 = require("../../StitchServiceErrorCode");
var StitchAuthResponseCredential_1 = __importDefault(require("../providers/internal/StitchAuthResponseCredential"));
var AccessTokenRefresher_1 = __importDefault(require("./AccessTokenRefresher"));
var AuthInfo_1 = __importDefault(require("./AuthInfo"));
var JWT_1 = __importDefault(require("./JWT"));
var ApiAuthInfo_1 = __importDefault(require("./models/ApiAuthInfo"));
var ApiCoreUserProfile_1 = __importDefault(require("./models/ApiCoreUserProfile"));
var StoreAuthInfo_1 = require("./models/StoreAuthInfo");
var OPTIONS = "options";
var DEVICE = "device";
var CoreStitchAuth = (function () {
function CoreStitchAuth(requestClient, authRoutes, storage, useTokenRefresher) {
if (useTokenRefresher === void 0) { useTokenRefresher = true; }
this.requestClient = requestClient;
this.authRoutes = authRoutes;
this.storage = storage;
var info;
try {
info = StoreAuthInfo_1.readFromStorage(storage);
}
catch (e) {
throw new StitchClientError_1.default(StitchClientErrorCode_1.StitchClientErrorCode.CouldNotLoadPersistedAuthInfo);
}
if (info === undefined) {
this.authInfo = AuthInfo_1.default.empty();
}
else {
this.authInfo = info;
}
this.prepUser();
if (useTokenRefresher) {
this.accessTokenRefresher = new AccessTokenRefresher_1.default(this);
this.accessTokenRefresher.run();
}
}
Object.defineProperty(CoreStitchAuth.prototype, "isLoggedIn", {
get: function () {
return this.currentUser !== undefined;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CoreStitchAuth.prototype, "user", {
get: function () {
return this.currentUser;
},
enumerable: true,
configurable: true
});
CoreStitchAuth.prototype.doAuthenticatedRequest = function (stitchReq) {
var _this = this;
return this.requestClient
.doRequest(this.prepareAuthRequest(stitchReq))
.catch(function (err) {
return _this.handleAuthFailure(err, stitchReq);
});
};
CoreStitchAuth.prototype.doAuthenticatedRequestWithDecoder = function (stitchReq, decoder) {
return this.doAuthenticatedRequest(stitchReq)
.then(function (response) {
var obj = bson_1.EJSON.parse(response.body, { strict: false });
if (decoder) {
return decoder.decode(obj);
}
return obj;
})
.catch(function (err) {
throw StitchErrorUtils_1.wrapDecodingError(err);
});
};
CoreStitchAuth.prototype.openAuthenticatedEventStream = function (stitchReq, open) {
var _this = this;
if (open === void 0) { open = true; }
if (!this.isLoggedIn) {
throw new StitchClientError_1.default(StitchClientErrorCode_1.StitchClientErrorCode.MustAuthenticateFirst);
}
var authToken;
if (stitchReq.useRefreshToken) {
authToken = this.authInfo.refreshToken;
}
else {
authToken = this.authInfo.accessToken;
}
return this.requestClient.doStreamRequest(stitchReq.builder
.withPath(stitchReq.path + "&stitch_at=" + authToken)
.build(), open, function () { return _this.openAuthenticatedEventStream(stitchReq, false); })
.catch(function (err) {
return _this.handleAuthFailureForEventStream(err, stitchReq, open);
});
};
CoreStitchAuth.prototype.openAuthenticatedStreamWithDecoder = function (stitchReq, decoder) {
return this.openAuthenticatedEventStream(stitchReq)
.then(function (eventStream) {
return new Stream_1.default(eventStream, decoder);
});
};
CoreStitchAuth.prototype.refreshAccessToken = function () {
var _this = this;
var reqBuilder = new StitchAuthRequest_1.StitchAuthRequest.Builder()
.withRefreshToken()
.withPath(this.authRoutes.sessionRoute)
.withMethod(Method_1.default.POST);
return this.doAuthenticatedRequest(reqBuilder.build()).then(function (response) {
try {
var partialInfo = ApiAuthInfo_1.default.fromJSON(JSON.parse(response.body));
_this.authInfo = _this.authInfo.merge(partialInfo);
}
catch (err) {
throw new StitchRequestError_1.default(err, StitchRequestErrorCode_1.StitchRequestErrorCode.DECODING_ERROR);
}
try {
StoreAuthInfo_1.writeToStorage(_this.authInfo, _this.storage);
}
catch (err) {
throw new StitchClientError_1.default(StitchClientErrorCode_1.StitchClientErrorCode.CouldNotPersistAuthInfo);
}
});
};
CoreStitchAuth.prototype.loginWithCredentialInternal = function (credential) {
if (credential instanceof StitchAuthResponseCredential_1.default) {
return this.processLogin(credential, credential.authInfo, credential.asLink);
}
if (!this.isLoggedIn) {
return this.doLogin(credential, false);
}
if (credential.providerCapabilities.reusesExistingSession) {
if (credential.providerType === this.currentUser.loggedInProviderType) {
return Promise.resolve(this.currentUser);
}
}
this.logoutInternal();
return this.doLogin(credential, false);
};
CoreStitchAuth.prototype.linkUserWithCredentialInternal = function (user, credential) {
if (this.currentUser !== undefined && user.id !== this.currentUser.id) {
return Promise.reject(new StitchClientError_1.default(StitchClientErrorCode_1.StitchClientErrorCode.UserNoLongerValid));
}
return this.doLogin(credential, true);
};
CoreStitchAuth.prototype.logoutInternal = function () {
var _this = this;
if (!this.isLoggedIn) {
return Promise.resolve();
}
return this.doLogout()
.then(function () {
_this.clearAuth();
})
.catch(function () {
_this.clearAuth();
});
};
Object.defineProperty(CoreStitchAuth.prototype, "hasDeviceId", {
get: function () {
return (this.authInfo.deviceId !== undefined &&
this.authInfo.deviceId !== "" &&
this.authInfo.deviceId !== "000000000000000000000000");
},
enumerable: true,
configurable: true
});
Object.defineProperty(CoreStitchAuth.prototype, "deviceId", {
get: function () {
if (!this.hasDeviceId) {
return undefined;
}
return this.authInfo.deviceId;
},
enumerable: true,
configurable: true
});
CoreStitchAuth.prototype.prepareAuthRequest = function (stitchReq) {
if (!this.isLoggedIn) {
throw new StitchClientError_1.default(StitchClientErrorCode_1.StitchClientErrorCode.MustAuthenticateFirst);
}
var newReq = stitchReq.builder;
var newHeaders = newReq.headers || {};
if (stitchReq.useRefreshToken) {
newHeaders[Headers_1.default.AUTHORIZATION] = Headers_1.default.getAuthorizationBearer(this.authInfo.refreshToken);
}
else {
newHeaders[Headers_1.default.AUTHORIZATION] = Headers_1.default.getAuthorizationBearer(this.authInfo.accessToken);
}
newReq.withHeaders(newHeaders);
return newReq.build();
};
CoreStitchAuth.prototype.handleAuthFailureForEventStream = function (ex, req, open) {
var _this = this;
if (open === void 0) { open = true; }
if (!(ex instanceof StitchServiceError_1.default) ||
ex.errorCode !== StitchServiceErrorCode_1.StitchServiceErrorCode.InvalidSession) {
throw ex;
}
if (req.useRefreshToken || !req.shouldRefreshOnFailure) {
this.clearAuth();
throw ex;
}
return this.tryRefreshAccessToken(req.startedAt).then(function () {
return _this.openAuthenticatedEventStream(req.builder.withShouldRefreshOnFailure(false).build(), open);
});
};
CoreStitchAuth.prototype.handleAuthFailure = function (ex, req) {
var _this = this;
if (!(ex instanceof StitchServiceError_1.default) ||
ex.errorCode !== StitchServiceErrorCode_1.StitchServiceErrorCode.InvalidSession) {
throw ex;
}
if (req.useRefreshToken || !req.shouldRefreshOnFailure) {
this.clearAuth();
throw ex;
}
return this.tryRefreshAccessToken(req.startedAt).then(function () {
return _this.doAuthenticatedRequest(req.builder.withShouldRefreshOnFailure(false).build());
});
};
CoreStitchAuth.prototype.tryRefreshAccessToken = function (reqStartedAt) {
if (!this.isLoggedIn) {
throw new StitchClientError_1.default(StitchClientErrorCode_1.StitchClientErrorCode.LoggedOutDuringRequest);
}
try {
var jwt = JWT_1.default.fromEncoded(this.authInfo.accessToken);
if (jwt.issuedAt >= reqStartedAt) {
return Promise.resolve();
}
}
catch (e) {
}
return this.refreshAccessToken();
};
CoreStitchAuth.prototype.prepUser = function () {
if (this.authInfo.userId !== undefined) {
this.currentUser = this.userFactory.makeUser(this.authInfo.userId, this.authInfo.loggedInProviderType, this.authInfo.loggedInProviderName, this.authInfo.userProfile);
}
};
CoreStitchAuth.prototype.attachAuthOptions = function (authBody) {
var options = {};
options[DEVICE] = this.deviceInfo;
authBody[OPTIONS] = options;
};
CoreStitchAuth.prototype.doLogin = function (credential, asLinkRequest) {
var _this = this;
return this.doLoginRequest(credential, asLinkRequest)
.then(function (response) { return _this.processLoginResponse(credential, response, asLinkRequest); })
.then(function (user) {
_this.onAuthEvent();
return user;
});
};
CoreStitchAuth.prototype.doLoginRequest = function (credential, asLinkRequest) {
var reqBuilder = new StitchDocRequest_1.StitchDocRequest.Builder();
reqBuilder.withMethod(Method_1.default.POST);
if (asLinkRequest) {
reqBuilder.withPath(this.authRoutes.getAuthProviderLinkRoute(credential.providerName));
}
else {
reqBuilder.withPath(this.authRoutes.getAuthProviderLoginRoute(credential.providerName));
}
var material = credential.material;
this.attachAuthOptions(material);
reqBuilder.withDocument(material);
if (!asLinkRequest) {
return this.requestClient.doRequest(reqBuilder.build());
}
var linkRequest = new StitchAuthDocRequest_1.StitchAuthDocRequest(reqBuilder.build(), reqBuilder.document);
return this.doAuthenticatedRequest(linkRequest);
};
CoreStitchAuth.prototype.processLogin = function (credential, newAuthInfo, asLinkRequest) {
var _this = this;
var oldInfo = this.authInfo;
var oldUser = this.currentUser;
newAuthInfo = this.authInfo.merge(new AuthInfo_1.default(newAuthInfo.userId, newAuthInfo.deviceId, newAuthInfo.accessToken, newAuthInfo.refreshToken, credential.providerType, credential.providerName, undefined));
this.authInfo = newAuthInfo;
this.currentUser = this.userFactory.makeUser(this.authInfo.userId, credential.providerType, credential.providerName, undefined);
return this.doGetUserProfile()
.then(function (profile) {
newAuthInfo = newAuthInfo.merge(new AuthInfo_1.default(newAuthInfo.userId, newAuthInfo.deviceId, newAuthInfo.accessToken, newAuthInfo.refreshToken, credential.providerType, credential.providerName, profile));
try {
StoreAuthInfo_1.writeToStorage(newAuthInfo, _this.storage);
}
catch (err) {
throw new StitchClientError_1.default(StitchClientErrorCode_1.StitchClientErrorCode.CouldNotPersistAuthInfo);
}
_this.authInfo = newAuthInfo;
_this.currentUser = _this.userFactory.makeUser(_this.authInfo.userId, credential.providerType, credential.providerName, profile);
return _this.currentUser;
})
.catch(function (err) {
if (asLinkRequest) {
_this.authInfo = oldInfo;
_this.currentUser = oldUser;
}
else {
_this.clearAuth();
}
throw err;
});
};
CoreStitchAuth.prototype.processLoginResponse = function (credential, response, asLinkRequest) {
try {
if (!response) {
throw new StitchServiceError_1.default("the login response could not be processed for credential: " + credential + ";" +
"response was undefined");
}
if (!response.body) {
throw new StitchServiceError_1.default("response with status code " + response.statusCode + " has empty body");
}
return this.processLogin(credential, ApiAuthInfo_1.default.fromJSON(JSON.parse(response.body)), asLinkRequest);
}
catch (err) {
throw new StitchRequestError_1.default(err, StitchRequestErrorCode_1.StitchRequestErrorCode.DECODING_ERROR);
}
};
CoreStitchAuth.prototype.doGetUserProfile = function () {
var reqBuilder = new StitchAuthRequest_1.StitchAuthRequest.Builder();
reqBuilder.withMethod(Method_1.default.GET).withPath(this.authRoutes.profileRoute);
return this.doAuthenticatedRequest(reqBuilder.build())
.then(function (response) { return ApiCoreUserProfile_1.default.fromJSON(JSON.parse(response.body)); })
.catch(function (err) {
if (err instanceof StitchError_1.default) {
throw err;
}
else {
throw new StitchRequestError_1.default(err, StitchRequestErrorCode_1.StitchRequestErrorCode.DECODING_ERROR);
}
});
};
CoreStitchAuth.prototype.doLogout = function () {
var reqBuilder = new StitchAuthRequest_1.StitchAuthRequest.Builder();
reqBuilder
.withRefreshToken()
.withPath(this.authRoutes.sessionRoute)
.withMethod(Method_1.default.DELETE);
return this.doAuthenticatedRequest(reqBuilder.build()).then(function () {
return;
});
};
CoreStitchAuth.prototype.clearAuth = function () {
if (!this.isLoggedIn) {
return;
}
this.authInfo = this.authInfo.loggedOut();
try {
StoreAuthInfo_1.writeToStorage(this.authInfo, this.storage);
}
catch (e) {
throw new StitchClientError_1.default(StitchClientErrorCode_1.StitchClientErrorCode.CouldNotPersistAuthInfo);
}
this.currentUser = undefined;
this.onAuthEvent();
};
CoreStitchAuth.prototype.close = function () {
if (this.accessTokenRefresher) {
this.accessTokenRefresher.stop();
}
};
return CoreStitchAuth;
}());
exports.default = CoreStitchAuth;
});
//# sourceMappingURL=CoreStitchAuth.js.map