1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.AuthenticationClient = void 0;
|
4 | const errors_1 = require("@feathersjs/errors");
|
5 | const storage_1 = require("./storage");
|
6 | class OauthError extends errors_1.FeathersError {
|
7 | constructor(message, data) {
|
8 | super(message, 'OauthError', 401, 'oauth-error', data);
|
9 | }
|
10 | }
|
11 | const getMatch = (location, key) => {
|
12 | const regex = new RegExp(`(?:\&?)${key}=([^&]*)`);
|
13 | const match = location.hash ? location.hash.match(regex) : null;
|
14 | if (match !== null) {
|
15 | const [, value] = match;
|
16 | return [value, regex];
|
17 | }
|
18 | return [null, regex];
|
19 | };
|
20 | class AuthenticationClient {
|
21 | constructor(app, options) {
|
22 | const socket = app.io;
|
23 | const storage = new storage_1.StorageWrapper(app.get('storage') || options.storage);
|
24 | this.app = app;
|
25 | this.options = options;
|
26 | this.authenticated = false;
|
27 | this.app.set('storage', storage);
|
28 | if (socket) {
|
29 | this.handleSocket(socket);
|
30 | }
|
31 | }
|
32 | get service() {
|
33 | return this.app.service(this.options.path);
|
34 | }
|
35 | get storage() {
|
36 | return this.app.get('storage');
|
37 | }
|
38 | handleSocket(socket) {
|
39 |
|
40 |
|
41 | socket.on('disconnect', () => {
|
42 | if (this.authenticated) {
|
43 | this.reAuthenticate(true);
|
44 | }
|
45 | });
|
46 | }
|
47 | |
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 | getFromLocation(location) {
|
55 | const [accessToken, tokenRegex] = getMatch(location, this.options.locationKey);
|
56 | if (accessToken !== null) {
|
57 | location.hash = location.hash.replace(tokenRegex, '');
|
58 | return Promise.resolve(accessToken);
|
59 | }
|
60 | const [message, errorRegex] = getMatch(location, this.options.locationErrorKey);
|
61 | if (message !== null) {
|
62 | location.hash = location.hash.replace(errorRegex, '');
|
63 | return Promise.reject(new OauthError(decodeURIComponent(message)));
|
64 | }
|
65 | return Promise.resolve(null);
|
66 | }
|
67 | |
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 | setAccessToken(accessToken) {
|
74 | return this.storage.setItem(this.options.storageKey, accessToken);
|
75 | }
|
76 | |
77 |
|
78 |
|
79 |
|
80 |
|
81 | getAccessToken() {
|
82 | return this.storage.getItem(this.options.storageKey).then((accessToken) => {
|
83 | if (!accessToken && typeof window !== 'undefined' && window.location) {
|
84 | return this.getFromLocation(window.location);
|
85 | }
|
86 | return accessToken || null;
|
87 | });
|
88 | }
|
89 | |
90 |
|
91 |
|
92 |
|
93 | removeAccessToken() {
|
94 | return this.storage.removeItem(this.options.storageKey);
|
95 | }
|
96 | |
97 |
|
98 |
|
99 |
|
100 |
|
101 | reset() {
|
102 | this.app.set('authentication', null);
|
103 | this.authenticated = false;
|
104 | return Promise.resolve(null);
|
105 | }
|
106 | handleError(error, type) {
|
107 |
|
108 |
|
109 | if (error.code > 400 && error.code < 408) {
|
110 | const promise = this.removeAccessToken().then(() => this.reset());
|
111 | return type === 'logout' ? promise : promise.then(() => Promise.reject(error));
|
112 | }
|
113 | return this.reset().then(() => Promise.reject(error));
|
114 | }
|
115 | |
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 | reAuthenticate(force = false, strategy, authParams) {
|
125 |
|
126 |
|
127 | let authPromise = this.app.get('authentication');
|
128 | if (!authPromise || force === true) {
|
129 | authPromise = this.getAccessToken().then((accessToken) => {
|
130 | if (!accessToken) {
|
131 | return this.handleError(new errors_1.NotAuthenticated('No accessToken found in storage'), 'authenticate');
|
132 | }
|
133 | return this.authenticate({
|
134 | strategy: strategy || this.options.jwtStrategy,
|
135 | accessToken
|
136 | }, authParams);
|
137 | });
|
138 | this.app.set('authentication', authPromise);
|
139 | }
|
140 | return authPromise;
|
141 | }
|
142 | |
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 | authenticate(authentication, params) {
|
150 | if (!authentication) {
|
151 | return this.reAuthenticate();
|
152 | }
|
153 | const promise = this.service
|
154 | .create(authentication, params)
|
155 | .then((authResult) => {
|
156 | const { accessToken } = authResult;
|
157 | this.authenticated = true;
|
158 | this.app.emit('login', authResult);
|
159 | this.app.emit('authenticated', authResult);
|
160 | return this.setAccessToken(accessToken).then(() => authResult);
|
161 | })
|
162 | .catch((error) => this.handleError(error, 'authenticate'));
|
163 | this.app.set('authentication', promise);
|
164 | return promise;
|
165 | }
|
166 | |
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 | logout() {
|
173 | return Promise.resolve(this.app.get('authentication'))
|
174 | .then(() => this.service.remove(null).then((authResult) => this.removeAccessToken()
|
175 | .then(() => this.reset())
|
176 | .then(() => {
|
177 | this.app.emit('logout', authResult);
|
178 | return authResult;
|
179 | })))
|
180 | .catch((error) => this.handleError(error, 'logout'));
|
181 | }
|
182 | }
|
183 | exports.AuthenticationClient = AuthenticationClient;
|
184 |
|
\ | No newline at end of file |