···
1
+
From fc26fe5ac9e9cd65af82609c5a4966c8f756ea0f Mon Sep 17 00:00:00 2001
2
+
From: oddlama <oddlama@oddlama.org>
3
+
Date: Fri, 21 Mar 2025 16:07:54 +0100
4
+
Subject: [PATCH 1/2] oauth2 basic secret modify
7
+
server/core/src/actors/v1_write.rs | 42 +++++++++++++++++++++++++++++
8
+
server/core/src/https/v1.rs | 6 ++++-
9
+
server/core/src/https/v1_oauth2.rs | 29 ++++++++++++++++++++
10
+
server/lib/src/server/migrations.rs | 16 +++++++++++
11
+
4 files changed, 92 insertions(+), 1 deletion(-)
13
+
diff --git a/server/core/src/actors/v1_write.rs b/server/core/src/actors/v1_write.rs
14
+
index 732e826c8..a2b8e503f 100644
15
+
--- a/server/core/src/actors/v1_write.rs
16
+
+++ b/server/core/src/actors/v1_write.rs
17
+
@@ -324,6 +324,48 @@ impl QueryServerWriteV1 {
18
+
.and_then(|_| idms_prox_write.commit().map(|_| ()))
24
+
+ fields(uuid = ?eventid)
26
+
+ pub async fn handle_oauth2_basic_secret_write(
28
+
+ client_auth_info: ClientAuthInfo,
29
+
+ filter: Filter<FilterInvalid>,
30
+
+ new_secret: String,
32
+
+ ) -> Result<(), OperationError> {
33
+
+ // Given a protoEntry, turn this into a modification set.
34
+
+ let ct = duration_from_epoch_now();
35
+
+ let mut idms_prox_write = self.idms.proxy_write(ct).await?;
36
+
+ let ident = idms_prox_write
37
+
+ .validate_client_auth_info_to_ident(client_auth_info, ct)
39
+
+ admin_error!(err = ?e, "Invalid identity");
43
+
+ let modlist = ModifyList::new_purge_and_set(
44
+
+ Attribute::OAuth2RsBasicSecret,
45
+
+ Value::SecretValue(new_secret),
49
+
+ ModifyEvent::from_internal_parts(ident, &modlist, &filter, &idms_prox_write.qs_write)
51
+
+ admin_error!(err = ?e, "Failed to begin modify during handle_oauth2_basic_secret_write");
55
+
+ trace!(?mdf, "Begin modify event");
60
+
+ .and_then(|_| idms_prox_write.commit())
66
+
diff --git a/server/core/src/https/v1.rs b/server/core/src/https/v1.rs
67
+
index 30de387b8..a11aa8ecd 100644
68
+
--- a/server/core/src/https/v1.rs
69
+
+++ b/server/core/src/https/v1.rs
70
+
@@ -4,7 +4,7 @@ use axum::extract::{Path, State};
71
+
use axum::http::{HeaderMap, HeaderValue};
72
+
use axum::middleware::from_fn;
73
+
use axum::response::{IntoResponse, Response};
74
+
-use axum::routing::{delete, get, post, put};
75
+
+use axum::routing::{delete, get, post, put, patch};
76
+
use axum::{Extension, Json, Router};
77
+
use axum_extra::extract::cookie::{Cookie, CookieJar, SameSite};
78
+
use compact_jwt::{Jwk, Jws, JwsSigner};
79
+
@@ -3129,6 +3129,10 @@ pub(crate) fn route_setup(state: ServerState) -> Router<ServerState> {
80
+
"/v1/oauth2/:rs_name/_basic_secret",
81
+
get(super::v1_oauth2::oauth2_id_get_basic_secret),
84
+
+ "/v1/oauth2/:rs_name/_basic_secret",
85
+
+ patch(super::v1_oauth2::oauth2_id_patch_basic_secret),
88
+
"/v1/oauth2/:rs_name/_scopemap/:group",
89
+
post(super::v1_oauth2::oauth2_id_scopemap_post)
90
+
diff --git a/server/core/src/https/v1_oauth2.rs b/server/core/src/https/v1_oauth2.rs
91
+
index f399539bc..ffad9921e 100644
92
+
--- a/server/core/src/https/v1_oauth2.rs
93
+
+++ b/server/core/src/https/v1_oauth2.rs
94
+
@@ -151,6 +151,35 @@ pub(crate) async fn oauth2_id_get_basic_secret(
95
+
.map_err(WebError::from)
100
+
+ path = "/v1/oauth2/{rs_name}/_basic_secret",
101
+
+ request_body=ProtoEntry,
103
+
+ DefaultApiResponse,
105
+
+ security(("token_jwt" = [])),
106
+
+ tag = "v1/oauth2",
107
+
+ operation_id = "oauth2_id_patch_basic_secret"
109
+
+/// Overwrite the basic secret for a given OAuth2 Resource Server.
110
+
+#[instrument(level = "info", skip(state, new_secret))]
111
+
+pub(crate) async fn oauth2_id_patch_basic_secret(
112
+
+ State(state): State<ServerState>,
113
+
+ Extension(kopid): Extension<KOpId>,
114
+
+ VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
115
+
+ Path(rs_name): Path<String>,
116
+
+ Json(new_secret): Json<String>,
117
+
+) -> Result<Json<()>, WebError> {
118
+
+ let filter = oauth2_id(&rs_name);
121
+
+ .handle_oauth2_basic_secret_write(client_auth_info, filter, new_secret, kopid.eventid)
124
+
+ .map_err(WebError::from)
129
+
path = "/v1/oauth2/{rs_name}",
130
+
diff --git a/server/lib/src/server/migrations.rs b/server/lib/src/server/migrations.rs
131
+
index fd0bca8db..8621714f2 100644
132
+
--- a/server/lib/src/server/migrations.rs
133
+
+++ b/server/lib/src/server/migrations.rs
134
+
@@ -171,6 +171,22 @@ impl QueryServer {
135
+
reload_required = true;
138
+
+ // secret provisioning: allow idm_admin to modify OAuth2RsBasicSecret.
139
+
+ write_txn.internal_modify_uuid(
140
+
+ UUID_IDM_ACP_OAUTH2_MANAGE_V1,
141
+
+ &ModifyList::new_append(
142
+
+ Attribute::AcpCreateAttr,
143
+
+ Attribute::OAuth2RsBasicSecret.into(),
146
+
+ write_txn.internal_modify_uuid(
147
+
+ UUID_IDM_ACP_OAUTH2_MANAGE_V1,
148
+
+ &ModifyList::new_append(
149
+
+ Attribute::AcpModifyPresentAttr,
150
+
+ Attribute::OAuth2RsBasicSecret.into(),
154
+
// Execute whatever operations we have batched up and ready to go. This is needed
155
+
// to preserve ordering of the operations - if we reloaded after a remigrate then
156
+
// we would have skipped the patch level fix which needs to have occurred *first*.