feat: add sqlreports and fixing up

Signed-off-by: benjdlambert <ben@blam.sh>

Signed-off-by: benjdlambert <ben@blam.sh>
This commit is contained in:
benjdlambert
2025-07-07 14:02:02 +02:00
parent bf372ab53f
commit 1122bb29ac
5 changed files with 82 additions and 19 deletions
+53
View File
@@ -5,6 +5,59 @@
> [!WARNING]
> Failed to migrate down from '20220321100910_timestamptz_again.js'
## Table `oauth_authorization_sessions`
| Column | Type | Nullable | Max Length | Default |
| ----------------------- | -------------------------- | -------- | ---------- | ----------------- |
| `client_id` | `character varying` | false | 255 | - |
| `code_challenge` | `character varying` | true | 255 | - |
| `code_challenge_method` | `character varying` | true | 255 | - |
| `expires_at` | `timestamp with time zone` | false | - | - |
| `id` | `character varying` | false | 255 | - |
| `nonce` | `character varying` | true | 255 | - |
| `redirect_uri` | `text` | false | - | - |
| `response_type` | `character varying` | false | 255 | - |
| `scope` | `text` | true | - | - |
| `state` | `character varying` | true | 255 | - |
| `status` | `text` | true | - | `'pending'::text` |
| `user_entity_ref` | `character varying` | true | 255 | - |
### Indices
- `oauth_authorization_sessions_client_id_user_entity_ref_index` (`client_id`, `user_entity_ref`)
- `oauth_authorization_sessions_pkey` (`id`) unique primary
- `oauth_authorization_sessions_status_expires_at_index` (`status`, `expires_at`)
## Table `oidc_authorization_codes`
| Column | Type | Nullable | Max Length | Default |
| ------------ | -------------------------- | -------- | ---------- | ------- |
| `code` | `character varying` | false | 255 | - |
| `expires_at` | `timestamp with time zone` | false | - | - |
| `session_id` | `character varying` | false | 255 | - |
| `used` | `boolean` | true | - | `false` |
### Indices
- `oidc_authorization_codes_pkey` (`code`) unique primary
## Table `oidc_clients`
| Column | Type | Nullable | Max Length | Default |
| ---------------- | ------------------- | -------- | ---------- | ------- |
| `client_id` | `character varying` | false | 255 | - |
| `client_name` | `character varying` | false | 255 | - |
| `client_secret` | `character varying` | false | 255 | - |
| `grant_types` | `text` | false | - | - |
| `metadata` | `text` | true | - | - |
| `redirect_uris` | `text` | false | - | - |
| `response_types` | `text` | false | - | - |
| `scope` | `text` | true | - | - |
### Indices
- `oidc_clients_pkey` (`client_id`) unique primary
## Table `sessions`
| Column | Type | Nullable | Max Length | Default |
+3
View File
@@ -66,6 +66,7 @@ export const authPlugin = createBackendPlugin({
database: coreServices.database,
discovery: coreServices.discovery,
auth: coreServices.auth,
httpAuth: coreServices.httpAuth,
catalog: catalogServiceRef,
},
async init({
@@ -75,6 +76,7 @@ export const authPlugin = createBackendPlugin({
database,
discovery,
auth,
httpAuth,
catalog,
}) {
const router = await createRouter({
@@ -86,6 +88,7 @@ export const authPlugin = createBackendPlugin({
catalog,
providerFactories: Object.fromEntries(providers),
ownershipResolver,
httpAuth,
});
httpRouter.addAuthPolicy({
path: '/',
@@ -24,7 +24,6 @@ import {
startTestBackend,
TestDatabases,
TestDatabaseId,
mockCredentials,
} from '@backstage/backend-test-utils';
import request from 'supertest';
import crypto from 'crypto';
@@ -68,6 +67,7 @@ describe('OidcRouter', () => {
} as unknown as jest.Mocked<TokenIssuer>;
const mockAuth = mockServices.auth.mock();
const mockHttpAuth = mockServices.httpAuth.mock();
const oidcService = OidcService.create({
auth: mockAuth,
@@ -85,14 +85,13 @@ describe('OidcRouter', () => {
logger: mockServices.logger.mock(),
userInfo: userInfoDatabase,
oidc: oidcDatabase,
httpAuth: mockServices.httpAuth({
defaultCredentials: mockCredentials.user(),
}),
httpAuth: mockHttpAuth,
});
return {
router: oidcRouter,
mocks: {
httpAuth: mockHttpAuth,
auth: mockAuth,
oidc: oidcDatabase,
userInfo: userInfoDatabase,
@@ -138,7 +137,6 @@ describe('OidcRouter', () => {
],
});
auth.authenticate.mockResolvedValueOnce({} as any);
auth.isPrincipal.mockReturnValueOnce(true);
const response = await request(server)
@@ -194,7 +192,6 @@ describe('OidcRouter', () => {
],
});
auth.authenticate.mockResolvedValueOnce({} as any);
auth.isPrincipal.mockReturnValueOnce(true);
const response = await request(server)
@@ -361,9 +358,9 @@ describe('OidcRouter', () => {
});
});
it('should approve consent request', async () => {
it('should approve authorization session', async () => {
const {
mocks: { auth, service },
mocks: { auth, service, httpAuth },
router,
} = await createRouter(databaseId);
@@ -403,6 +400,14 @@ describe('OidcRouter', () => {
],
});
httpAuth.credentials.mockResolvedValueOnce({
principal: {
type: 'user',
userEntityRef: 'user:default/test-user',
},
$$type: '@backstage/BackstageCredentials',
});
auth.isPrincipal.mockReturnValueOnce(true);
const response = await request(server)
@@ -474,17 +479,18 @@ describe('OidcRouter', () => {
describe('token exchange', () => {
it('should exchange authorization code for tokens', async () => {
const {
mocks: { auth, service, tokenIssuer },
mocks: { auth, service, tokenIssuer, httpAuth },
router,
} = await createRouter(databaseId);
auth.authenticate.mockResolvedValueOnce({
httpAuth.credentials.mockResolvedValueOnce({
principal: {
type: 'user',
userEntityRef: 'user:default/test-user',
},
$$type: '@backstage/BackstageCredentials',
});
auth.isPrincipal.mockReturnValueOnce(true);
tokenIssuer.issueToken.mockResolvedValue({
@@ -565,7 +571,7 @@ describe('OidcRouter', () => {
it('should exchange authorization code for tokens with PKCE', async () => {
const {
mocks: { auth, service, tokenIssuer },
mocks: { auth, service, tokenIssuer, httpAuth },
router,
} = await createRouter(databaseId);
@@ -573,13 +579,14 @@ describe('OidcRouter', () => {
token: 'mock-access-token-pkce',
});
auth.authenticate.mockResolvedValueOnce({
httpAuth.credentials.mockResolvedValueOnce({
principal: {
type: 'user',
userEntityRef: 'user:default/test-user-pkce',
},
$$type: '@backstage/BackstageCredentials',
});
auth.isPrincipal.mockReturnValueOnce(true);
const client = await service.registerClient({
@@ -656,24 +663,25 @@ describe('OidcRouter', () => {
expect(tokenIssuer.issueToken).toHaveBeenCalledWith({
claims: {
sub: MOCK_USER_ENTITY_REF,
sub: 'user:default/test-user-pkce',
},
});
});
it('should reject token exchange with invalid client credentials', async () => {
const {
mocks: { auth, service },
mocks: { auth, service, httpAuth },
router,
} = await createRouter(databaseId);
auth.authenticate.mockResolvedValueOnce({
httpAuth.credentials.mockResolvedValueOnce({
principal: {
type: 'user',
userEntityRef: 'user:default/test-user',
},
$$type: '@backstage/BackstageCredentials',
});
auth.isPrincipal.mockReturnValueOnce(true);
const client = await service.registerClient({
@@ -789,7 +797,7 @@ describe('OidcRouter', () => {
it('should exchange authorization code for tokens with PKCE S256', async () => {
const {
mocks: { auth, service, tokenIssuer },
mocks: { auth, service, tokenIssuer, httpAuth },
router,
} = await createRouter(databaseId);
@@ -797,13 +805,14 @@ describe('OidcRouter', () => {
token: 'mock-access-token-s256',
});
auth.authenticate.mockResolvedValueOnce({
httpAuth.credentials.mockResolvedValueOnce({
principal: {
type: 'user',
userEntityRef: 'user:default/test-user-s256',
},
$$type: '@backstage/BackstageCredentials',
});
auth.isPrincipal.mockReturnValueOnce(true);
const client = await service.registerClient({
@@ -211,7 +211,6 @@ export class OidcRouter {
redirectUrl: result.redirectUrl,
});
} catch (error) {
console.log(error);
this.logger.error(
`Failed to approve authorization session: ${
isError(error) ? error.message : 'Unknown error'
@@ -28,7 +28,6 @@ import {
import { AuthDatabase } from '../database/AuthDatabase';
import { OidcDatabase } from '../database/OidcDatabase';
import { UserInfoDatabase } from '../database/UserInfoDatabase';
import { InputError, AuthenticationError } from '@backstage/errors';
import crypto from 'crypto';
import { AnyJWK, TokenIssuer } from '../identity/types';