@backstage/plugin-auth-backend 0.16.0 → 0.17.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/index.cjs.js +48 -30
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/package.json +11 -12
- package/LICENSE +0 -201
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @backstage/plugin-auth-backend
|
|
2
2
|
|
|
3
|
+
## 0.17.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5fa831ce55: CookieConfigurer can optionally return the `SameSite` cookie attribute.
|
|
8
|
+
CookieConfigurer now requires an additional argument `appOrigin` - the origin URL of the app - which is used to calculate the `SameSite` attribute.
|
|
9
|
+
defaultCookieConfigurer returns the `SameSite` attribute which defaults to `Lax`. In cases where an auth-backend is running on a different domain than the App, `SameSite=None` is used - but only for secure contexts. This is so that cookies can be included in third-party requests.
|
|
10
|
+
|
|
11
|
+
OAuthAdapterOptions has been modified to require additional arguments, `baseUrl`, and `cookieConfigurer`.
|
|
12
|
+
OAuthAdapter now resolves cookie configuration using its supplied CookieConfigurer for each request to make sure that the proper attributes always are set.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 8c6ec175bf: Fix GitLab provider setup so that it supports GitLab installations with a path in the URL.
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
- @backstage/catalog-model@1.1.2-next.0
|
|
19
|
+
- @backstage/catalog-client@1.1.1-next.0
|
|
20
|
+
- @backstage/backend-common@0.15.2-next.0
|
|
21
|
+
- @backstage/plugin-auth-node@0.2.6-next.0
|
|
22
|
+
- @backstage/config@1.0.3-next.0
|
|
23
|
+
- @backstage/errors@1.1.2-next.0
|
|
24
|
+
- @backstage/types@1.0.0
|
|
25
|
+
|
|
3
26
|
## 0.16.0
|
|
4
27
|
|
|
5
28
|
### Minor Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -165,12 +165,17 @@ const verifyNonce = (req, providerId) => {
|
|
|
165
165
|
};
|
|
166
166
|
const defaultCookieConfigurer = ({
|
|
167
167
|
callbackUrl,
|
|
168
|
-
providerId
|
|
168
|
+
providerId,
|
|
169
|
+
appOrigin
|
|
169
170
|
}) => {
|
|
170
171
|
const { hostname: domain, pathname, protocol } = new URL(callbackUrl);
|
|
171
172
|
const secure = protocol === "https:";
|
|
173
|
+
let sameSite = "lax";
|
|
174
|
+
if (new URL(appOrigin).hostname !== domain && secure) {
|
|
175
|
+
sameSite = "none";
|
|
176
|
+
}
|
|
172
177
|
const path = pathname.endsWith(`${providerId}/handler/frame`) ? pathname.slice(0, -"/handler/frame".length) : `${pathname}/${providerId}`;
|
|
173
|
-
return { domain, path, secure };
|
|
178
|
+
return { domain, path, secure, sameSite };
|
|
174
179
|
};
|
|
175
180
|
|
|
176
181
|
class OAuthEnvironmentHandler {
|
|
@@ -286,58 +291,62 @@ class OAuthAdapter {
|
|
|
286
291
|
constructor(handlers, options) {
|
|
287
292
|
this.handlers = handlers;
|
|
288
293
|
this.options = options;
|
|
289
|
-
this.setNonceCookie = (res, nonce) => {
|
|
294
|
+
this.setNonceCookie = (res, nonce, cookieConfig) => {
|
|
290
295
|
res.cookie(`${this.options.providerId}-nonce`, nonce, {
|
|
291
296
|
maxAge: TEN_MINUTES_MS,
|
|
292
297
|
...this.baseCookieOptions,
|
|
293
|
-
|
|
298
|
+
...cookieConfig,
|
|
299
|
+
path: `${cookieConfig.path}/handler`
|
|
294
300
|
});
|
|
295
301
|
};
|
|
296
|
-
this.setGrantedScopeCookie = (res, scope) => {
|
|
302
|
+
this.setGrantedScopeCookie = (res, scope, cookieConfig) => {
|
|
297
303
|
res.cookie(`${this.options.providerId}-granted-scope`, scope, {
|
|
298
304
|
maxAge: THOUSAND_DAYS_MS,
|
|
299
|
-
...this.baseCookieOptions
|
|
305
|
+
...this.baseCookieOptions,
|
|
306
|
+
...cookieConfig
|
|
300
307
|
});
|
|
301
308
|
};
|
|
302
309
|
this.getGrantedScopeFromCookie = (req) => {
|
|
303
310
|
return req.cookies[`${this.options.providerId}-granted-scope`];
|
|
304
311
|
};
|
|
305
|
-
this.setRefreshTokenCookie = (res, refreshToken) => {
|
|
312
|
+
this.setRefreshTokenCookie = (res, refreshToken, cookieConfig) => {
|
|
306
313
|
res.cookie(`${this.options.providerId}-refresh-token`, refreshToken, {
|
|
307
314
|
maxAge: THOUSAND_DAYS_MS,
|
|
308
|
-
...this.baseCookieOptions
|
|
315
|
+
...this.baseCookieOptions,
|
|
316
|
+
...cookieConfig
|
|
309
317
|
});
|
|
310
318
|
};
|
|
311
|
-
this.removeRefreshTokenCookie = (res) => {
|
|
319
|
+
this.removeRefreshTokenCookie = (res, cookieConfig) => {
|
|
312
320
|
res.cookie(`${this.options.providerId}-refresh-token`, "", {
|
|
313
321
|
maxAge: 0,
|
|
314
|
-
...this.baseCookieOptions
|
|
322
|
+
...this.baseCookieOptions,
|
|
323
|
+
...cookieConfig
|
|
324
|
+
});
|
|
325
|
+
};
|
|
326
|
+
this.getCookieConfig = (origin) => {
|
|
327
|
+
return this.options.cookieConfigurer({
|
|
328
|
+
providerId: this.options.providerId,
|
|
329
|
+
baseUrl: this.options.baseUrl,
|
|
330
|
+
callbackUrl: this.options.callbackUrl,
|
|
331
|
+
appOrigin: origin != null ? origin : this.options.appOrigin
|
|
315
332
|
});
|
|
316
333
|
};
|
|
317
334
|
this.baseCookieOptions = {
|
|
318
335
|
httpOnly: true,
|
|
319
|
-
sameSite: "lax"
|
|
320
|
-
secure: this.options.secure,
|
|
321
|
-
path: this.options.cookiePath,
|
|
322
|
-
domain: this.options.cookieDomain
|
|
336
|
+
sameSite: "lax"
|
|
323
337
|
};
|
|
324
338
|
}
|
|
325
339
|
static fromConfig(config, handlers, options) {
|
|
326
340
|
var _a;
|
|
327
|
-
const {
|
|
341
|
+
const { appUrl, baseUrl, isOriginAllowed } = config;
|
|
342
|
+
const { origin: appOrigin } = new url.URL(appUrl);
|
|
328
343
|
const cookieConfigurer = (_a = config.cookieConfigurer) != null ? _a : defaultCookieConfigurer;
|
|
329
|
-
const cookieConfig = cookieConfigurer({
|
|
330
|
-
providerId: options.providerId,
|
|
331
|
-
baseUrl: config.baseUrl,
|
|
332
|
-
callbackUrl: options.callbackUrl
|
|
333
|
-
});
|
|
334
344
|
return new OAuthAdapter(handlers, {
|
|
335
345
|
...options,
|
|
336
346
|
appOrigin,
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
isOriginAllowed: config.isOriginAllowed
|
|
347
|
+
baseUrl,
|
|
348
|
+
cookieConfigurer,
|
|
349
|
+
isOriginAllowed
|
|
341
350
|
});
|
|
342
351
|
}
|
|
343
352
|
async start(req, res) {
|
|
@@ -348,8 +357,9 @@ class OAuthAdapter {
|
|
|
348
357
|
if (!env) {
|
|
349
358
|
throw new errors.InputError("No env provided in request query parameters");
|
|
350
359
|
}
|
|
360
|
+
const cookieConfig = this.getCookieConfig(origin);
|
|
351
361
|
const nonce = crypto__default["default"].randomBytes(16).toString("base64");
|
|
352
|
-
this.setNonceCookie(res, nonce);
|
|
362
|
+
this.setNonceCookie(res, nonce, cookieConfig);
|
|
353
363
|
const state = { nonce, env, origin };
|
|
354
364
|
if (this.options.persistScopes) {
|
|
355
365
|
state.scope = scope;
|
|
@@ -380,12 +390,13 @@ class OAuthAdapter {
|
|
|
380
390
|
}
|
|
381
391
|
verifyNonce(req, this.options.providerId);
|
|
382
392
|
const { response, refreshToken } = await this.handlers.handler(req);
|
|
393
|
+
const cookieConfig = this.getCookieConfig(appOrigin);
|
|
383
394
|
if (this.options.persistScopes && state.scope) {
|
|
384
|
-
this.setGrantedScopeCookie(res, state.scope);
|
|
395
|
+
this.setGrantedScopeCookie(res, state.scope, cookieConfig);
|
|
385
396
|
response.providerInfo.scope = state.scope;
|
|
386
397
|
}
|
|
387
398
|
if (refreshToken) {
|
|
388
|
-
this.setRefreshTokenCookie(res, refreshToken);
|
|
399
|
+
this.setRefreshTokenCookie(res, refreshToken, cookieConfig);
|
|
389
400
|
}
|
|
390
401
|
const identity = await this.populateIdentity(response.backstageIdentity);
|
|
391
402
|
return postMessageResponse(res, appOrigin, {
|
|
@@ -404,7 +415,9 @@ class OAuthAdapter {
|
|
|
404
415
|
if (!ensuresXRequestedWith(req)) {
|
|
405
416
|
throw new errors.AuthenticationError("Invalid X-Requested-With header");
|
|
406
417
|
}
|
|
407
|
-
|
|
418
|
+
const origin = req.get("origin");
|
|
419
|
+
const cookieConfig = this.getCookieConfig(origin);
|
|
420
|
+
this.removeRefreshTokenCookie(res, cookieConfig);
|
|
408
421
|
res.status(200).end();
|
|
409
422
|
}
|
|
410
423
|
async refresh(req, res) {
|
|
@@ -432,7 +445,9 @@ class OAuthAdapter {
|
|
|
432
445
|
response.backstageIdentity
|
|
433
446
|
);
|
|
434
447
|
if (newRefreshToken && newRefreshToken !== refreshToken) {
|
|
435
|
-
|
|
448
|
+
const origin = req.get("origin");
|
|
449
|
+
const cookieConfig = this.getCookieConfig(origin);
|
|
450
|
+
this.setRefreshTokenCookie(res, newRefreshToken, cookieConfig);
|
|
436
451
|
}
|
|
437
452
|
res.status(200).json({ ...response, backstageIdentity });
|
|
438
453
|
} catch (error) {
|
|
@@ -1555,7 +1570,10 @@ class GitlabAuthProvider {
|
|
|
1555
1570
|
clientID: options.clientId,
|
|
1556
1571
|
clientSecret: options.clientSecret,
|
|
1557
1572
|
callbackURL: options.callbackUrl,
|
|
1558
|
-
baseURL: options.baseUrl
|
|
1573
|
+
baseURL: options.baseUrl,
|
|
1574
|
+
authorizationURL: `${options.baseUrl}/oauth/authorize`,
|
|
1575
|
+
tokenURL: `${options.baseUrl}/oauth/token`,
|
|
1576
|
+
profileURL: `${options.baseUrl}/api/v4/user`
|
|
1559
1577
|
},
|
|
1560
1578
|
(accessToken, refreshToken, params, fullProfile, done) => {
|
|
1561
1579
|
done(
|