1 |
|
2 | "use strict";
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | Object.defineProperty(exports, "__esModule", { value: true });
|
20 | exports.handleCryptoSignerError = exports.FirebaseTokenGenerator = exports.EmulatedSigner = exports.BLACKLISTED_CLAIMS = void 0;
|
21 | var error_1 = require("../utils/error");
|
22 | var crypto_signer_1 = require("../utils/crypto-signer");
|
23 | var validator = require("../utils/validator");
|
24 | var utils_1 = require("../utils");
|
25 | var ALGORITHM_NONE = 'none';
|
26 | var ONE_HOUR_IN_SECONDS = 60 * 60;
|
27 |
|
28 | exports.BLACKLISTED_CLAIMS = [
|
29 | 'acr', 'amr', 'at_hash', 'aud', 'auth_time', 'azp', 'cnf', 'c_hash', 'exp', 'iat', 'iss', 'jti',
|
30 | 'nbf', 'nonce',
|
31 | ];
|
32 |
|
33 | var FIREBASE_AUDIENCE = 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit';
|
34 |
|
35 |
|
36 |
|
37 |
|
38 | var EmulatedSigner = (function () {
|
39 | function EmulatedSigner() {
|
40 | this.algorithm = ALGORITHM_NONE;
|
41 | }
|
42 | |
43 |
|
44 |
|
45 |
|
46 | EmulatedSigner.prototype.sign = function (buffer) {
|
47 | return Promise.resolve(Buffer.from(''));
|
48 | };
|
49 | |
50 |
|
51 |
|
52 | EmulatedSigner.prototype.getAccountId = function () {
|
53 | return Promise.resolve('firebase-auth-emulator@example.com');
|
54 | };
|
55 | return EmulatedSigner;
|
56 | }());
|
57 | exports.EmulatedSigner = EmulatedSigner;
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 | var FirebaseTokenGenerator = (function () {
|
64 | |
65 |
|
66 |
|
67 |
|
68 |
|
69 | function FirebaseTokenGenerator(signer, tenantId) {
|
70 | this.tenantId = tenantId;
|
71 | if (!validator.isNonNullObject(signer)) {
|
72 | throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, 'INTERNAL ASSERT: Must provide a CryptoSigner to use FirebaseTokenGenerator.');
|
73 | }
|
74 | if (typeof this.tenantId !== 'undefined' && !validator.isNonEmptyString(this.tenantId)) {
|
75 | throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '`tenantId` argument must be a non-empty string.');
|
76 | }
|
77 | this.signer = signer;
|
78 | }
|
79 | |
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | FirebaseTokenGenerator.prototype.createCustomToken = function (uid, developerClaims) {
|
89 | var _this = this;
|
90 | var errorMessage;
|
91 | if (!validator.isNonEmptyString(uid)) {
|
92 | errorMessage = '`uid` argument must be a non-empty string uid.';
|
93 | }
|
94 | else if (uid.length > 128) {
|
95 | errorMessage = '`uid` argument must a uid with less than or equal to 128 characters.';
|
96 | }
|
97 | else if (!this.isDeveloperClaimsValid_(developerClaims)) {
|
98 | errorMessage = '`developerClaims` argument must be a valid, non-null object containing the developer claims.';
|
99 | }
|
100 | if (errorMessage) {
|
101 | throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, errorMessage);
|
102 | }
|
103 | var claims = {};
|
104 | if (typeof developerClaims !== 'undefined') {
|
105 | for (var key in developerClaims) {
|
106 |
|
107 | if (Object.prototype.hasOwnProperty.call(developerClaims, key)) {
|
108 | if (exports.BLACKLISTED_CLAIMS.indexOf(key) !== -1) {
|
109 | throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Developer claim \"" + key + "\" is reserved and cannot be specified.");
|
110 | }
|
111 | claims[key] = developerClaims[key];
|
112 | }
|
113 | }
|
114 | }
|
115 | return this.signer.getAccountId().then(function (account) {
|
116 | var header = {
|
117 | alg: _this.signer.algorithm,
|
118 | typ: 'JWT',
|
119 | };
|
120 | var iat = Math.floor(Date.now() / 1000);
|
121 | var body = {
|
122 | aud: FIREBASE_AUDIENCE,
|
123 | iat: iat,
|
124 | exp: iat + ONE_HOUR_IN_SECONDS,
|
125 | iss: account,
|
126 | sub: account,
|
127 | uid: uid,
|
128 | };
|
129 | if (_this.tenantId) {
|
130 |
|
131 | body.tenant_id = _this.tenantId;
|
132 | }
|
133 | if (Object.keys(claims).length > 0) {
|
134 | body.claims = claims;
|
135 | }
|
136 | var token = _this.encodeSegment(header) + "." + _this.encodeSegment(body);
|
137 | var signPromise = _this.signer.sign(Buffer.from(token));
|
138 | return Promise.all([token, signPromise]);
|
139 | }).then(function (_a) {
|
140 | var token = _a[0], signature = _a[1];
|
141 | return token + "." + _this.encodeSegment(signature);
|
142 | }).catch(function (err) {
|
143 | throw handleCryptoSignerError(err);
|
144 | });
|
145 | };
|
146 | FirebaseTokenGenerator.prototype.encodeSegment = function (segment) {
|
147 | var buffer = (segment instanceof Buffer) ? segment : Buffer.from(JSON.stringify(segment));
|
148 | return utils_1.toWebSafeBase64(buffer).replace(/=+$/, '');
|
149 | };
|
150 | |
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 | FirebaseTokenGenerator.prototype.isDeveloperClaimsValid_ = function (developerClaims) {
|
157 | if (typeof developerClaims === 'undefined') {
|
158 | return true;
|
159 | }
|
160 | return validator.isNonNullObject(developerClaims);
|
161 | };
|
162 | return FirebaseTokenGenerator;
|
163 | }());
|
164 | exports.FirebaseTokenGenerator = FirebaseTokenGenerator;
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 | function handleCryptoSignerError(err) {
|
173 | if (!(err instanceof crypto_signer_1.CryptoSignerError)) {
|
174 | return err;
|
175 | }
|
176 | if (err.code === crypto_signer_1.CryptoSignerErrorCode.SERVER_ERROR && validator.isNonNullObject(err.cause)) {
|
177 | var httpError = err.cause;
|
178 | var errorResponse = httpError.response.data;
|
179 | if (validator.isNonNullObject(errorResponse) && errorResponse.error) {
|
180 | var errorCode = errorResponse.error.status;
|
181 | var description = 'Please refer to https://firebase.google.com/docs/auth/admin/create-custom-tokens ' +
|
182 | 'for more details on how to use and troubleshoot this feature.';
|
183 | var errorMsg = errorResponse.error.message + "; " + description;
|
184 | return error_1.FirebaseAuthError.fromServerError(errorCode, errorMsg, errorResponse);
|
185 | }
|
186 | return new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'Error returned from server: ' + errorResponse + '. Additionally, an ' +
|
187 | 'internal error occurred while attempting to extract the ' +
|
188 | 'errorcode from the error.');
|
189 | }
|
190 | return new error_1.FirebaseAuthError(mapToAuthClientErrorCode(err.code), err.message);
|
191 | }
|
192 | exports.handleCryptoSignerError = handleCryptoSignerError;
|
193 | function mapToAuthClientErrorCode(code) {
|
194 | switch (code) {
|
195 | case crypto_signer_1.CryptoSignerErrorCode.INVALID_CREDENTIAL:
|
196 | return error_1.AuthClientErrorCode.INVALID_CREDENTIAL;
|
197 | case crypto_signer_1.CryptoSignerErrorCode.INVALID_ARGUMENT:
|
198 | return error_1.AuthClientErrorCode.INVALID_ARGUMENT;
|
199 | default:
|
200 | return error_1.AuthClientErrorCode.INTERNAL_ERROR;
|
201 | }
|
202 | }
|