UNPKG

mongodb-stitch

Version:

[![Join the chat at https://gitter.im/mongodb/stitch](https://badges.gitter.im/mongodb/stitch.svg)](https://gitter.im/mongodb/stitch?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

373 lines 15.6 kB
import { EJSON } from "bson"; import { wrapDecodingError } from "../../internal/common/StitchErrorUtils"; import Headers from "../../internal/net/Headers"; import Method from "../../internal/net/Method"; import Stream from "../../internal/net/Stream"; import { StitchAuthDocRequest } from "../../internal/net/StitchAuthDocRequest"; import { StitchAuthRequest } from "../../internal/net/StitchAuthRequest"; import { StitchDocRequest } from "../../internal/net/StitchDocRequest"; import StitchClientError from "../../StitchClientError"; import { StitchClientErrorCode } from "../../StitchClientErrorCode"; import StitchError from "../../StitchError"; import StitchRequestError from "../../StitchRequestError"; import { StitchRequestErrorCode } from "../../StitchRequestErrorCode"; import StitchServiceError from "../../StitchServiceError"; import { StitchServiceErrorCode } from "../../StitchServiceErrorCode"; import StitchAuthResponseCredential from "../providers/internal/StitchAuthResponseCredential"; import AccessTokenRefresher from "./AccessTokenRefresher"; import AuthInfo from "./AuthInfo"; import JWT from "./JWT"; import ApiAuthInfo from "./models/ApiAuthInfo"; import ApiCoreUserProfile from "./models/ApiCoreUserProfile"; import { readFromStorage, writeToStorage } from "./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 = readFromStorage(storage); } catch (e) { throw new StitchClientError(StitchClientErrorCode.CouldNotLoadPersistedAuthInfo); } if (info === undefined) { this.authInfo = AuthInfo.empty(); } else { this.authInfo = info; } this.prepUser(); if (useTokenRefresher) { this.accessTokenRefresher = new AccessTokenRefresher(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 = EJSON.parse(response.body, { strict: false }); if (decoder) { return decoder.decode(obj); } return obj; }) .catch(function (err) { throw wrapDecodingError(err); }); }; CoreStitchAuth.prototype.openAuthenticatedEventStream = function (stitchReq, open) { var _this = this; if (open === void 0) { open = true; } if (!this.isLoggedIn) { throw new StitchClientError(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(eventStream, decoder); }); }; CoreStitchAuth.prototype.refreshAccessToken = function () { var _this = this; var reqBuilder = new StitchAuthRequest.Builder() .withRefreshToken() .withPath(this.authRoutes.sessionRoute) .withMethod(Method.POST); return this.doAuthenticatedRequest(reqBuilder.build()).then(function (response) { try { var partialInfo = ApiAuthInfo.fromJSON(JSON.parse(response.body)); _this.authInfo = _this.authInfo.merge(partialInfo); } catch (err) { throw new StitchRequestError(err, StitchRequestErrorCode.DECODING_ERROR); } try { writeToStorage(_this.authInfo, _this.storage); } catch (err) { throw new StitchClientError(StitchClientErrorCode.CouldNotPersistAuthInfo); } }); }; CoreStitchAuth.prototype.loginWithCredentialInternal = function (credential) { if (credential instanceof StitchAuthResponseCredential) { 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(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(StitchClientErrorCode.MustAuthenticateFirst); } var newReq = stitchReq.builder; var newHeaders = newReq.headers || {}; if (stitchReq.useRefreshToken) { newHeaders[Headers.AUTHORIZATION] = Headers.getAuthorizationBearer(this.authInfo.refreshToken); } else { newHeaders[Headers.AUTHORIZATION] = Headers.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) || ex.errorCode !== 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) || ex.errorCode !== 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(StitchClientErrorCode.LoggedOutDuringRequest); } try { var jwt = JWT.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.Builder(); reqBuilder.withMethod(Method.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(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(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(newAuthInfo.userId, newAuthInfo.deviceId, newAuthInfo.accessToken, newAuthInfo.refreshToken, credential.providerType, credential.providerName, profile)); try { writeToStorage(newAuthInfo, _this.storage); } catch (err) { throw new StitchClientError(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("the login response could not be processed for credential: " + credential + ";" + "response was undefined"); } if (!response.body) { throw new StitchServiceError("response with status code " + response.statusCode + " has empty body"); } return this.processLogin(credential, ApiAuthInfo.fromJSON(JSON.parse(response.body)), asLinkRequest); } catch (err) { throw new StitchRequestError(err, StitchRequestErrorCode.DECODING_ERROR); } }; CoreStitchAuth.prototype.doGetUserProfile = function () { var reqBuilder = new StitchAuthRequest.Builder(); reqBuilder.withMethod(Method.GET).withPath(this.authRoutes.profileRoute); return this.doAuthenticatedRequest(reqBuilder.build()) .then(function (response) { return ApiCoreUserProfile.fromJSON(JSON.parse(response.body)); }) .catch(function (err) { if (err instanceof StitchError) { throw err; } else { throw new StitchRequestError(err, StitchRequestErrorCode.DECODING_ERROR); } }); }; CoreStitchAuth.prototype.doLogout = function () { var reqBuilder = new StitchAuthRequest.Builder(); reqBuilder .withRefreshToken() .withPath(this.authRoutes.sessionRoute) .withMethod(Method.DELETE); return this.doAuthenticatedRequest(reqBuilder.build()).then(function () { return; }); }; CoreStitchAuth.prototype.clearAuth = function () { if (!this.isLoggedIn) { return; } this.authInfo = this.authInfo.loggedOut(); try { writeToStorage(this.authInfo, this.storage); } catch (e) { throw new StitchClientError(StitchClientErrorCode.CouldNotPersistAuthInfo); } this.currentUser = undefined; this.onAuthEvent(); }; CoreStitchAuth.prototype.close = function () { if (this.accessTokenRefresher) { this.accessTokenRefresher.stop(); } }; return CoreStitchAuth; }()); export default CoreStitchAuth; //# sourceMappingURL=CoreStitchAuth.js.map