diff --git a/src/app/hooks/useAuthMetadata.test.ts b/src/app/hooks/useAuthMetadata.test.ts new file mode 100644 index 0000000000..95bf05d0cd --- /dev/null +++ b/src/app/hooks/useAuthMetadata.test.ts @@ -0,0 +1,53 @@ +import { describe, expect, it } from 'vitest'; +import type { ValidatedAuthMetadata } from '$types/matrix-sdk'; +import type { Session } from '$state/sessions'; +import { getSessionAuthMetadata } from './useAuthMetadata'; + +const metadata = { + issuer: 'https://auth.example.org/', + authorization_endpoint: 'https://auth.example.org/authorize', + token_endpoint: 'https://auth.example.org/token', + registration_endpoint: 'https://auth.example.org/register', + response_types_supported: ['code'], + response_modes_supported: ['query'], + grant_types_supported: ['authorization_code', 'refresh_token'], + code_challenge_methods_supported: ['S256'], + account_management_uri: 'https://auth.example.org/account', +} as ValidatedAuthMetadata; + +const session: Session = { + baseUrl: 'https://matrix.example.org', + userId: '@alice:example.org', + deviceId: 'DEVICE', + accessToken: 'access-token', +}; + +describe('getSessionAuthMetadata', () => { + it('does not expose delegated account management to non-OIDC sessions', () => { + expect(getSessionAuthMetadata(metadata, session)).toBeUndefined(); + }); + + it('exposes delegated account management to OIDC sessions', () => { + const oidcSession: Session = { + ...session, + oidc: { + issuer: metadata.issuer, + clientId: 'client-id', + }, + }; + + expect(getSessionAuthMetadata(metadata, oidcSession)).toBe(metadata); + }); + + it('does not invent metadata when an OIDC session has no discovered metadata', () => { + const oidcSession: Session = { + ...session, + oidc: { + issuer: metadata.issuer, + clientId: 'client-id', + }, + }; + + expect(getSessionAuthMetadata(undefined, oidcSession)).toBeUndefined(); + }); +}); diff --git a/src/app/hooks/useAuthMetadata.ts b/src/app/hooks/useAuthMetadata.ts index 3d434beb93..cc41f0a26a 100644 --- a/src/app/hooks/useAuthMetadata.ts +++ b/src/app/hooks/useAuthMetadata.ts @@ -1,10 +1,16 @@ import type { ValidatedAuthMetadata } from '$types/matrix-sdk'; +import type { Session } from '$state/sessions'; import { createContext, useContext } from 'react'; const AuthMetadataContext = createContext(undefined); export const AuthMetadataProvider = AuthMetadataContext.Provider; +export const getSessionAuthMetadata = ( + metadata: ValidatedAuthMetadata | undefined, + session: Session | undefined +): ValidatedAuthMetadata | undefined => (session?.oidc ? metadata : undefined); + export const useAuthMetadata = (): ValidatedAuthMetadata | undefined => { const metadata = useContext(AuthMetadataContext); diff --git a/src/app/pages/client/ClientRoot.tsx b/src/app/pages/client/ClientRoot.tsx index f86e518b28..5d4ea38a81 100644 --- a/src/app/pages/client/ClientRoot.tsx +++ b/src/app/pages/client/ClientRoot.tsx @@ -35,7 +35,7 @@ import { MatrixClientProvider } from '$hooks/useMatrixClient'; import { AsyncStatus, useAsyncCallback } from '$hooks/useAsyncCallback'; import { useSyncState } from '$hooks/useSyncState'; import { stopPropagation } from '$utils/keyboard'; -import { AuthMetadataProvider } from '$hooks/useAuthMetadata'; +import { AuthMetadataProvider, getSessionAuthMetadata } from '$hooks/useAuthMetadata'; import { sessionsAtom, activeSessionIdAtom, @@ -480,7 +480,9 @@ export function ClientRoot({ children }: ClientRootProps) { {(serverConfigs) => ( - + {children}