1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
use kittybox_indieauth::{AuthorizationRequest, TokenData};
pub use kittybox_util::auth::EnrolledCredential;
use std::collections::HashMap;
use std::future::Future;
type Result<T> = std::io::Result<T>;
pub mod fs;
pub use fs::FileBackend;
pub trait AuthBackend: Clone + Send + Sync + 'static {
/// Initialize self from URL, possibly performing initialization.
fn new(url: &'_ url::Url) -> impl Future<Output = Result<Self>> + Send;
// Authorization code management.
/// Create a one-time OAuth2 authorization code for the passed
/// authorization request, and save it for later retrieval.
///
/// Note for implementors: the [`AuthorizationRequest::me`] value
/// is guaranteed to be [`Some(url::Url)`][Option::Some] and can
/// be trusted to be correct and non-malicious.
fn create_code(
&self,
data: AuthorizationRequest,
) -> impl Future<Output = Result<String>> + Send;
/// Retreive an authorization request using the one-time
/// code. Implementations must sanitize the `code` field to
/// prevent exploits, and must check if the code should still be
/// valid at this point in time (validity interval is left up to
/// the implementation, but is recommended to be no more than 10
/// minutes).
fn get_code(
&self,
code: &str,
) -> impl Future<Output = Result<Option<AuthorizationRequest>>> + Send;
// Token management.
fn create_token(&self, data: TokenData) -> impl Future<Output = Result<String>> + Send;
fn get_token(
&self,
website: &url::Url,
token: &str,
) -> impl Future<Output = Result<Option<TokenData>>> + Send;
fn list_tokens(
&self,
website: &url::Url,
) -> impl Future<Output = Result<HashMap<String, TokenData>>> + Send;
fn revoke_token(
&self,
website: &url::Url,
token: &str,
) -> impl Future<Output = Result<()>> + Send;
// Refresh token management.
fn create_refresh_token(&self, data: TokenData) -> impl Future<Output = Result<String>> + Send;
fn get_refresh_token(
&self,
website: &url::Url,
token: &str,
) -> impl Future<Output = Result<Option<TokenData>>> + Send;
fn list_refresh_tokens(
&self,
website: &url::Url,
) -> impl Future<Output = Result<HashMap<String, TokenData>>> + Send;
fn revoke_refresh_token(
&self,
website: &url::Url,
token: &str,
) -> impl Future<Output = Result<()>> + Send;
// Password management.
/// Verify a password.
#[must_use]
fn verify_password(
&self,
website: &url::Url,
password: String,
) -> impl Future<Output = Result<bool>> + Send;
/// Enroll a password credential for a user. Only one password
/// credential must exist for a given user.
fn enroll_password(
&self,
website: &url::Url,
password: String,
) -> impl Future<Output = Result<()>> + Send;
/// List currently enrolled credential types for a given user.
fn list_user_credential_types(
&self,
website: &url::Url,
) -> impl Future<Output = Result<Vec<EnrolledCredential>>> + Send;
// WebAuthn credential management.
#[cfg(feature = "webauthn")]
/// Enroll a WebAuthn authenticator public key for this user.
/// Multiple public keys may be saved for one user, corresponding
/// to different authenticators used by them.
///
/// This function can also be used to overwrite a passkey with an
/// updated version after using
/// [webauthn::prelude::Passkey::update_credential()].
fn enroll_webauthn(
&self,
website: &url::Url,
credential: webauthn::prelude::Passkey,
) -> impl Future<Output = Result<()>> + Send;
#[cfg(feature = "webauthn")]
/// List currently enrolled WebAuthn authenticators for a given user.
fn list_webauthn_pubkeys(
&self,
website: &url::Url,
) -> impl Future<Output = Result<Vec<webauthn::prelude::Passkey>>> + Send;
#[cfg(feature = "webauthn")]
/// Persist registration challenge state for a little while so it
/// can be used later.
///
/// Challenges saved in this manner MUST expire after a little
/// while. 10 minutes is recommended.
fn persist_registration_challenge(
&self,
website: &url::Url,
state: webauthn::prelude::PasskeyRegistration,
) -> impl Future<Output = Result<String>> + Send;
#[cfg(feature = "webauthn")]
/// Retrieve a persisted registration challenge.
///
/// The challenge should be deleted after retrieval.
fn retrieve_registration_challenge(
&self,
website: &url::Url,
challenge_id: &str,
) -> impl Future<Output = Result<webauthn::prelude::PasskeyRegistration>> + Send;
#[cfg(feature = "webauthn")]
/// Persist authentication challenge state for a little while so
/// it can be used later.
///
/// Challenges saved in this manner MUST expire after a little
/// while. 10 minutes is recommended.
///
/// To support multiple authentication options, this can return an
/// opaque token that should be set as a cookie.
fn persist_authentication_challenge(
&self,
website: &url::Url,
state: webauthn::prelude::PasskeyAuthentication,
) -> impl Future<Output = Result<String>> + Send;
#[cfg(feature = "webauthn")]
/// Retrieve a persisted authentication challenge.
///
/// The challenge should be deleted after retrieval.
fn retrieve_authentication_challenge(
&self,
website: &url::Url,
challenge_id: &str,
) -> impl Future<Output = Result<webauthn::prelude::PasskeyAuthentication>> + Send;
}
|