oauth2_types/webfinger.rs
1// Copyright 2022 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Types for provider discovery using [Webfinger].
16//!
17//! [Webfinger]: https://www.rfc-editor.org/rfc/rfc7033
18
19use serde::{Deserialize, Serialize};
20use url::Url;
21
22/// The response of the Webfinger endpoint.
23#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
24pub struct WebFingerResponse {
25 /// A URI that identifies the entity described by the response.
26 subject: String,
27
28 /// Links that describe the subject.
29 links: Vec<WebFingerLink>,
30}
31
32impl WebFingerResponse {
33 /// Creates a new `WebFingerResponse` with the given subject.
34 #[must_use]
35 pub const fn new(subject: String) -> Self {
36 Self {
37 subject,
38 links: Vec::new(),
39 }
40 }
41
42 /// Adds the given link to this `WebFingerResponse`.
43 #[must_use]
44 pub fn with_link(mut self, link: WebFingerLink) -> Self {
45 self.links.push(link);
46 self
47 }
48
49 /// Adds the given issuer to this `WebFingerResponse`.
50 #[must_use]
51 pub fn with_issuer(self, issuer: Url) -> Self {
52 self.with_link(WebFingerLink::issuer(issuer))
53 }
54}
55
56/// A link in a Webfinger response.
57#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
58#[serde(tag = "rel")]
59pub enum WebFingerLink {
60 /// An OpenID Connect issuer.
61 #[serde(rename = "http://openid.net/specs/connect/1.0/issuer")]
62 OidcIssuer {
63 /// The URL of the issuer.
64 href: Url,
65 },
66}
67
68impl WebFingerLink {
69 /// Creates a new `WebFingerLink` for an OpenID Connect issuer.
70 #[must_use]
71 pub const fn issuer(href: Url) -> Self {
72 Self::OidcIssuer { href }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use serde_json::json;
79
80 use super::*;
81
82 #[test]
83 fn serialize_webfinger_response_test() {
84 let res = WebFingerResponse::new("acct:john@example.com".to_owned())
85 .with_issuer(Url::parse("https://account.example.com/").unwrap());
86
87 let res = serde_json::to_value(res).unwrap();
88
89 assert_eq!(
90 res,
91 json!({
92 "subject": "acct:john@example.com",
93 "links": [{
94 "rel": "http://openid.net/specs/connect/1.0/issuer",
95 "href": "https://account.example.com/",
96 }]
97 })
98 );
99 }
100}