mcp_kit/auth/identity.rs
1use std::collections::HashMap;
2
3/// The result of a successful authentication.
4///
5/// An `AuthenticatedIdentity` is stored in the [`Session`] after the transport
6/// layer validates the incoming credentials. Handlers that declare an [`Auth`]
7/// extractor receive a clone of this value.
8///
9/// [`Session`]: crate::server::session::Session
10/// [`Auth`]: crate::server::extract::Auth
11#[derive(Debug, Clone)]
12pub struct AuthenticatedIdentity {
13 /// Stable subject identifier — e.g. a username, client ID, or JWT `sub` claim.
14 pub subject: String,
15
16 /// Scopes / roles granted to this identity (e.g. `["tools:execute", "admin"]`).
17 pub scopes: Vec<String>,
18
19 /// Arbitrary key-value metadata attached during authentication.
20 /// Examples: OAuth2 claims, certificate CN, tenant ID.
21 pub metadata: HashMap<String, serde_json::Value>,
22}
23
24impl AuthenticatedIdentity {
25 /// Create a new identity with the given subject and no scopes or metadata.
26 pub fn new(subject: impl Into<String>) -> Self {
27 Self {
28 subject: subject.into(),
29 scopes: Vec::new(),
30 metadata: HashMap::new(),
31 }
32 }
33
34 /// Builder: attach scopes to this identity.
35 pub fn with_scopes(mut self, scopes: impl IntoIterator<Item = impl Into<String>>) -> Self {
36 self.scopes = scopes.into_iter().map(Into::into).collect();
37 self
38 }
39
40 /// Builder: attach a single metadata key-value pair.
41 pub fn with_meta(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
42 self.metadata.insert(key.into(), value);
43 self
44 }
45
46 /// Returns `true` if this identity has the given scope.
47 pub fn has_scope(&self, scope: &str) -> bool {
48 self.scopes.iter().any(|s| s == scope)
49 }
50
51 /// Returns `true` if this identity has **all** of the given scopes.
52 pub fn has_all_scopes(&self, scopes: &[&str]) -> bool {
53 scopes.iter().all(|s| self.has_scope(s))
54 }
55}