1use std::collections::{BTreeMap, BTreeSet};
2use std::future::Future;
3use std::pin::Pin;
4use std::sync::{Arc, RwLock};
5
6use openauth_core::db::{Session, User};
7use openauth_core::error::OpenAuthError;
8use openauth_core::options::RateLimitRule;
9use openauth_core::plugin::AuthPlugin;
10use serde_json::{Map, Value};
11use thiserror::Error;
12
13use crate::models::SchemaClient;
14
15type ClientReferenceFuture =
16 Pin<Box<dyn Future<Output = Result<Option<String>, OpenAuthError>> + Send>>;
17type ClientPrivilegesFuture = Pin<Box<dyn Future<Output = Result<bool, OpenAuthError>> + Send>>;
18type JsonObjectFuture =
19 Pin<Box<dyn Future<Output = Result<Map<String, Value>, OpenAuthError>> + Send>>;
20type OptionalStringFuture =
21 Pin<Box<dyn Future<Output = Result<Option<String>, OpenAuthError>> + Send>>;
22type RequestUriFuture =
23 Pin<Box<dyn Future<Output = Result<Option<Vec<(String, String)>>, OpenAuthError>> + Send>>;
24type StringGeneratorFuture = Pin<Box<dyn Future<Output = Result<String, OpenAuthError>> + Send>>;
25type BoolResolverFuture = Pin<Box<dyn Future<Output = Result<bool, OpenAuthError>> + Send>>;
26type RefreshTokenEncodeFuture = Pin<Box<dyn Future<Output = Result<String, OpenAuthError>> + Send>>;
27type RefreshTokenDecodeFuture =
28 Pin<Box<dyn Future<Output = Result<RefreshTokenFormatDecodeOutput, OpenAuthError>> + Send>>;
29
30#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct ClientReferenceInput {
33 pub user: Option<User>,
34 pub session: Option<Session>,
35}
36
37#[derive(Clone)]
39pub struct ClientReferenceResolver {
40 resolver: Arc<dyn Fn(ClientReferenceInput) -> ClientReferenceFuture + Send + Sync>,
41}
42
43impl ClientReferenceResolver {
44 pub fn new<F, Fut>(resolver: F) -> Self
46 where
47 F: Fn(ClientReferenceInput) -> Fut + Send + Sync + 'static,
48 Fut: Future<Output = Result<Option<String>, OpenAuthError>> + Send + 'static,
49 {
50 Self {
51 resolver: Arc::new(move |input| Box::pin(resolver(input))),
52 }
53 }
54
55 pub async fn resolve(
56 &self,
57 input: ClientReferenceInput,
58 ) -> Result<Option<String>, OpenAuthError> {
59 (self.resolver)(input).await
60 }
61}
62
63impl std::fmt::Debug for ClientReferenceResolver {
64 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 formatter.write_str("ClientReferenceResolver(..)")
66 }
67}
68
69impl PartialEq for ClientReferenceResolver {
70 fn eq(&self, _other: &Self) -> bool {
71 true
72 }
73}
74
75impl Eq for ClientReferenceResolver {}
76
77#[derive(Clone, Default)]
78pub struct TrustedClientCache {
79 clients: Arc<RwLock<BTreeMap<String, SchemaClient>>>,
80}
81
82impl TrustedClientCache {
83 pub fn get(&self, client_id: &str) -> Result<Option<SchemaClient>, OpenAuthError> {
84 let clients = self
85 .clients
86 .read()
87 .map_err(|_| OpenAuthError::Api("trusted client cache lock poisoned".to_owned()))?;
88 Ok(clients.get(client_id).cloned())
89 }
90
91 pub fn insert(&self, client: SchemaClient) -> Result<(), OpenAuthError> {
92 let mut clients = self
93 .clients
94 .write()
95 .map_err(|_| OpenAuthError::Api("trusted client cache lock poisoned".to_owned()))?;
96 clients.insert(client.client_id.clone(), client);
97 Ok(())
98 }
99}
100
101impl std::fmt::Debug for TrustedClientCache {
102 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 formatter.write_str("TrustedClientCache(..)")
104 }
105}
106
107impl PartialEq for TrustedClientCache {
108 fn eq(&self, _other: &Self) -> bool {
109 true
110 }
111}
112
113impl Eq for TrustedClientCache {}
114
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
117pub enum ClientPrivilegeAction {
118 Create,
119 Read,
120 Update,
121 Delete,
122 List,
123 Rotate,
124}
125
126#[derive(Debug, Clone, PartialEq, Eq)]
128pub struct ClientPrivilegesInput {
129 pub action: ClientPrivilegeAction,
130 pub user: Option<User>,
131 pub session: Option<Session>,
132}
133
134#[derive(Clone)]
136pub struct ClientPrivilegesResolver {
137 resolver: Arc<dyn Fn(ClientPrivilegesInput) -> ClientPrivilegesFuture + Send + Sync>,
138}
139
140impl ClientPrivilegesResolver {
141 pub fn new<F, Fut>(resolver: F) -> Self
142 where
143 F: Fn(ClientPrivilegesInput) -> Fut + Send + Sync + 'static,
144 Fut: Future<Output = Result<bool, OpenAuthError>> + Send + 'static,
145 {
146 Self {
147 resolver: Arc::new(move |input| Box::pin(resolver(input))),
148 }
149 }
150
151 pub async fn resolve(&self, input: ClientPrivilegesInput) -> Result<bool, OpenAuthError> {
152 (self.resolver)(input).await
153 }
154}
155
156impl std::fmt::Debug for ClientPrivilegesResolver {
157 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158 formatter.write_str("ClientPrivilegesResolver(..)")
159 }
160}
161
162impl PartialEq for ClientPrivilegesResolver {
163 fn eq(&self, _other: &Self) -> bool {
164 true
165 }
166}
167
168impl Eq for ClientPrivilegesResolver {}
169
170#[derive(Debug, Clone, PartialEq, Eq)]
172pub struct ClientSecretHashInput {
173 pub secret: String,
174}
175
176#[derive(Clone)]
178pub struct ClientSecretHashResolver {
179 resolver: Arc<dyn Fn(ClientSecretHashInput) -> StringGeneratorFuture + Send + Sync>,
180}
181
182impl ClientSecretHashResolver {
183 pub fn new<F, Fut>(resolver: F) -> Self
184 where
185 F: Fn(ClientSecretHashInput) -> Fut + Send + Sync + 'static,
186 Fut: Future<Output = Result<String, OpenAuthError>> + Send + 'static,
187 {
188 Self {
189 resolver: Arc::new(move |input| Box::pin(resolver(input))),
190 }
191 }
192
193 pub async fn resolve(&self, input: ClientSecretHashInput) -> Result<String, OpenAuthError> {
194 (self.resolver)(input).await
195 }
196}
197
198impl std::fmt::Debug for ClientSecretHashResolver {
199 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200 formatter.write_str("ClientSecretHashResolver(..)")
201 }
202}
203
204impl PartialEq for ClientSecretHashResolver {
205 fn eq(&self, _other: &Self) -> bool {
206 true
207 }
208}
209
210impl Eq for ClientSecretHashResolver {}
211
212#[derive(Debug, Clone, PartialEq, Eq)]
214pub struct ClientSecretVerifyInput {
215 pub secret: String,
216 pub stored_hash: String,
217}
218
219#[derive(Clone)]
221pub struct ClientSecretVerifyResolver {
222 resolver: Arc<dyn Fn(ClientSecretVerifyInput) -> BoolResolverFuture + Send + Sync>,
223}
224
225impl ClientSecretVerifyResolver {
226 pub fn new<F, Fut>(resolver: F) -> Self
227 where
228 F: Fn(ClientSecretVerifyInput) -> Fut + Send + Sync + 'static,
229 Fut: Future<Output = Result<bool, OpenAuthError>> + Send + 'static,
230 {
231 Self {
232 resolver: Arc::new(move |input| Box::pin(resolver(input))),
233 }
234 }
235
236 pub async fn resolve(&self, input: ClientSecretVerifyInput) -> Result<bool, OpenAuthError> {
237 (self.resolver)(input).await
238 }
239}
240
241impl std::fmt::Debug for ClientSecretVerifyResolver {
242 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
243 formatter.write_str("ClientSecretVerifyResolver(..)")
244 }
245}
246
247impl PartialEq for ClientSecretVerifyResolver {
248 fn eq(&self, _other: &Self) -> bool {
249 true
250 }
251}
252
253impl Eq for ClientSecretVerifyResolver {}
254
255#[derive(Debug, Clone, PartialEq, Eq)]
257pub struct TokenHashInput {
258 pub token: String,
259 pub token_type: String,
260}
261
262#[derive(Clone)]
264pub struct TokenHashResolver {
265 resolver: Arc<dyn Fn(TokenHashInput) -> StringGeneratorFuture + Send + Sync>,
266}
267
268impl TokenHashResolver {
269 pub fn new<F, Fut>(resolver: F) -> Self
270 where
271 F: Fn(TokenHashInput) -> Fut + Send + Sync + 'static,
272 Fut: Future<Output = Result<String, OpenAuthError>> + Send + 'static,
273 {
274 Self {
275 resolver: Arc::new(move |input| Box::pin(resolver(input))),
276 }
277 }
278
279 pub async fn resolve(&self, input: TokenHashInput) -> Result<String, OpenAuthError> {
280 (self.resolver)(input).await
281 }
282}
283
284impl std::fmt::Debug for TokenHashResolver {
285 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
286 formatter.write_str("TokenHashResolver(..)")
287 }
288}
289
290impl PartialEq for TokenHashResolver {
291 fn eq(&self, _other: &Self) -> bool {
292 true
293 }
294}
295
296impl Eq for TokenHashResolver {}
297
298#[derive(Debug, Clone, PartialEq, Eq)]
300pub struct PromptRedirectInput {
301 pub user: User,
302 pub session: Session,
303 pub scopes: Vec<String>,
304}
305
306#[derive(Clone)]
308pub struct PromptRedirectResolver {
309 resolver: Arc<dyn Fn(PromptRedirectInput) -> OptionalStringFuture + Send + Sync>,
310}
311
312impl PromptRedirectResolver {
313 pub fn new<F, Fut>(resolver: F) -> Self
314 where
315 F: Fn(PromptRedirectInput) -> Fut + Send + Sync + 'static,
316 Fut: Future<Output = Result<Option<String>, OpenAuthError>> + Send + 'static,
317 {
318 Self {
319 resolver: Arc::new(move |input| Box::pin(resolver(input))),
320 }
321 }
322
323 pub async fn resolve(
324 &self,
325 input: PromptRedirectInput,
326 ) -> Result<Option<String>, OpenAuthError> {
327 (self.resolver)(input).await
328 }
329}
330
331impl std::fmt::Debug for PromptRedirectResolver {
332 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
333 formatter.write_str("PromptRedirectResolver(..)")
334 }
335}
336
337impl PartialEq for PromptRedirectResolver {
338 fn eq(&self, _other: &Self) -> bool {
339 true
340 }
341}
342
343impl Eq for PromptRedirectResolver {}
344
345#[derive(Debug, Clone, PartialEq)]
347pub struct CustomIdTokenClaimsInput {
348 pub user: User,
349 pub scopes: Vec<String>,
350 pub metadata: Option<Value>,
351}
352
353#[derive(Debug, Clone, PartialEq)]
355pub struct CustomAccessTokenClaimsInput {
356 pub user: Option<User>,
357 pub reference_id: Option<String>,
358 pub scopes: Vec<String>,
359 pub resource: Vec<String>,
360 pub metadata: Option<Value>,
361}
362
363#[derive(Clone)]
365pub struct CustomAccessTokenClaimsResolver {
366 resolver: Arc<dyn Fn(CustomAccessTokenClaimsInput) -> JsonObjectFuture + Send + Sync>,
367}
368
369impl CustomAccessTokenClaimsResolver {
370 pub fn new<F, Fut>(resolver: F) -> Self
371 where
372 F: Fn(CustomAccessTokenClaimsInput) -> Fut + Send + Sync + 'static,
373 Fut: Future<Output = Result<Map<String, Value>, OpenAuthError>> + Send + 'static,
374 {
375 Self {
376 resolver: Arc::new(move |input| Box::pin(resolver(input))),
377 }
378 }
379
380 pub async fn resolve(
381 &self,
382 input: CustomAccessTokenClaimsInput,
383 ) -> Result<Map<String, Value>, OpenAuthError> {
384 (self.resolver)(input).await
385 }
386}
387
388impl std::fmt::Debug for CustomAccessTokenClaimsResolver {
389 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
390 formatter.write_str("CustomAccessTokenClaimsResolver(..)")
391 }
392}
393
394impl PartialEq for CustomAccessTokenClaimsResolver {
395 fn eq(&self, _other: &Self) -> bool {
396 true
397 }
398}
399
400impl Eq for CustomAccessTokenClaimsResolver {}
401
402#[derive(Clone)]
404pub struct CustomIdTokenClaimsResolver {
405 resolver: Arc<dyn Fn(CustomIdTokenClaimsInput) -> JsonObjectFuture + Send + Sync>,
406}
407
408impl CustomIdTokenClaimsResolver {
409 pub fn new<F, Fut>(resolver: F) -> Self
410 where
411 F: Fn(CustomIdTokenClaimsInput) -> Fut + Send + Sync + 'static,
412 Fut: Future<Output = Result<Map<String, Value>, OpenAuthError>> + Send + 'static,
413 {
414 Self {
415 resolver: Arc::new(move |input| Box::pin(resolver(input))),
416 }
417 }
418
419 pub async fn resolve(
420 &self,
421 input: CustomIdTokenClaimsInput,
422 ) -> Result<Map<String, Value>, OpenAuthError> {
423 (self.resolver)(input).await
424 }
425}
426
427impl std::fmt::Debug for CustomIdTokenClaimsResolver {
428 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
429 formatter.write_str("CustomIdTokenClaimsResolver(..)")
430 }
431}
432
433impl PartialEq for CustomIdTokenClaimsResolver {
434 fn eq(&self, _other: &Self) -> bool {
435 true
436 }
437}
438
439impl Eq for CustomIdTokenClaimsResolver {}
440
441#[derive(Debug, Clone, PartialEq)]
443pub struct CustomTokenResponseFieldsInput {
444 pub grant_type: GrantType,
445 pub user: Option<User>,
446 pub scopes: Vec<String>,
447 pub metadata: Option<Value>,
448}
449
450#[derive(Clone)]
452pub struct CustomTokenResponseFieldsResolver {
453 resolver: Arc<dyn Fn(CustomTokenResponseFieldsInput) -> JsonObjectFuture + Send + Sync>,
454}
455
456impl CustomTokenResponseFieldsResolver {
457 pub fn new<F, Fut>(resolver: F) -> Self
458 where
459 F: Fn(CustomTokenResponseFieldsInput) -> Fut + Send + Sync + 'static,
460 Fut: Future<Output = Result<Map<String, Value>, OpenAuthError>> + Send + 'static,
461 {
462 Self {
463 resolver: Arc::new(move |input| Box::pin(resolver(input))),
464 }
465 }
466
467 pub async fn resolve(
468 &self,
469 input: CustomTokenResponseFieldsInput,
470 ) -> Result<Map<String, Value>, OpenAuthError> {
471 (self.resolver)(input).await
472 }
473}
474
475impl std::fmt::Debug for CustomTokenResponseFieldsResolver {
476 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
477 formatter.write_str("CustomTokenResponseFieldsResolver(..)")
478 }
479}
480
481impl PartialEq for CustomTokenResponseFieldsResolver {
482 fn eq(&self, _other: &Self) -> bool {
483 true
484 }
485}
486
487impl Eq for CustomTokenResponseFieldsResolver {}
488
489#[derive(Debug, Clone, PartialEq)]
491pub struct CustomUserInfoClaimsInput {
492 pub user: User,
493 pub scopes: Vec<String>,
494 pub jwt: Value,
495}
496
497#[derive(Clone)]
499pub struct CustomUserInfoClaimsResolver {
500 resolver: Arc<dyn Fn(CustomUserInfoClaimsInput) -> JsonObjectFuture + Send + Sync>,
501}
502
503impl CustomUserInfoClaimsResolver {
504 pub fn new<F, Fut>(resolver: F) -> Self
505 where
506 F: Fn(CustomUserInfoClaimsInput) -> Fut + Send + Sync + 'static,
507 Fut: Future<Output = Result<Map<String, Value>, OpenAuthError>> + Send + 'static,
508 {
509 Self {
510 resolver: Arc::new(move |input| Box::pin(resolver(input))),
511 }
512 }
513
514 pub async fn resolve(
515 &self,
516 input: CustomUserInfoClaimsInput,
517 ) -> Result<Map<String, Value>, OpenAuthError> {
518 (self.resolver)(input).await
519 }
520}
521
522impl std::fmt::Debug for CustomUserInfoClaimsResolver {
523 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
524 formatter.write_str("CustomUserInfoClaimsResolver(..)")
525 }
526}
527
528impl PartialEq for CustomUserInfoClaimsResolver {
529 fn eq(&self, _other: &Self) -> bool {
530 true
531 }
532}
533
534impl Eq for CustomUserInfoClaimsResolver {}
535
536#[derive(Debug, Clone, PartialEq, Eq)]
538pub struct RequestUriResolverInput {
539 pub request_uri: String,
540 pub client_id: Option<String>,
541}
542
543#[derive(Clone)]
545pub struct RequestUriResolver {
546 resolver: Arc<dyn Fn(RequestUriResolverInput) -> RequestUriFuture + Send + Sync>,
547}
548
549impl RequestUriResolver {
550 pub fn new<F, Fut>(resolver: F) -> Self
551 where
552 F: Fn(RequestUriResolverInput) -> Fut + Send + Sync + 'static,
553 Fut: Future<Output = Result<Option<Vec<(String, String)>>, OpenAuthError>> + Send + 'static,
554 {
555 Self {
556 resolver: Arc::new(move |input| Box::pin(resolver(input))),
557 }
558 }
559
560 pub async fn resolve(
561 &self,
562 input: RequestUriResolverInput,
563 ) -> Result<Option<Vec<(String, String)>>, OpenAuthError> {
564 (self.resolver)(input).await
565 }
566}
567
568impl std::fmt::Debug for RequestUriResolver {
569 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
570 formatter.write_str("RequestUriResolver(..)")
571 }
572}
573
574impl PartialEq for RequestUriResolver {
575 fn eq(&self, _other: &Self) -> bool {
576 true
577 }
578}
579
580impl Eq for RequestUriResolver {}
581
582#[derive(Clone)]
584pub struct StringGeneratorResolver {
585 resolver: Arc<dyn Fn() -> StringGeneratorFuture + Send + Sync>,
586}
587
588impl StringGeneratorResolver {
589 pub fn new<F, Fut>(resolver: F) -> Self
590 where
591 F: Fn() -> Fut + Send + Sync + 'static,
592 Fut: Future<Output = Result<String, OpenAuthError>> + Send + 'static,
593 {
594 Self {
595 resolver: Arc::new(move || Box::pin(resolver())),
596 }
597 }
598
599 pub async fn generate(&self) -> Result<String, OpenAuthError> {
600 (self.resolver)().await
601 }
602}
603
604impl std::fmt::Debug for StringGeneratorResolver {
605 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
606 formatter.write_str("StringGeneratorResolver(..)")
607 }
608}
609
610impl PartialEq for StringGeneratorResolver {
611 fn eq(&self, _other: &Self) -> bool {
612 true
613 }
614}
615
616impl Eq for StringGeneratorResolver {}
617
618#[derive(Debug, Clone, PartialEq, Eq)]
620pub struct RefreshTokenFormatEncodeInput {
621 pub token: String,
622 pub session_id: Option<String>,
623}
624
625#[derive(Debug, Clone, PartialEq, Eq)]
627pub struct RefreshTokenFormatDecodeOutput {
628 pub session_id: Option<String>,
629 pub token: String,
630}
631
632#[derive(Clone)]
634pub struct RefreshTokenFormatter {
635 encoder: Arc<dyn Fn(RefreshTokenFormatEncodeInput) -> RefreshTokenEncodeFuture + Send + Sync>,
636 decoder: Arc<dyn Fn(String) -> RefreshTokenDecodeFuture + Send + Sync>,
637}
638
639impl RefreshTokenFormatter {
640 pub fn new<Encode, EncodeFuture, Decode, DecodeFuture>(encoder: Encode, decoder: Decode) -> Self
641 where
642 Encode: Fn(RefreshTokenFormatEncodeInput) -> EncodeFuture + Send + Sync + 'static,
643 EncodeFuture: Future<Output = Result<String, OpenAuthError>> + Send + 'static,
644 Decode: Fn(String) -> DecodeFuture + Send + Sync + 'static,
645 DecodeFuture:
646 Future<Output = Result<RefreshTokenFormatDecodeOutput, OpenAuthError>> + Send + 'static,
647 {
648 Self {
649 encoder: Arc::new(move |input| Box::pin(encoder(input))),
650 decoder: Arc::new(move |token| Box::pin(decoder(token))),
651 }
652 }
653
654 pub async fn encode(
655 &self,
656 input: RefreshTokenFormatEncodeInput,
657 ) -> Result<String, OpenAuthError> {
658 (self.encoder)(input).await
659 }
660
661 pub async fn decode(
662 &self,
663 token: String,
664 ) -> Result<RefreshTokenFormatDecodeOutput, OpenAuthError> {
665 (self.decoder)(token).await
666 }
667}
668
669impl std::fmt::Debug for RefreshTokenFormatter {
670 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
671 formatter.write_str("RefreshTokenFormatter(..)")
672 }
673}
674
675impl PartialEq for RefreshTokenFormatter {
676 fn eq(&self, _other: &Self) -> bool {
677 true
678 }
679}
680
681impl Eq for RefreshTokenFormatter {}
682
683#[derive(Debug, Clone, Default, PartialEq, Eq)]
685pub struct OAuthTokenPrefixes {
686 pub opaque_access_token: Option<String>,
687 pub refresh_token: Option<String>,
688 pub client_secret: Option<String>,
689}
690
691#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
693#[serde(rename_all = "snake_case")]
694pub enum GrantType {
695 AuthorizationCode,
696 ClientCredentials,
697 RefreshToken,
698}
699
700impl GrantType {
701 pub fn as_str(self) -> &'static str {
702 match self {
703 Self::AuthorizationCode => "authorization_code",
704 Self::ClientCredentials => "client_credentials",
705 Self::RefreshToken => "refresh_token",
706 }
707 }
708}
709
710#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
712#[serde(rename_all = "snake_case")]
713pub enum TokenEndpointAuthMethod {
714 None,
715 ClientSecretBasic,
716 ClientSecretPost,
717}
718
719impl TokenEndpointAuthMethod {
720 pub fn as_str(self) -> &'static str {
721 match self {
722 Self::None => "none",
723 Self::ClientSecretBasic => "client_secret_basic",
724 Self::ClientSecretPost => "client_secret_post",
725 }
726 }
727}
728
729#[derive(Debug, Clone, Copy, PartialEq, Eq)]
731pub enum SecretStorage {
732 Auto,
734 Hashed,
736 Encrypted,
738}
739
740#[derive(Debug, Clone, PartialEq, Eq)]
742pub enum OAuthProviderRateLimit {
743 Default,
745 Disabled,
747 Custom(RateLimitRule),
749}
750
751#[derive(Debug, Clone, PartialEq, Eq)]
753pub struct OAuthProviderRateLimits {
754 pub token: OAuthProviderRateLimit,
755 pub authorize: OAuthProviderRateLimit,
756 pub introspect: OAuthProviderRateLimit,
757 pub revoke: OAuthProviderRateLimit,
758 pub register: OAuthProviderRateLimit,
759 pub userinfo: OAuthProviderRateLimit,
760}
761
762impl Default for OAuthProviderRateLimits {
763 fn default() -> Self {
764 Self {
765 token: OAuthProviderRateLimit::Default,
766 authorize: OAuthProviderRateLimit::Default,
767 introspect: OAuthProviderRateLimit::Default,
768 revoke: OAuthProviderRateLimit::Default,
769 register: OAuthProviderRateLimit::Default,
770 userinfo: OAuthProviderRateLimit::Default,
771 }
772 }
773}
774
775#[derive(Debug, Clone, PartialEq, Eq)]
777pub struct OAuthProviderOptions {
778 pub scopes: Vec<String>,
779 pub client_registration_default_scopes: Vec<String>,
780 pub client_registration_allowed_scopes: Vec<String>,
781 pub grant_types: Vec<GrantType>,
782 pub login_page: String,
783 pub consent_page: String,
784 pub signup_page: Option<String>,
785 pub select_account_page: Option<String>,
786 pub post_login_page: Option<String>,
787 pub signup_redirect: Option<PromptRedirectResolver>,
788 pub select_account_redirect: Option<PromptRedirectResolver>,
789 pub post_login_redirect: Option<PromptRedirectResolver>,
790 pub code_expires_in: u64,
791 pub access_token_expires_in: u64,
792 pub m2m_access_token_expires_in: u64,
793 pub id_token_expires_in: u64,
794 pub refresh_token_expires_in: u64,
795 pub client_credential_grant_default_scopes: Vec<String>,
796 pub scope_expirations: BTreeMap<String, u64>,
797 pub client_registration_client_secret_expiration: Option<u64>,
798 pub allow_unauthenticated_client_registration: bool,
799 pub allow_dynamic_client_registration: bool,
800 pub allow_public_client_prelogin: bool,
801 pub cached_trusted_clients: BTreeSet<String>,
802 pub client_reference: Option<ClientReferenceResolver>,
803 pub client_privileges: Option<ClientPrivilegesResolver>,
804 pub custom_access_token_claims: Option<CustomAccessTokenClaimsResolver>,
805 pub custom_id_token_claims: Option<CustomIdTokenClaimsResolver>,
806 pub custom_token_response_fields: Option<CustomTokenResponseFieldsResolver>,
807 pub custom_userinfo_claims: Option<CustomUserInfoClaimsResolver>,
808 pub request_uri_resolver: Option<RequestUriResolver>,
809 pub prefixes: OAuthTokenPrefixes,
810 pub generate_client_id: Option<StringGeneratorResolver>,
811 pub generate_client_secret: Option<StringGeneratorResolver>,
812 pub generate_opaque_access_token: Option<StringGeneratorResolver>,
813 pub generate_refresh_token: Option<StringGeneratorResolver>,
814 pub format_refresh_token: Option<RefreshTokenFormatter>,
815 pub disable_jwt_plugin: bool,
816 pub store_client_secret: SecretStorage,
817 pub store_tokens: SecretStorage,
818 pub hash_client_secret: Option<ClientSecretHashResolver>,
819 pub verify_client_secret_hash: Option<ClientSecretVerifyResolver>,
820 pub hash_token: Option<TokenHashResolver>,
821 pub pairwise_secret: Option<String>,
822 pub advertised_scopes_supported: Vec<String>,
823 pub advertised_claims_supported: Vec<String>,
824 pub valid_audiences: Vec<String>,
825 pub rate_limits: OAuthProviderRateLimits,
826}
827
828impl Default for OAuthProviderOptions {
829 fn default() -> Self {
830 Self {
831 scopes: Vec::new(),
832 client_registration_default_scopes: Vec::new(),
833 client_registration_allowed_scopes: Vec::new(),
834 grant_types: Vec::new(),
835 login_page: String::new(),
836 consent_page: String::new(),
837 signup_page: None,
838 select_account_page: None,
839 post_login_page: None,
840 signup_redirect: None,
841 select_account_redirect: None,
842 post_login_redirect: None,
843 code_expires_in: 600,
844 access_token_expires_in: 3600,
845 m2m_access_token_expires_in: 3600,
846 id_token_expires_in: 36000,
847 refresh_token_expires_in: 2_592_000,
848 client_credential_grant_default_scopes: Vec::new(),
849 scope_expirations: BTreeMap::new(),
850 client_registration_client_secret_expiration: None,
851 allow_unauthenticated_client_registration: false,
852 allow_dynamic_client_registration: false,
853 allow_public_client_prelogin: false,
854 cached_trusted_clients: BTreeSet::new(),
855 client_reference: None,
856 client_privileges: None,
857 custom_access_token_claims: None,
858 custom_id_token_claims: None,
859 custom_token_response_fields: None,
860 custom_userinfo_claims: None,
861 request_uri_resolver: None,
862 prefixes: OAuthTokenPrefixes::default(),
863 generate_client_id: None,
864 generate_client_secret: None,
865 generate_opaque_access_token: None,
866 generate_refresh_token: None,
867 format_refresh_token: None,
868 disable_jwt_plugin: false,
869 store_client_secret: SecretStorage::Auto,
870 store_tokens: SecretStorage::Hashed,
871 hash_client_secret: None,
872 verify_client_secret_hash: None,
873 hash_token: None,
874 pairwise_secret: None,
875 advertised_scopes_supported: Vec::new(),
876 advertised_claims_supported: Vec::new(),
877 valid_audiences: Vec::new(),
878 rate_limits: OAuthProviderRateLimits::default(),
879 }
880 }
881}
882
883#[derive(Debug, Clone, PartialEq, Eq)]
885pub struct ResolvedOAuthProviderOptions {
886 pub scopes: Vec<String>,
887 pub claims: Vec<String>,
888 pub client_registration_allowed_scopes: Vec<String>,
889 pub grant_types: Vec<GrantType>,
890 pub login_page: String,
891 pub consent_page: String,
892 pub signup_page: Option<String>,
893 pub select_account_page: Option<String>,
894 pub post_login_page: Option<String>,
895 pub signup_redirect: Option<PromptRedirectResolver>,
896 pub select_account_redirect: Option<PromptRedirectResolver>,
897 pub post_login_redirect: Option<PromptRedirectResolver>,
898 pub code_expires_in: u64,
899 pub access_token_expires_in: u64,
900 pub m2m_access_token_expires_in: u64,
901 pub id_token_expires_in: u64,
902 pub refresh_token_expires_in: u64,
903 pub client_credential_grant_default_scopes: Vec<String>,
904 pub scope_expirations: BTreeMap<String, u64>,
905 pub client_registration_default_scopes: Vec<String>,
906 pub client_registration_client_secret_expiration: Option<u64>,
907 pub allow_unauthenticated_client_registration: bool,
908 pub allow_dynamic_client_registration: bool,
909 pub allow_public_client_prelogin: bool,
910 pub cached_trusted_clients: BTreeSet<String>,
911 pub trusted_client_cache: TrustedClientCache,
912 pub client_reference: Option<ClientReferenceResolver>,
913 pub client_privileges: Option<ClientPrivilegesResolver>,
914 pub custom_access_token_claims: Option<CustomAccessTokenClaimsResolver>,
915 pub custom_id_token_claims: Option<CustomIdTokenClaimsResolver>,
916 pub custom_token_response_fields: Option<CustomTokenResponseFieldsResolver>,
917 pub custom_userinfo_claims: Option<CustomUserInfoClaimsResolver>,
918 pub request_uri_resolver: Option<RequestUriResolver>,
919 pub prefixes: OAuthTokenPrefixes,
920 pub generate_client_id: Option<StringGeneratorResolver>,
921 pub generate_client_secret: Option<StringGeneratorResolver>,
922 pub generate_opaque_access_token: Option<StringGeneratorResolver>,
923 pub generate_refresh_token: Option<StringGeneratorResolver>,
924 pub format_refresh_token: Option<RefreshTokenFormatter>,
925 pub disable_jwt_plugin: bool,
926 pub store_client_secret: SecretStorage,
927 pub store_tokens: SecretStorage,
928 pub hash_client_secret: Option<ClientSecretHashResolver>,
929 pub verify_client_secret_hash: Option<ClientSecretVerifyResolver>,
930 pub hash_token: Option<TokenHashResolver>,
931 pub pairwise_secret: Option<String>,
932 pub advertised_scopes_supported: Vec<String>,
933 pub advertised_claims_supported: Vec<String>,
934 pub valid_audiences: Vec<String>,
935 pub rate_limits: OAuthProviderRateLimits,
936}
937
938#[derive(Debug, Clone)]
940pub struct OAuthProviderPlugin {
941 pub id: String,
942 pub version: String,
943 pub options: ResolvedOAuthProviderOptions,
944 pub(crate) auth_plugin: AuthPlugin,
945}
946
947impl OAuthProviderPlugin {
948 pub fn into_auth_plugin(self) -> AuthPlugin {
950 self.auth_plugin
951 }
952
953 pub fn as_auth_plugin(&self) -> &AuthPlugin {
955 &self.auth_plugin
956 }
957}
958
959#[derive(Debug, Clone, PartialEq, Eq, Error)]
961pub enum OAuthProviderConfigError {
962 #[error("login_page is required")]
963 MissingLoginPage,
964 #[error("consent_page is required")]
965 MissingConsentPage,
966 #[error("clientRegistrationAllowedScope {0} not found in scopes")]
967 UnknownClientRegistrationScope(String),
968 #[error("clientCredentialGrantDefaultScopes {0} not found in scopes")]
969 UnknownClientCredentialGrantScope(String),
970 #[error("advertisedMetadata.scopes_supported {0} not found in scopes")]
971 UnknownAdvertisedScope(String),
972 #[error(
973 "pairwiseSecret must be at least 32 characters long for adequate HMAC-SHA256 security"
974 )]
975 PairwiseSecretTooShort,
976 #[error("refresh_token grant requires authorization_code grant")]
977 RefreshTokenRequiresAuthorizationCode,
978 #[error("unable to store hashed secrets because id tokens will be signed with secret")]
979 HashedClientSecretsRequireJwtPlugin,
980 #[error("encryption method not recommended, please use 'hashed' or the 'hash' function")]
981 EncryptedClientSecretsWithJwtPlugin,
982 #[error("unable to initialize jwt plugin: {0}")]
983 JwtPlugin(String),
984}