1use crate::codec::host_service::{HostServiceChannel, connect_host_service, plain_channel};
6use crate::codec::identity::{
7 from_wire_authorize_response, from_wire_get_grant_response, from_wire_introspect_response,
8 from_wire_list_grants_response, from_wire_revoke_grant_response, from_wire_token_response,
9 from_wire_user_info_response, to_wire_authorize_request, to_wire_get_grant_request,
10 to_wire_introspect_request, to_wire_list_grants_request, to_wire_revoke_grant_request,
11 to_wire_token_request, to_wire_user_info_request,
12};
13use crate::generated::v1;
14use crate::rpc_support::GestaltError;
15
16#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
20#[serde(rename_all = "camelCase")]
21pub struct AuthorizeRequest {
22 pub response_type: String,
26 pub client_id: String,
28 pub redirect_uri: String,
30 pub scope: String,
32 pub state: String,
34}
35
36#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
41#[serde(rename_all = "camelCase")]
42pub struct AuthorizeResponse {
43 pub redirect_uri: String,
45}
46
47#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
51#[serde(rename_all = "camelCase")]
52pub struct GetGrantRequest {
53 pub grant_id: String,
55}
56
57#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
61#[serde(rename_all = "camelCase")]
62pub struct GetGrantResponse {
63 pub scopes: Vec<GrantScope>,
65 pub created_at: i64,
67 pub expires_at: i64,
69}
70
71#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
75#[serde(rename_all = "camelCase")]
76pub struct GrantScope {
77 pub scope: String,
79 pub resource: Vec<String>,
81}
82
83#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
87#[serde(rename_all = "camelCase")]
88pub struct IntrospectRequest {
89 pub token: String,
91 pub token_type_hint: String,
95}
96
97#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
105#[serde(rename_all = "camelCase")]
106pub struct IntrospectResponse {
107 pub active: bool,
109 pub subject: String,
111 pub scope: String,
113 pub client_id: String,
115 pub audience: Vec<String>,
117}
118
119#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
123#[serde(rename_all = "camelCase")]
124pub struct ListGrantsRequest {}
125
126#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
131#[serde(rename_all = "camelCase")]
132pub struct ListGrantsResponse {
133 pub grant_ids: Vec<String>,
135}
136
137#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
141#[serde(rename_all = "camelCase")]
142pub struct RevokeGrantRequest {
143 pub grant_id: String,
145}
146
147#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
151#[serde(rename_all = "camelCase")]
152pub struct RevokeGrantResponse {}
153
154#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
159#[serde(rename_all = "camelCase")]
160pub struct TokenRequest {
161 pub grant_type: String,
166 pub code: String,
168 pub redirect_uri: String,
170 pub client_id: String,
172 pub state: String,
176 pub scope: String,
180 pub subject_token: String,
184 pub subject_token_type: String,
188 pub expires_in: i64,
195}
196
197#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
201#[serde(rename_all = "camelCase")]
202pub struct TokenResponse {
203 pub access_token: String,
205 pub token_type: String,
207 pub expires_in: i64,
209 pub refresh_token: String,
211 pub scope: String,
213 pub grant_id: String,
217}
218
219#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
224#[serde(rename_all = "camelCase")]
225pub struct UserInfoRequest {}
226
227#[derive(Clone, Debug, Default, PartialEq, serde::Serialize, serde::Deserialize)]
231#[serde(rename_all = "camelCase")]
232pub struct UserInfoResponse {
233 pub subject_id: String,
235 pub email: String,
237 pub name: String,
239}
240
241pub struct Identity {
245 inner: v1::identity_client::IdentityClient<HostServiceChannel>,
246 timeout: Option<std::time::Duration>,
247}
248
249impl Identity {
250 pub fn new(channel: tonic::transport::Channel) -> Self {
252 Self {
253 inner: v1::identity_client::IdentityClient::new(plain_channel(channel)),
254 timeout: None,
255 }
256 }
257
258 pub fn with_timeout(mut self, timeout: std::time::Duration) -> Self {
261 self.timeout = Some(timeout);
262 self
263 }
264
265 pub async fn connect() -> Result<Self, GestaltError> {
267 Self::connect_named("").await
268 }
269
270 pub async fn connect_named(name: &str) -> Result<Self, GestaltError> {
272 Ok(Self {
273 inner: v1::identity_client::IdentityClient::new(
274 connect_host_service("identity", name).await?,
275 ),
276 timeout: None,
277 })
278 }
279
280 pub async fn authorize(
282 &mut self,
283 response_type: String,
284 client_id: String,
285 redirect_uri: String,
286 scope: String,
287 state: String,
288 ) -> Result<AuthorizeResponse, GestaltError> {
289 let request = AuthorizeRequest {
290 response_type,
291 client_id,
292 redirect_uri,
293 scope,
294 state,
295 };
296 let mut tonic_request = tonic::Request::new(to_wire_authorize_request(request));
297 if let Some(timeout) = self.timeout {
298 tonic_request.set_timeout(timeout);
299 }
300 let response = self.inner.authorize(tonic_request).await?;
301 Ok(from_wire_authorize_response(response.into_inner()))
302 }
303
304 pub async fn authorize_raw(
306 &mut self,
307 request: AuthorizeRequest,
308 ) -> Result<AuthorizeResponse, GestaltError> {
309 let mut tonic_request = tonic::Request::new(to_wire_authorize_request(request));
310 if let Some(timeout) = self.timeout {
311 tonic_request.set_timeout(timeout);
312 }
313 let response = self.inner.authorize(tonic_request).await?;
314 Ok(from_wire_authorize_response(response.into_inner()))
315 }
316
317 #[allow(clippy::too_many_arguments)]
319 pub async fn token(
320 &mut self,
321 grant_type: String,
322 code: String,
323 redirect_uri: String,
324 client_id: String,
325 state: String,
326 scope: String,
327 subject_token: String,
328 subject_token_type: String,
329 options: IdentityTokenOptions,
330 ) -> Result<TokenResponse, GestaltError> {
331 let request = TokenRequest {
332 grant_type,
333 code,
334 redirect_uri,
335 client_id,
336 state,
337 scope,
338 subject_token,
339 subject_token_type,
340 expires_in: options.expires_in,
341 };
342 let mut tonic_request = tonic::Request::new(to_wire_token_request(request));
343 if let Some(timeout) = self.timeout {
344 tonic_request.set_timeout(timeout);
345 }
346 let response = self.inner.token(tonic_request).await?;
347 Ok(from_wire_token_response(response.into_inner()))
348 }
349
350 pub async fn token_raw(
352 &mut self,
353 request: TokenRequest,
354 ) -> Result<TokenResponse, GestaltError> {
355 let mut tonic_request = tonic::Request::new(to_wire_token_request(request));
356 if let Some(timeout) = self.timeout {
357 tonic_request.set_timeout(timeout);
358 }
359 let response = self.inner.token(tonic_request).await?;
360 Ok(from_wire_token_response(response.into_inner()))
361 }
362
363 pub async fn introspect(
365 &mut self,
366 token: String,
367 token_type_hint: String,
368 ) -> Result<IntrospectResponse, GestaltError> {
369 let request = IntrospectRequest {
370 token,
371 token_type_hint,
372 };
373 let mut tonic_request = tonic::Request::new(to_wire_introspect_request(request));
374 if let Some(timeout) = self.timeout {
375 tonic_request.set_timeout(timeout);
376 }
377 let response = self.inner.introspect(tonic_request).await?;
378 Ok(from_wire_introspect_response(response.into_inner()))
379 }
380
381 pub async fn introspect_raw(
383 &mut self,
384 request: IntrospectRequest,
385 ) -> Result<IntrospectResponse, GestaltError> {
386 let mut tonic_request = tonic::Request::new(to_wire_introspect_request(request));
387 if let Some(timeout) = self.timeout {
388 tonic_request.set_timeout(timeout);
389 }
390 let response = self.inner.introspect(tonic_request).await?;
391 Ok(from_wire_introspect_response(response.into_inner()))
392 }
393
394 pub async fn user_info(
396 &mut self,
397 request: UserInfoRequest,
398 ) -> Result<UserInfoResponse, GestaltError> {
399 let mut tonic_request = tonic::Request::new(to_wire_user_info_request(request));
400 if let Some(timeout) = self.timeout {
401 tonic_request.set_timeout(timeout);
402 }
403 let response = self.inner.user_info(tonic_request).await?;
404 Ok(from_wire_user_info_response(response.into_inner()))
405 }
406
407 pub async fn list_grants(
409 &mut self,
410 request: ListGrantsRequest,
411 ) -> Result<ListGrantsResponse, GestaltError> {
412 let mut tonic_request = tonic::Request::new(to_wire_list_grants_request(request));
413 if let Some(timeout) = self.timeout {
414 tonic_request.set_timeout(timeout);
415 }
416 let response = self.inner.list_grants(tonic_request).await?;
417 Ok(from_wire_list_grants_response(response.into_inner()))
418 }
419
420 pub async fn get_grant(&mut self, grant_id: String) -> Result<GetGrantResponse, GestaltError> {
422 let request = GetGrantRequest { grant_id };
423 let mut tonic_request = tonic::Request::new(to_wire_get_grant_request(request));
424 if let Some(timeout) = self.timeout {
425 tonic_request.set_timeout(timeout);
426 }
427 let response = self.inner.get_grant(tonic_request).await?;
428 Ok(from_wire_get_grant_response(response.into_inner()))
429 }
430
431 pub async fn get_grant_raw(
433 &mut self,
434 request: GetGrantRequest,
435 ) -> Result<GetGrantResponse, GestaltError> {
436 let mut tonic_request = tonic::Request::new(to_wire_get_grant_request(request));
437 if let Some(timeout) = self.timeout {
438 tonic_request.set_timeout(timeout);
439 }
440 let response = self.inner.get_grant(tonic_request).await?;
441 Ok(from_wire_get_grant_response(response.into_inner()))
442 }
443
444 pub async fn revoke_grant(
446 &mut self,
447 grant_id: String,
448 ) -> Result<RevokeGrantResponse, GestaltError> {
449 let request = RevokeGrantRequest { grant_id };
450 let mut tonic_request = tonic::Request::new(to_wire_revoke_grant_request(request));
451 if let Some(timeout) = self.timeout {
452 tonic_request.set_timeout(timeout);
453 }
454 let response = self.inner.revoke_grant(tonic_request).await?;
455 Ok(from_wire_revoke_grant_response(response.into_inner()))
456 }
457
458 pub async fn revoke_grant_raw(
460 &mut self,
461 request: RevokeGrantRequest,
462 ) -> Result<RevokeGrantResponse, GestaltError> {
463 let mut tonic_request = tonic::Request::new(to_wire_revoke_grant_request(request));
464 if let Some(timeout) = self.timeout {
465 tonic_request.set_timeout(timeout);
466 }
467 let response = self.inner.revoke_grant(tonic_request).await?;
468 Ok(from_wire_revoke_grant_response(response.into_inner()))
469 }
470}
471
472#[derive(Clone, Debug, Default)]
475pub struct IdentityTokenOptions {
476 pub expires_in: i64,
483}