1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-08-07 17:03:01 +03:00

Allow more characters in device IDs

This commit is contained in:
Quentin Gliech
2024-05-02 16:52:24 +02:00
parent 4dfbc4b509
commit 6db50f098d
5 changed files with 38 additions and 16 deletions

View File

@@ -70,13 +70,35 @@ impl Device {
} }
} }
const fn valid_device_chars(c: char) -> bool {
// This matches the regex in the policy
c.is_ascii_alphanumeric()
|| c == '.'
|| c == '_'
|| c == '~'
|| c == '!'
|| c == '$'
|| c == '&'
|| c == '\''
|| c == '('
|| c == ')'
|| c == '*'
|| c == '+'
|| c == ','
|| c == ';'
|| c == '='
|| c == ':'
|| c == '@'
|| c == '/'
|| c == '-'
}
impl TryFrom<String> for Device { impl TryFrom<String> for Device {
type Error = InvalidDeviceID; type Error = InvalidDeviceID;
/// Create a [`Device`] out of an ID, validating the ID has the right shape /// Create a [`Device`] out of an ID, validating the ID has the right shape
fn try_from(id: String) -> Result<Self, Self::Error> { fn try_from(id: String) -> Result<Self, Self::Error> {
// This matches the regex in the policy if !id.chars().all(valid_device_chars) {
if !id.chars().all(|c| c.is_ascii_alphanumeric() || c == '-') {
return Err(InvalidDeviceID::InvalidCharacters); return Err(InvalidDeviceID::InvalidCharacters);
} }

View File

@@ -14,7 +14,7 @@ import { Route as rootRoute } from './routes/__root'
import { Route as ResetCrossSigningImport } from './routes/reset-cross-signing' import { Route as ResetCrossSigningImport } from './routes/reset-cross-signing'
import { Route as AccountImport } from './routes/_account' import { Route as AccountImport } from './routes/_account'
import { Route as AccountIndexImport } from './routes/_account.index' import { Route as AccountIndexImport } from './routes/_account.index'
import { Route as DevicesIdImport } from './routes/devices.$id' import { Route as DevicesSplatImport } from './routes/devices.$'
import { Route as ClientsIdImport } from './routes/clients.$id' import { Route as ClientsIdImport } from './routes/clients.$id'
import { Route as AccountSessionsIndexImport } from './routes/_account.sessions.index' import { Route as AccountSessionsIndexImport } from './routes/_account.sessions.index'
import { Route as EmailsIdVerifyImport } from './routes/emails.$id.verify' import { Route as EmailsIdVerifyImport } from './routes/emails.$id.verify'
@@ -38,8 +38,8 @@ const AccountIndexRoute = AccountIndexImport.update({
getParentRoute: () => AccountRoute, getParentRoute: () => AccountRoute,
} as any) } as any)
const DevicesIdRoute = DevicesIdImport.update({ const DevicesSplatRoute = DevicesSplatImport.update({
path: '/devices/$id', path: '/devices/$',
getParentRoute: () => rootRoute, getParentRoute: () => rootRoute,
} as any) } as any)
@@ -84,8 +84,8 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof ClientsIdImport preLoaderRoute: typeof ClientsIdImport
parentRoute: typeof rootRoute parentRoute: typeof rootRoute
} }
'/devices/$id': { '/devices/$': {
preLoaderRoute: typeof DevicesIdImport preLoaderRoute: typeof DevicesSplatImport
parentRoute: typeof rootRoute parentRoute: typeof rootRoute
} }
'/_account/': { '/_account/': {
@@ -122,7 +122,7 @@ export const routeTree = rootRoute.addChildren([
]), ]),
ResetCrossSigningRoute, ResetCrossSigningRoute,
ClientsIdRoute, ClientsIdRoute,
DevicesIdRoute, DevicesSplatRoute,
EmailsIdVerifyRoute, EmailsIdVerifyRoute,
]) ])

View File

@@ -71,8 +71,8 @@ export const Route = createRootRouteWithContext<{
case "org.matrix.session_view": case "org.matrix.session_view":
if (search.device_id) if (search.device_id)
throw redirect({ throw redirect({
to: "/devices/$id", to: "/devices/$",
params: { id: search.device_id }, params: { _splat: search.device_id },
}); });
throw redirect({ to: "/sessions", search: { last: PAGE_SIZE } }); throw redirect({ to: "/sessions", search: { last: PAGE_SIZE } });
@@ -80,8 +80,8 @@ export const Route = createRootRouteWithContext<{
case "org.matrix.session_end": case "org.matrix.session_end":
if (search.device_id) if (search.device_id)
throw redirect({ throw redirect({
to: "/devices/$id", to: "/devices/$",
params: { id: search.device_id }, params: { _splat: search.device_id },
}); });
throw redirect({ to: "/sessions", search: { last: PAGE_SIZE } }); throw redirect({ to: "/sessions", search: { last: PAGE_SIZE } });

View File

@@ -42,7 +42,7 @@ const QUERY = graphql(/* GraphQL */ `
} }
`); `);
export const Route = createFileRoute("/devices/$id")({ export const Route = createFileRoute("/devices/$")({
async loader({ context, params, abortController: { signal } }) { async loader({ context, params, abortController: { signal } }) {
const viewer = await context.client.query( const viewer = await context.client.query(
CURRENT_VIEWER_QUERY, CURRENT_VIEWER_QUERY,
@@ -57,7 +57,7 @@ export const Route = createFileRoute("/devices/$id")({
const result = await context.client.query( const result = await context.client.query(
QUERY, QUERY,
{ {
deviceId: params.id, deviceId: params._splat,
userId: viewer.data.viewer.id, userId: viewer.data.viewer.id,
}, },
{ fetchOptions: { signal } }, { fetchOptions: { signal } },
@@ -78,7 +78,7 @@ export const Route = createFileRoute("/devices/$id")({
function NotFound(): React.ReactElement { function NotFound(): React.ReactElement {
const { t } = useTranslation(); const { t } = useTranslation();
const { id: deviceId } = Route.useParams(); const { _splat: deviceId } = Route.useParams();
return ( return (
<Layout> <Layout>
<Alert <Alert

View File

@@ -62,7 +62,7 @@ allowed_scope("urn:mas:admin") {
allowed_scope(scope) { allowed_scope(scope) {
# Grant access to the C-S API only if there is a user # Grant access to the C-S API only if there is a user
interactive_grant_type(input.grant_type) interactive_grant_type(input.grant_type)
regex.match("urn:matrix:org.matrix.msc2967.client:device:[A-Za-z0-9-]{10,}", scope) regex.match("^urn:matrix:org.matrix.msc2967.client:device:[A-Za-z0-9._~!$&'()*+,;=:@/-]{10,}$", scope)
} }
allowed_scope("urn:matrix:org.matrix.msc2967.client:api:*") { allowed_scope("urn:matrix:org.matrix.msc2967.client:api:*") {