switch omitIdentityTokenOwnershipClaim to true
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
---
|
||||
'@backstage/plugin-auth-backend': minor
|
||||
---
|
||||
|
||||
**BREAKING**: The setting `auth.omitIdentityTokenOwnershipClaim` has had its default value switched to `true`.
|
||||
|
||||
With this setting Backstage user tokens issued by the `auth` backend will no longer contain an `ent` claim - the one with the user's ownership entity refs. This means that tokens issued in large orgs no longer risk hitting HTTP header size limits.
|
||||
|
||||
To get ownership info for the current user, code should use the `userInfo` core service. In practice code will typically already conform to this since the `ent` claim has not been readily exposed in any other way for quite some time. But code which explicitly decodes Backstage tokens - which is strongly discouraged - may be affected by this change.
|
||||
|
||||
The setting will remain for some time to allow it to be set back to `false` if need be, but it will be removed entirely in a future release.
|
||||
@@ -399,50 +399,6 @@ async signInResolver({ profile }, ctx) {
|
||||
}
|
||||
```
|
||||
|
||||
## Reducing the size of issued tokens
|
||||
|
||||
By default the auth backend will issue user identity tokens that include the
|
||||
ownership references of the user in the `ent` claim of the JWT payload. This is
|
||||
done to make it easier and more efficient for consumers of the token to resolve
|
||||
ownership of the user. However, depending on the shape of your organization and
|
||||
how you resolve ownership claims, these tokens can grow quite large.
|
||||
|
||||
To address this, the auth backend now supports the configuration flag
|
||||
`auth.omitIdentityTokenOwnershipClaim` that causes the `ent` claim to be omitted
|
||||
from the token. This can be set to `true` in the `app-config.yaml` file.
|
||||
|
||||
```yaml title="in app-config.yaml"
|
||||
auth:
|
||||
omitIdentityTokenOwnershipClaim: true
|
||||
```
|
||||
|
||||
When this flag is set, the `ent` claim will no longer be present in the token,
|
||||
and consumers of the token will need to call the `/v1/userinfo` endpoint on the
|
||||
auth backend to fetch the ownership references of the user. However, there's usually no
|
||||
action required for consumers. Clients will still receive the full set
|
||||
of claims during authentication, and any plugin backends will already need to
|
||||
use the
|
||||
[`UserInfoService`](../backend-system/core-services/user-info.md) to
|
||||
access the ownership references from user credentials, which already calls the
|
||||
user info endpoint if necessary.
|
||||
|
||||
When enabling this flag, it is important that any custom sign-in resolvers directly return the result of the sign-in method. For example, the following would not work:
|
||||
|
||||
```ts
|
||||
const { token } = await ctx.issueToken({
|
||||
claims: { sub: entityRef, ent: [entityRef] },
|
||||
});
|
||||
return { token }; // WARNING: This will not work
|
||||
```
|
||||
|
||||
Instead, the sign-in resolver should directly return the result:
|
||||
|
||||
```ts
|
||||
return ctx.issueToken({
|
||||
claims: { sub: entityRef, ent: [entityRef] },
|
||||
});
|
||||
```
|
||||
|
||||
##### Using the `dangerouslyAllowSignInWithoutUserInCatalog` Option
|
||||
|
||||
Another way to bypass this requirement is to enable the `dangerouslyAllowSignInWithoutUserInCatalog` option for resolvers.
|
||||
|
||||
Vendored
+9
-3
@@ -45,10 +45,16 @@ export interface Config {
|
||||
|
||||
/**
|
||||
* Whether to omit the entity ownership references (`ent`) claim from the
|
||||
* identity token. If this is enabled the `ent` claim will only be available
|
||||
* via the user info endpoint and the `UserInfoService`.
|
||||
* identity token.
|
||||
*
|
||||
* Defaults to `false`.
|
||||
* If this is disabled an `ent` claim will be included in the token
|
||||
* containing all of the user's ownership refs as returned by the sign in
|
||||
* resolver. This can in extreme cases lead to tokens that risk hitting HTTP
|
||||
* header size limits. Setting it to `false` is therefore discouraged, and
|
||||
* is only provided for backward compatibility reasons.
|
||||
*
|
||||
* Defaults to `true`, which means that the `ent` claim instead is available
|
||||
* via the user info endpoint and the `UserInfoService`.
|
||||
*/
|
||||
omitIdentityTokenOwnershipClaim?: boolean;
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ describe('authPlugin', () => {
|
||||
const token = refreshRes.body.backstageIdentity.token;
|
||||
const decoded = JSON.parse(atob(token.split('.')[1]));
|
||||
expect(decoded.sub).toEqual(expectedIdentity.userEntityRef);
|
||||
expect(decoded.ent).toEqual(expectedIdentity.ownershipEntityRefs);
|
||||
expect('ent' in decoded).toBeFalsy();
|
||||
|
||||
const userInfoRes = await request(server)
|
||||
.get('/api/auth/v1/userinfo')
|
||||
@@ -115,7 +115,7 @@ describe('authPlugin', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should omit ownership claims from the token when the config is set', async () => {
|
||||
it('should include ownership claims in the token when the config is set to false', async () => {
|
||||
const { server } = await startTestBackend({
|
||||
features: [
|
||||
authPlugin,
|
||||
@@ -127,7 +127,7 @@ describe('authPlugin', () => {
|
||||
baseUrl: 'http://localhost',
|
||||
},
|
||||
auth: {
|
||||
omitIdentityTokenOwnershipClaim: true,
|
||||
omitIdentityTokenOwnershipClaim: false,
|
||||
...mockProvidersConfig,
|
||||
},
|
||||
},
|
||||
@@ -149,7 +149,7 @@ describe('authPlugin', () => {
|
||||
const token = refreshRes.body.backstageIdentity.token;
|
||||
const decoded = JSON.parse(atob(token.split('.')[1]));
|
||||
expect(decoded.sub).toEqual(expectedIdentity.userEntityRef);
|
||||
expect(decoded.ent).toBeUndefined();
|
||||
expect(decoded.ent).toEqual(expectedIdentity.ownershipEntityRefs);
|
||||
|
||||
const userInfoRes = await request(server)
|
||||
.get('/api/auth/v1/userinfo')
|
||||
|
||||
@@ -87,11 +87,10 @@ export async function createRouter(
|
||||
database,
|
||||
});
|
||||
|
||||
const omitClaimsFromToken = config.getOptionalBoolean(
|
||||
'auth.omitIdentityTokenOwnershipClaim',
|
||||
)
|
||||
? ['ent']
|
||||
: [];
|
||||
const omitClaimsFromToken =
|
||||
config.getOptionalBoolean('auth.omitIdentityTokenOwnershipClaim') ?? true
|
||||
? ['ent']
|
||||
: [];
|
||||
|
||||
let tokenIssuer: TokenIssuer;
|
||||
if (keyStore instanceof StaticKeyStore) {
|
||||
|
||||
Reference in New Issue
Block a user