diff --git a/crates/handlers/src/oauth2/device/authorize.rs b/crates/handlers/src/oauth2/device/authorize.rs index 75a6c6fbb..05d84a5c9 100644 --- a/crates/handlers/src/oauth2/device/authorize.rs +++ b/crates/handlers/src/oauth2/device/authorize.rs @@ -26,7 +26,7 @@ use mas_router::UrlBuilder; use mas_storage::{oauth2::OAuth2DeviceCodeGrantParams, BoxClock, BoxRepository, BoxRng}; use oauth2_types::{ errors::{ClientError, ClientErrorCode}, - requests::{DeviceAuthorizationRequest, DeviceAuthorizationResponse}, + requests::{DeviceAuthorizationRequest, DeviceAuthorizationResponse, GrantType}, scope::ScopeToken, }; use rand::distributions::{Alphanumeric, DistString}; @@ -111,7 +111,9 @@ pub(crate) async fn post( .verify(&http_client_factory, &encrypter, method, &client) .await?; - // TODO: check if the client can use the device code grant type + if !client.grant_types.contains(&GrantType::DeviceCode) { + return Err(RouteError::ClientNotAllowed); + } let scope = client_authorization .form diff --git a/crates/handlers/src/oauth2/token.rs b/crates/handlers/src/oauth2/token.rs index fc9b68caf..6af48b68d 100644 --- a/crates/handlers/src/oauth2/token.rs +++ b/crates/handlers/src/oauth2/token.rs @@ -625,10 +625,10 @@ async fn device_code_grant( site_config: &SiteConfig, mut repo: BoxRepository, ) -> Result<(AccessTokenResponse, BoxRepository), RouteError> { - // TODO: Check that the client is allowed to use this grant type - //if !client.grant_types.contains(&GrantType::DeviceCode) { - // return Err(RouteError::UnauthorizedClient); - //} + // Check that the client is allowed to use this grant type + if !client.grant_types.contains(&GrantType::DeviceCode) { + return Err(RouteError::UnauthorizedClient); + } let grant = repo .oauth2_device_code_grant() diff --git a/crates/storage-pg/.sqlx/query-9697ae6915c7e9268c82a4a2bf7a538515bb2be35c003f49e93641fb1d5ed8af.json b/crates/storage-pg/.sqlx/query-100c6cfa46133f3b196b00ccf8f33ba0bcb4bb1afc1985092dd8ec51b40f631a.json similarity index 76% rename from crates/storage-pg/.sqlx/query-9697ae6915c7e9268c82a4a2bf7a538515bb2be35c003f49e93641fb1d5ed8af.json rename to crates/storage-pg/.sqlx/query-100c6cfa46133f3b196b00ccf8f33ba0bcb4bb1afc1985092dd8ec51b40f631a.json index 7e196ca70..f8e009a8d 100644 --- a/crates/storage-pg/.sqlx/query-9697ae6915c7e9268c82a4a2bf7a538515bb2be35c003f49e93641fb1d5ed8af.json +++ b/crates/storage-pg/.sqlx/query-100c6cfa46133f3b196b00ccf8f33ba0bcb4bb1afc1985092dd8ec51b40f631a.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT oauth2_client_id\n , encrypted_client_secret\n , application_type\n , redirect_uris\n , grant_type_authorization_code\n , grant_type_refresh_token\n , grant_type_client_credentials\n , contacts\n , client_name\n , logo_uri\n , client_uri\n , policy_uri\n , tos_uri\n , jwks_uri\n , jwks\n , id_token_signed_response_alg\n , userinfo_signed_response_alg\n , token_endpoint_auth_method\n , token_endpoint_auth_signing_alg\n , initiate_login_uri\n FROM oauth2_clients c\n\n WHERE oauth2_client_id = $1\n ", + "query": "\n SELECT oauth2_client_id\n , encrypted_client_secret\n , application_type\n , redirect_uris\n , grant_type_authorization_code\n , grant_type_refresh_token\n , grant_type_client_credentials\n , grant_type_device_code\n , contacts\n , client_name\n , logo_uri\n , client_uri\n , policy_uri\n , tos_uri\n , jwks_uri\n , jwks\n , id_token_signed_response_alg\n , userinfo_signed_response_alg\n , token_endpoint_auth_method\n , token_endpoint_auth_signing_alg\n , initiate_login_uri\n FROM oauth2_clients c\n\n WHERE oauth2_client_id = $1\n ", "describe": { "columns": [ { @@ -40,66 +40,71 @@ }, { "ordinal": 7, + "name": "grant_type_device_code", + "type_info": "Bool" + }, + { + "ordinal": 8, "name": "contacts", "type_info": "TextArray" }, { - "ordinal": 8, + "ordinal": 9, "name": "client_name", "type_info": "Text" }, { - "ordinal": 9, + "ordinal": 10, "name": "logo_uri", "type_info": "Text" }, { - "ordinal": 10, + "ordinal": 11, "name": "client_uri", "type_info": "Text" }, { - "ordinal": 11, + "ordinal": 12, "name": "policy_uri", "type_info": "Text" }, { - "ordinal": 12, + "ordinal": 13, "name": "tos_uri", "type_info": "Text" }, { - "ordinal": 13, + "ordinal": 14, "name": "jwks_uri", "type_info": "Text" }, { - "ordinal": 14, + "ordinal": 15, "name": "jwks", "type_info": "Jsonb" }, { - "ordinal": 15, + "ordinal": 16, "name": "id_token_signed_response_alg", "type_info": "Text" }, { - "ordinal": 16, + "ordinal": 17, "name": "userinfo_signed_response_alg", "type_info": "Text" }, { - "ordinal": 17, + "ordinal": 18, "name": "token_endpoint_auth_method", "type_info": "Text" }, { - "ordinal": 18, + "ordinal": 19, "name": "token_endpoint_auth_signing_alg", "type_info": "Text" }, { - "ordinal": 19, + "ordinal": 20, "name": "initiate_login_uri", "type_info": "Text" } @@ -118,6 +123,7 @@ false, false, false, + false, true, true, true, @@ -132,5 +138,5 @@ true ] }, - "hash": "9697ae6915c7e9268c82a4a2bf7a538515bb2be35c003f49e93641fb1d5ed8af" + "hash": "100c6cfa46133f3b196b00ccf8f33ba0bcb4bb1afc1985092dd8ec51b40f631a" } diff --git a/crates/storage-pg/.sqlx/query-2e1d7fb3f69d99dc5c879f43d92bc52f9abeb606393aff5440f948632d914708.json b/crates/storage-pg/.sqlx/query-2e1d7fb3f69d99dc5c879f43d92bc52f9abeb606393aff5440f948632d914708.json deleted file mode 100644 index db4f3e8a1..000000000 --- a/crates/storage-pg/.sqlx/query-2e1d7fb3f69d99dc5c879f43d92bc52f9abeb606393aff5440f948632d914708.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO oauth2_clients\n ( oauth2_client_id\n , encrypted_client_secret\n , redirect_uris\n , grant_type_authorization_code\n , grant_type_refresh_token\n , grant_type_client_credentials\n , token_endpoint_auth_method\n , jwks\n , jwks_uri\n , is_static\n )\n VALUES\n ($1, $2, $3, $4, $5, $6, $7, $8, $9, TRUE)\n ON CONFLICT (oauth2_client_id)\n DO\n UPDATE SET encrypted_client_secret = EXCLUDED.encrypted_client_secret\n , grant_type_authorization_code = EXCLUDED.grant_type_authorization_code\n , grant_type_refresh_token = EXCLUDED.grant_type_refresh_token\n , grant_type_client_credentials = EXCLUDED.grant_type_client_credentials\n , token_endpoint_auth_method = EXCLUDED.token_endpoint_auth_method\n , jwks = EXCLUDED.jwks\n , jwks_uri = EXCLUDED.jwks_uri\n , is_static = TRUE\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Uuid", - "Text", - "TextArray", - "Bool", - "Bool", - "Bool", - "Text", - "Jsonb", - "Text" - ] - }, - "nullable": [] - }, - "hash": "2e1d7fb3f69d99dc5c879f43d92bc52f9abeb606393aff5440f948632d914708" -} diff --git a/crates/storage-pg/.sqlx/query-61dc64c1980b5d1d2e2b52c8c55c91e1953595e413bedcec27eafbf87e42f1cd.json b/crates/storage-pg/.sqlx/query-61dc64c1980b5d1d2e2b52c8c55c91e1953595e413bedcec27eafbf87e42f1cd.json new file mode 100644 index 000000000..79e26fcdc --- /dev/null +++ b/crates/storage-pg/.sqlx/query-61dc64c1980b5d1d2e2b52c8c55c91e1953595e413bedcec27eafbf87e42f1cd.json @@ -0,0 +1,88 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT oauth2_device_code_grant_id\n , oauth2_client_id\n , scope\n , device_code\n , user_code\n , created_at\n , expires_at\n , fulfilled_at\n , rejected_at\n , exchanged_at\n , user_session_id\n , oauth2_session_id\n FROM \n oauth2_device_code_grant\n\n WHERE oauth2_device_code_grant_id = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "oauth2_device_code_grant_id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "oauth2_client_id", + "type_info": "Uuid" + }, + { + "ordinal": 2, + "name": "scope", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "device_code", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "user_code", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "created_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 6, + "name": "expires_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 7, + "name": "fulfilled_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 8, + "name": "rejected_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 9, + "name": "exchanged_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 10, + "name": "user_session_id", + "type_info": "Uuid" + }, + { + "ordinal": 11, + "name": "oauth2_session_id", + "type_info": "Uuid" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false, + true, + true, + true, + true, + true + ] + }, + "hash": "61dc64c1980b5d1d2e2b52c8c55c91e1953595e413bedcec27eafbf87e42f1cd" +} diff --git a/crates/storage-pg/.sqlx/query-6a72c38cb718ac09b61e0fadd9703e4b7a984c46185cceea4eceff4655f4e81f.json b/crates/storage-pg/.sqlx/query-6a72c38cb718ac09b61e0fadd9703e4b7a984c46185cceea4eceff4655f4e81f.json new file mode 100644 index 000000000..33b5e5dd5 --- /dev/null +++ b/crates/storage-pg/.sqlx/query-6a72c38cb718ac09b61e0fadd9703e4b7a984c46185cceea4eceff4655f4e81f.json @@ -0,0 +1,20 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO \"oauth2_device_code_grant\" \n ( oauth2_device_code_grant_id\n , oauth2_client_id\n , scope\n , device_code\n , user_code\n , created_at\n , expires_at\n )\n VALUES\n ($1, $2, $3, $4, $5, $6, $7)\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Uuid", + "Text", + "Text", + "Text", + "Timestamptz", + "Timestamptz" + ] + }, + "nullable": [] + }, + "hash": "6a72c38cb718ac09b61e0fadd9703e4b7a984c46185cceea4eceff4655f4e81f" +} diff --git a/crates/storage-pg/.sqlx/query-755f62d0a3a40acc90037371339a8459736fdd4bbffd932f7930d847f2c3ef5d.json b/crates/storage-pg/.sqlx/query-755f62d0a3a40acc90037371339a8459736fdd4bbffd932f7930d847f2c3ef5d.json new file mode 100644 index 000000000..3254f116c --- /dev/null +++ b/crates/storage-pg/.sqlx/query-755f62d0a3a40acc90037371339a8459736fdd4bbffd932f7930d847f2c3ef5d.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE oauth2_device_code_grant\n SET rejected_at = $1\n , user_session_id = $2\n WHERE oauth2_device_code_grant_id = $3\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Timestamptz", + "Uuid", + "Uuid" + ] + }, + "nullable": [] + }, + "hash": "755f62d0a3a40acc90037371339a8459736fdd4bbffd932f7930d847f2c3ef5d" +} diff --git a/crates/storage-pg/.sqlx/query-92c8eb526fcc5de6874eb0fab1d71fb1ed3dafe2bd1a49aa72e4f4862931c6c2.json b/crates/storage-pg/.sqlx/query-92c8eb526fcc5de6874eb0fab1d71fb1ed3dafe2bd1a49aa72e4f4862931c6c2.json new file mode 100644 index 000000000..34ac29db3 --- /dev/null +++ b/crates/storage-pg/.sqlx/query-92c8eb526fcc5de6874eb0fab1d71fb1ed3dafe2bd1a49aa72e4f4862931c6c2.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE oauth2_device_code_grant\n SET exchanged_at = $1\n , oauth2_session_id = $2\n WHERE oauth2_device_code_grant_id = $3\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Timestamptz", + "Uuid", + "Uuid" + ] + }, + "nullable": [] + }, + "hash": "92c8eb526fcc5de6874eb0fab1d71fb1ed3dafe2bd1a49aa72e4f4862931c6c2" +} diff --git a/crates/storage-pg/.sqlx/query-8cd9e33fb146fd528dbb169b6339d33703b6b719d5f28f1cf232bc81cac0da85.json b/crates/storage-pg/.sqlx/query-92fb511938dff21e5e0f7800c742b852b8c4468d1770c4cbc0b51611ce50e922.json similarity index 50% rename from crates/storage-pg/.sqlx/query-8cd9e33fb146fd528dbb169b6339d33703b6b719d5f28f1cf232bc81cac0da85.json rename to crates/storage-pg/.sqlx/query-92fb511938dff21e5e0f7800c742b852b8c4468d1770c4cbc0b51611ce50e922.json index f30f56804..2b33f6935 100644 --- a/crates/storage-pg/.sqlx/query-8cd9e33fb146fd528dbb169b6339d33703b6b719d5f28f1cf232bc81cac0da85.json +++ b/crates/storage-pg/.sqlx/query-92fb511938dff21e5e0f7800c742b852b8c4468d1770c4cbc0b51611ce50e922.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n INSERT INTO oauth2_clients\n ( oauth2_client_id\n , encrypted_client_secret\n , application_type\n , redirect_uris\n , grant_type_authorization_code\n , grant_type_refresh_token\n , grant_type_client_credentials\n , client_name\n , logo_uri\n , client_uri\n , policy_uri\n , tos_uri\n , jwks_uri\n , jwks\n , id_token_signed_response_alg\n , userinfo_signed_response_alg\n , token_endpoint_auth_method\n , token_endpoint_auth_signing_alg\n , initiate_login_uri\n , is_static\n )\n VALUES\n ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, FALSE)\n ", + "query": "\n INSERT INTO oauth2_clients\n ( oauth2_client_id\n , encrypted_client_secret\n , application_type\n , redirect_uris\n , grant_type_authorization_code\n , grant_type_refresh_token\n , grant_type_client_credentials\n , grant_type_device_code\n , client_name\n , logo_uri\n , client_uri\n , policy_uri\n , tos_uri\n , jwks_uri\n , jwks\n , id_token_signed_response_alg\n , userinfo_signed_response_alg\n , token_endpoint_auth_method\n , token_endpoint_auth_signing_alg\n , initiate_login_uri\n , is_static\n )\n VALUES\n ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, FALSE)\n ", "describe": { "columns": [], "parameters": { @@ -12,6 +12,7 @@ "Bool", "Bool", "Bool", + "Bool", "Text", "Text", "Text", @@ -28,5 +29,5 @@ }, "nullable": [] }, - "hash": "8cd9e33fb146fd528dbb169b6339d33703b6b719d5f28f1cf232bc81cac0da85" + "hash": "92fb511938dff21e5e0f7800c742b852b8c4468d1770c4cbc0b51611ce50e922" } diff --git a/crates/storage-pg/.sqlx/query-59a7b0eb03e45db5bee0aa1447fef2a3c061cf385ccf67acb237b94a0f25a074.json b/crates/storage-pg/.sqlx/query-9e6e639be74654bb5a9e6a978b7b07d6d59a22c876f24dd92eb43917259934fd.json similarity index 75% rename from crates/storage-pg/.sqlx/query-59a7b0eb03e45db5bee0aa1447fef2a3c061cf385ccf67acb237b94a0f25a074.json rename to crates/storage-pg/.sqlx/query-9e6e639be74654bb5a9e6a978b7b07d6d59a22c876f24dd92eb43917259934fd.json index ece26f145..4637bc31a 100644 --- a/crates/storage-pg/.sqlx/query-59a7b0eb03e45db5bee0aa1447fef2a3c061cf385ccf67acb237b94a0f25a074.json +++ b/crates/storage-pg/.sqlx/query-9e6e639be74654bb5a9e6a978b7b07d6d59a22c876f24dd92eb43917259934fd.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT oauth2_client_id\n , encrypted_client_secret\n , application_type\n , redirect_uris\n , grant_type_authorization_code\n , grant_type_refresh_token\n , grant_type_client_credentials\n , contacts\n , client_name\n , logo_uri\n , client_uri\n , policy_uri\n , tos_uri\n , jwks_uri\n , jwks\n , id_token_signed_response_alg\n , userinfo_signed_response_alg\n , token_endpoint_auth_method\n , token_endpoint_auth_signing_alg\n , initiate_login_uri\n FROM oauth2_clients c\n\n WHERE oauth2_client_id = ANY($1::uuid[])\n ", + "query": "\n SELECT oauth2_client_id\n , encrypted_client_secret\n , application_type\n , redirect_uris\n , grant_type_authorization_code\n , grant_type_refresh_token\n , grant_type_client_credentials\n , grant_type_device_code\n , contacts\n , client_name\n , logo_uri\n , client_uri\n , policy_uri\n , tos_uri\n , jwks_uri\n , jwks\n , id_token_signed_response_alg\n , userinfo_signed_response_alg\n , token_endpoint_auth_method\n , token_endpoint_auth_signing_alg\n , initiate_login_uri\n FROM oauth2_clients c\n\n WHERE oauth2_client_id = ANY($1::uuid[])\n ", "describe": { "columns": [ { @@ -40,66 +40,71 @@ }, { "ordinal": 7, + "name": "grant_type_device_code", + "type_info": "Bool" + }, + { + "ordinal": 8, "name": "contacts", "type_info": "TextArray" }, { - "ordinal": 8, + "ordinal": 9, "name": "client_name", "type_info": "Text" }, { - "ordinal": 9, + "ordinal": 10, "name": "logo_uri", "type_info": "Text" }, { - "ordinal": 10, + "ordinal": 11, "name": "client_uri", "type_info": "Text" }, { - "ordinal": 11, + "ordinal": 12, "name": "policy_uri", "type_info": "Text" }, { - "ordinal": 12, + "ordinal": 13, "name": "tos_uri", "type_info": "Text" }, { - "ordinal": 13, + "ordinal": 14, "name": "jwks_uri", "type_info": "Text" }, { - "ordinal": 14, + "ordinal": 15, "name": "jwks", "type_info": "Jsonb" }, { - "ordinal": 15, + "ordinal": 16, "name": "id_token_signed_response_alg", "type_info": "Text" }, { - "ordinal": 16, + "ordinal": 17, "name": "userinfo_signed_response_alg", "type_info": "Text" }, { - "ordinal": 17, + "ordinal": 18, "name": "token_endpoint_auth_method", "type_info": "Text" }, { - "ordinal": 18, + "ordinal": 19, "name": "token_endpoint_auth_signing_alg", "type_info": "Text" }, { - "ordinal": 19, + "ordinal": 20, "name": "initiate_login_uri", "type_info": "Text" } @@ -118,6 +123,7 @@ false, false, false, + false, true, true, true, @@ -132,5 +138,5 @@ true ] }, - "hash": "59a7b0eb03e45db5bee0aa1447fef2a3c061cf385ccf67acb237b94a0f25a074" + "hash": "9e6e639be74654bb5a9e6a978b7b07d6d59a22c876f24dd92eb43917259934fd" } diff --git a/crates/storage-pg/.sqlx/query-ef45f7ed060951ec7d881f2da2a9454eb32c4620cac1ea13c7186df513692fd6.json b/crates/storage-pg/.sqlx/query-a40531c4c2b0cbf8cd968f72dfbeed00df0e6a9689195ee8c4f83f8ccbe59748.json similarity index 76% rename from crates/storage-pg/.sqlx/query-ef45f7ed060951ec7d881f2da2a9454eb32c4620cac1ea13c7186df513692fd6.json rename to crates/storage-pg/.sqlx/query-a40531c4c2b0cbf8cd968f72dfbeed00df0e6a9689195ee8c4f83f8ccbe59748.json index 5297cf1c9..6fb10e8d8 100644 --- a/crates/storage-pg/.sqlx/query-ef45f7ed060951ec7d881f2da2a9454eb32c4620cac1ea13c7186df513692fd6.json +++ b/crates/storage-pg/.sqlx/query-a40531c4c2b0cbf8cd968f72dfbeed00df0e6a9689195ee8c4f83f8ccbe59748.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT oauth2_client_id\n , encrypted_client_secret\n , application_type\n , redirect_uris\n , grant_type_authorization_code\n , grant_type_refresh_token\n , grant_type_client_credentials\n , contacts\n , client_name\n , logo_uri\n , client_uri\n , policy_uri\n , tos_uri\n , jwks_uri\n , jwks\n , id_token_signed_response_alg\n , userinfo_signed_response_alg\n , token_endpoint_auth_method\n , token_endpoint_auth_signing_alg\n , initiate_login_uri\n FROM oauth2_clients c\n WHERE is_static = TRUE\n ", + "query": "\n SELECT oauth2_client_id\n , encrypted_client_secret\n , application_type\n , redirect_uris\n , grant_type_authorization_code\n , grant_type_refresh_token\n , grant_type_client_credentials\n , grant_type_device_code\n , contacts\n , client_name\n , logo_uri\n , client_uri\n , policy_uri\n , tos_uri\n , jwks_uri\n , jwks\n , id_token_signed_response_alg\n , userinfo_signed_response_alg\n , token_endpoint_auth_method\n , token_endpoint_auth_signing_alg\n , initiate_login_uri\n FROM oauth2_clients c\n WHERE is_static = TRUE\n ", "describe": { "columns": [ { @@ -40,66 +40,71 @@ }, { "ordinal": 7, + "name": "grant_type_device_code", + "type_info": "Bool" + }, + { + "ordinal": 8, "name": "contacts", "type_info": "TextArray" }, { - "ordinal": 8, + "ordinal": 9, "name": "client_name", "type_info": "Text" }, { - "ordinal": 9, + "ordinal": 10, "name": "logo_uri", "type_info": "Text" }, { - "ordinal": 10, + "ordinal": 11, "name": "client_uri", "type_info": "Text" }, { - "ordinal": 11, + "ordinal": 12, "name": "policy_uri", "type_info": "Text" }, { - "ordinal": 12, + "ordinal": 13, "name": "tos_uri", "type_info": "Text" }, { - "ordinal": 13, + "ordinal": 14, "name": "jwks_uri", "type_info": "Text" }, { - "ordinal": 14, + "ordinal": 15, "name": "jwks", "type_info": "Jsonb" }, { - "ordinal": 15, + "ordinal": 16, "name": "id_token_signed_response_alg", "type_info": "Text" }, { - "ordinal": 16, + "ordinal": 17, "name": "userinfo_signed_response_alg", "type_info": "Text" }, { - "ordinal": 17, + "ordinal": 18, "name": "token_endpoint_auth_method", "type_info": "Text" }, { - "ordinal": 18, + "ordinal": 19, "name": "token_endpoint_auth_signing_alg", "type_info": "Text" }, { - "ordinal": 19, + "ordinal": 20, "name": "initiate_login_uri", "type_info": "Text" } @@ -116,6 +121,7 @@ false, false, false, + false, true, true, true, @@ -130,5 +136,5 @@ true ] }, - "hash": "ef45f7ed060951ec7d881f2da2a9454eb32c4620cac1ea13c7186df513692fd6" + "hash": "a40531c4c2b0cbf8cd968f72dfbeed00df0e6a9689195ee8c4f83f8ccbe59748" } diff --git a/crates/storage-pg/.sqlx/query-b83fd5c55a209151ce5053b56034c49b5972df523f21a17be76303bde4a88522.json b/crates/storage-pg/.sqlx/query-b83fd5c55a209151ce5053b56034c49b5972df523f21a17be76303bde4a88522.json new file mode 100644 index 000000000..eb02cf6bc --- /dev/null +++ b/crates/storage-pg/.sqlx/query-b83fd5c55a209151ce5053b56034c49b5972df523f21a17be76303bde4a88522.json @@ -0,0 +1,88 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT oauth2_device_code_grant_id\n , oauth2_client_id\n , scope\n , device_code\n , user_code\n , created_at\n , expires_at\n , fulfilled_at\n , rejected_at\n , exchanged_at\n , user_session_id\n , oauth2_session_id\n FROM \n oauth2_device_code_grant\n\n WHERE user_code = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "oauth2_device_code_grant_id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "oauth2_client_id", + "type_info": "Uuid" + }, + { + "ordinal": 2, + "name": "scope", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "device_code", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "user_code", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "created_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 6, + "name": "expires_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 7, + "name": "fulfilled_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 8, + "name": "rejected_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 9, + "name": "exchanged_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 10, + "name": "user_session_id", + "type_info": "Uuid" + }, + { + "ordinal": 11, + "name": "oauth2_session_id", + "type_info": "Uuid" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false, + true, + true, + true, + true, + true + ] + }, + "hash": "b83fd5c55a209151ce5053b56034c49b5972df523f21a17be76303bde4a88522" +} diff --git a/crates/storage-pg/.sqlx/query-be25896189a30862a0aa0b6d1d6ba44278b98d4b8d027036e8871853f5d175c0.json b/crates/storage-pg/.sqlx/query-be25896189a30862a0aa0b6d1d6ba44278b98d4b8d027036e8871853f5d175c0.json new file mode 100644 index 000000000..d99085a3b --- /dev/null +++ b/crates/storage-pg/.sqlx/query-be25896189a30862a0aa0b6d1d6ba44278b98d4b8d027036e8871853f5d175c0.json @@ -0,0 +1,88 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT oauth2_device_code_grant_id\n , oauth2_client_id\n , scope\n , device_code\n , user_code\n , created_at\n , expires_at\n , fulfilled_at\n , rejected_at\n , exchanged_at\n , user_session_id\n , oauth2_session_id\n FROM \n oauth2_device_code_grant\n\n WHERE device_code = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "oauth2_device_code_grant_id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "oauth2_client_id", + "type_info": "Uuid" + }, + { + "ordinal": 2, + "name": "scope", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "device_code", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "user_code", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "created_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 6, + "name": "expires_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 7, + "name": "fulfilled_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 8, + "name": "rejected_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 9, + "name": "exchanged_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 10, + "name": "user_session_id", + "type_info": "Uuid" + }, + { + "ordinal": 11, + "name": "oauth2_session_id", + "type_info": "Uuid" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false, + false, + false, + false, + true, + true, + true, + true, + true + ] + }, + "hash": "be25896189a30862a0aa0b6d1d6ba44278b98d4b8d027036e8871853f5d175c0" +} diff --git a/crates/storage-pg/.sqlx/query-d26e42d9fd2b2ee3cf9702c1666d83e7cffa26b320ae1442c7f3e22376c4a4ee.json b/crates/storage-pg/.sqlx/query-d26e42d9fd2b2ee3cf9702c1666d83e7cffa26b320ae1442c7f3e22376c4a4ee.json new file mode 100644 index 000000000..c607483c4 --- /dev/null +++ b/crates/storage-pg/.sqlx/query-d26e42d9fd2b2ee3cf9702c1666d83e7cffa26b320ae1442c7f3e22376c4a4ee.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE oauth2_device_code_grant\n SET fulfilled_at = $1\n , user_session_id = $2\n WHERE oauth2_device_code_grant_id = $3\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Timestamptz", + "Uuid", + "Uuid" + ] + }, + "nullable": [] + }, + "hash": "d26e42d9fd2b2ee3cf9702c1666d83e7cffa26b320ae1442c7f3e22376c4a4ee" +} diff --git a/crates/storage-pg/.sqlx/query-d93810bb6573bf27f4ed83f5a1733640f3d5aa6d7354a1b16647d3cc941fc76c.json b/crates/storage-pg/.sqlx/query-d93810bb6573bf27f4ed83f5a1733640f3d5aa6d7354a1b16647d3cc941fc76c.json new file mode 100644 index 000000000..ea17cb75e --- /dev/null +++ b/crates/storage-pg/.sqlx/query-d93810bb6573bf27f4ed83f5a1733640f3d5aa6d7354a1b16647d3cc941fc76c.json @@ -0,0 +1,23 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO oauth2_clients\n ( oauth2_client_id\n , encrypted_client_secret\n , redirect_uris\n , grant_type_authorization_code\n , grant_type_refresh_token\n , grant_type_client_credentials\n , grant_type_device_code\n , token_endpoint_auth_method\n , jwks\n , jwks_uri\n , is_static\n )\n VALUES\n ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, TRUE)\n ON CONFLICT (oauth2_client_id)\n DO\n UPDATE SET encrypted_client_secret = EXCLUDED.encrypted_client_secret\n , grant_type_authorization_code = EXCLUDED.grant_type_authorization_code\n , grant_type_refresh_token = EXCLUDED.grant_type_refresh_token\n , grant_type_client_credentials = EXCLUDED.grant_type_client_credentials\n , grant_type_device_code = EXCLUDED.grant_type_device_code\n , token_endpoint_auth_method = EXCLUDED.token_endpoint_auth_method\n , jwks = EXCLUDED.jwks\n , jwks_uri = EXCLUDED.jwks_uri\n , is_static = TRUE\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Text", + "TextArray", + "Bool", + "Bool", + "Bool", + "Bool", + "Text", + "Jsonb", + "Text" + ] + }, + "nullable": [] + }, + "hash": "d93810bb6573bf27f4ed83f5a1733640f3d5aa6d7354a1b16647d3cc941fc76c" +} diff --git a/crates/storage-pg/migrations/20231208155602_oauth_clients_device_code_grant.sql b/crates/storage-pg/migrations/20231208155602_oauth_clients_device_code_grant.sql new file mode 100644 index 000000000..569db26e9 --- /dev/null +++ b/crates/storage-pg/migrations/20231208155602_oauth_clients_device_code_grant.sql @@ -0,0 +1,18 @@ +-- Copyright 2023 The Matrix.org Foundation C.I.C. +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +-- Add a flag on oauth_clients to indicate whether they support the device code grant +ALTER TABLE oauth2_clients + ADD COLUMN grant_type_device_code BOOLEAN + NOT NULL DEFAULT FALSE; diff --git a/crates/storage-pg/src/oauth2/client.rs b/crates/storage-pg/src/oauth2/client.rs index 54c0dec6c..0e5cc1d50 100644 --- a/crates/storage-pg/src/oauth2/client.rs +++ b/crates/storage-pg/src/oauth2/client.rs @@ -64,6 +64,7 @@ struct OAuth2ClientLookup { grant_type_authorization_code: bool, grant_type_refresh_token: bool, grant_type_client_credentials: bool, + grant_type_device_code: bool, contacts: Vec, client_name: Option, logo_uri: Option, @@ -130,6 +131,9 @@ impl TryInto for OAuth2ClientLookup { if self.grant_type_client_credentials { grant_types.push(GrantType::ClientCredentials); } + if self.grant_type_device_code { + grant_types.push(GrantType::DeviceCode); + } let logo_uri = self.logo_uri.map(|s| s.parse()).transpose().map_err(|e| { DatabaseInconsistencyError::on("oauth2_clients") @@ -298,6 +302,7 @@ impl<'c> OAuth2ClientRepository for PgOAuth2ClientRepository<'c> { , grant_type_authorization_code , grant_type_refresh_token , grant_type_client_credentials + , grant_type_device_code , contacts , client_name , logo_uri @@ -349,6 +354,7 @@ impl<'c> OAuth2ClientRepository for PgOAuth2ClientRepository<'c> { , grant_type_authorization_code , grant_type_refresh_token , grant_type_client_credentials + , grant_type_device_code , contacts , client_name , logo_uri @@ -436,6 +442,7 @@ impl<'c> OAuth2ClientRepository for PgOAuth2ClientRepository<'c> { , grant_type_authorization_code , grant_type_refresh_token , grant_type_client_credentials + , grant_type_device_code , client_name , logo_uri , client_uri @@ -451,7 +458,7 @@ impl<'c> OAuth2ClientRepository for PgOAuth2ClientRepository<'c> { , is_static ) VALUES - ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, FALSE) + ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, FALSE) "#, Uuid::from(id), encrypted_client_secret, @@ -460,6 +467,7 @@ impl<'c> OAuth2ClientRepository for PgOAuth2ClientRepository<'c> { grant_types.contains(&GrantType::AuthorizationCode), grant_types.contains(&GrantType::RefreshToken), grant_types.contains(&GrantType::ClientCredentials), + grant_types.contains(&GrantType::DeviceCode), client_name, logo_uri.as_ref().map(Url::as_str), client_uri.as_ref().map(Url::as_str), @@ -553,19 +561,21 @@ impl<'c> OAuth2ClientRepository for PgOAuth2ClientRepository<'c> { , grant_type_authorization_code , grant_type_refresh_token , grant_type_client_credentials + , grant_type_device_code , token_endpoint_auth_method , jwks , jwks_uri , is_static ) VALUES - ($1, $2, $3, $4, $5, $6, $7, $8, $9, TRUE) + ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, TRUE) ON CONFLICT (oauth2_client_id) DO UPDATE SET encrypted_client_secret = EXCLUDED.encrypted_client_secret , grant_type_authorization_code = EXCLUDED.grant_type_authorization_code , grant_type_refresh_token = EXCLUDED.grant_type_refresh_token , grant_type_client_credentials = EXCLUDED.grant_type_client_credentials + , grant_type_device_code = EXCLUDED.grant_type_device_code , token_endpoint_auth_method = EXCLUDED.token_endpoint_auth_method , jwks = EXCLUDED.jwks , jwks_uri = EXCLUDED.jwks_uri @@ -577,6 +587,7 @@ impl<'c> OAuth2ClientRepository for PgOAuth2ClientRepository<'c> { true, true, true, + true, client_auth_method, jwks_json, jwks_uri.as_ref().map(Url::as_str), @@ -642,6 +653,7 @@ impl<'c> OAuth2ClientRepository for PgOAuth2ClientRepository<'c> { , grant_type_authorization_code , grant_type_refresh_token , grant_type_client_credentials + , grant_type_device_code , contacts , client_name , logo_uri