diff --git a/policies/authorization_grant/authorization_grant.rego b/policies/authorization_grant/authorization_grant.rego index 72fa7ee8b..e999ebb70 100644 --- a/policies/authorization_grant/authorization_grant.rego +++ b/policies/authorization_grant/authorization_grant.rego @@ -67,11 +67,32 @@ allowed_scope(scope) if { regex.match(`^urn:matrix:org.matrix.msc2967.client:device:[A-Za-z0-9._~!$&'()*+,;=:@/-]{10,}$`, scope) } +allowed_scope(scope) if { + # Grant access to the C-S API only if there is a user + interactive_grant_type(input.grant_type) + regex.match(`^urn:matrix:client:device:[A-Za-z0-9._~!$&'()*+,;=:@/-]{10,}$`, scope) +} + +allowed_scope("urn:matrix:client:api:*") if { + # Grant access to the C-S API only if there is a user + interactive_grant_type(input.grant_type) +} + allowed_scope("urn:matrix:org.matrix.msc2967.client:api:*") if { # Grant access to the C-S API only if there is a user interactive_grant_type(input.grant_type) } +uses_unstable_scopes if { + scope_list := split(input.scope, " ") + count({scope | some scope in scope_list; startswith(scope, "urn:matrix:org.matrix.msc2967.client:")}) > 0 +} + +uses_stable_scopes if { + scope_list := split(input.scope, " ") + count({scope | some scope in scope_list; startswith(scope, "urn:matrix:client:")}) > 0 +} + # METADATA # entrypoint: true violation contains {"msg": msg} if { @@ -85,6 +106,16 @@ violation contains {"msg": "only one device scope is allowed at a time"} if { count({scope | some scope in scope_list; startswith(scope, "urn:matrix:org.matrix.msc2967.client:device:")}) > 1 } +violation contains {"msg": "only one device scope is allowed at a time"} if { + scope_list := split(input.scope, " ") + count({scope | some scope in scope_list; startswith(scope, "urn:matrix:client:device:")}) > 1 +} + +violation contains {"msg": "request cannot mix unstable and stable scopes"} if { + uses_stable_scopes + uses_unstable_scopes +} + violation contains {"msg": sprintf( "Requester [%s] isn't allowed to do this action", [common.format_requester(input.requester)], diff --git a/policies/authorization_grant/authorization_grant_test.rego b/policies/authorization_grant/authorization_grant_test.rego index 3594bfac2..fdf097da2 100644 --- a/policies/authorization_grant/authorization_grant_test.rego +++ b/policies/authorization_grant/authorization_grant_test.rego @@ -35,7 +35,7 @@ test_standard_scopes if { with input.scope as "profile" } -test_matrix_scopes if { +test_matrix_unstable_scopes if { authorization_grant.allow with input.user as user with input.client as client with input.grant_type as "authorization_code" @@ -52,7 +52,24 @@ test_matrix_scopes if { with input.scope as "urn:matrix:org.matrix.msc2967.client:api:*" } -test_device_scopes if { +test_matrix_stable_scopes if { + authorization_grant.allow with input.user as user + with input.client as client + with input.grant_type as "authorization_code" + with input.scope as "urn:matrix:client:api:*" + + authorization_grant.allow with input.user as user + with input.client as client + with input.grant_type as "urn:ietf:params:oauth:grant-type:device_code" + with input.scope as "urn:matrix:client:api:*" + + not authorization_grant.allow with input.user as user + with input.client as client + with input.grant_type as "client_credentials" + with input.scope as "urn:matrix:client:api:*" +} + +test_unstable_device_scopes if { authorization_grant.allow with input.user as user with input.client as client with input.grant_type as "authorization_code" @@ -87,6 +104,58 @@ test_device_scopes if { with input.scope as "urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01" } +test_stable_device_scopes if { + authorization_grant.allow with input.user as user + with input.client as client + with input.grant_type as "authorization_code" + with input.scope as "urn:matrix:client:device:AAbbCCdd01" + + authorization_grant.allow with input.user as user + with input.client as client + with input.grant_type as "authorization_code" + with input.scope as "urn:matrix:client:device:AAbbCCdd01-asdasdsa1-2313" + + # Too short + not authorization_grant.allow with input.user as user + with input.client as client + with input.grant_type as "authorization_code" + with input.scope as "urn:matrix:client:device:abcd" + + # Multiple device scope + not authorization_grant.allow with input.user as user + with input.client as client + with input.grant_type as "authorization_code" + with input.scope as "urn:matrix:client:device:AAbbCCdd01 urn:matrix:client:device:AAbbCCdd02" + + # Allowed with the device code grant + authorization_grant.allow with input.user as user + with input.client as client + with input.grant_type as "urn:ietf:params:oauth:grant-type:device_code" + with input.scope as "urn:matrix:client:device:AAbbCCdd01" + + # Not authorization_grant.allowed for the client credentials grant + not authorization_grant.allow with input.client as client + with input.grant_type as "client_credentials" + with input.scope as "urn:matrix:client:device:AAbbCCdd01" +} + +test_mix_stable_and_unstable_scopes if { + not authorization_grant.allow with input.user as user + with input.client as client + with input.grant_type as "authorization_code" + with input.scope as "urn:matrix:org.matrix.msc2967.client:api:* urn:matrix:client:device:AAbbCCdd01" + + not authorization_grant.allow with input.user as user + with input.client as client + with input.grant_type as "authorization_code" + with input.scope as "urn:matrix:client:api:* urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01" + + not authorization_grant.allow with input.user as user + with input.client as client + with input.grant_type as "authorization_code" + with input.scope as "urn:matrix:client:api:* urn:matrix:org.matrix.msc2967.client:api:*" +} + test_synapse_admin_scopes if { some grant_type in ["authorization_code", "urn:ietf:params:oauth:grant-type:device_code"]