From 65ca0b4fd307b7ea4a4d86814577aaa145a501c1 Mon Sep 17 00:00:00 2001 From: Matthew Scheirer Date: Tue, 19 Sep 2017 11:54:57 -0400 Subject: [PATCH] More docs more defaults --- src/lib.rs | 63 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 616d7ac..400f5aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,8 @@ //! There are two ways to interact with this library - the batteries included magic methods, and //! the slightly more boilerplate but more fine grained ones. For most users the following is what //! you want. -//! ``` +//! +//! ```rust,ignore //! use oidc; //! use reqwest; //! use std::default::Default; @@ -21,11 +22,13 @@ //! //! let token = client.authenticate(auth_code, Options::default())?; //! ``` +//! //! That example leaves you with a decoded `Token` that has been validated. Your user is //! authenticated! //! //! You can also take a more nuanced approach that gives you more fine grained control: -//! ``` +//! +//! ```rust,ignore //! use oidc; //! use reqwest; //! use std::default::Default; @@ -51,13 +54,16 @@ //! //! let userinfo = client.request_userinfo(&http, &token)?; //! ``` +//! //! This more complicated version uses the discovery module directly. Important distinctions to make //! between the two: +//! //! - The complex pattern avoids constructing a new reqwest client every time an outbound method is //! called. Especially for token decoding having to rebuild reqwest every time can be a large //! performance penalty. //! - Tokens don't come decoded or validated. You need to do both manually. //! - This version demonstrates userinfo. It is not required by spec, so make sure its available! + extern crate base64; extern crate biscuit; extern crate chrono; @@ -113,6 +119,7 @@ macro_rules! wrong_key { ) } +/// OpenID Connect Client for a provider specified at construction. impl Client { /// Constructs a client from an issuer url and client parameters via discovery pub fn discover(id: String, secret: String, redirect: Url, issuer: Url) -> Result { @@ -126,7 +133,8 @@ impl Client { /// Constructs a client from a given provider, key set, and parameters. Unlike ::discover(..) /// this function does not perform any network operations. - pub fn new(id: String, secret: String, redirect: Url, provider: Discovered, jwks: JWKSet) -> Self { + pub fn new(id: String, secret: + String, redirect: Url, provider: Discovered, jwks: JWKSet) -> Self { Client { oauth: inth_oauth2::Client::new( provider, @@ -320,7 +328,9 @@ impl Client { panic!("chrono::Utc::now() can never be before this was written!") } if claims.exp <= now.timestamp() { - return Err(Validation::Expired(Expiry::Expires(chrono::naive::NaiveDateTime::from_timestamp(claims.exp, 0))).into()); + return Err(Validation::Expired( + Expiry::Expires( + chrono::naive::NaiveDateTime::from_timestamp(claims.exp, 0))).into()); } if let Some(max) = max_age { @@ -338,7 +348,8 @@ impl Client { Ok(()) } - pub fn request_userinfo(&self, client: &reqwest::Client, token: &Token) -> Result { + pub fn request_userinfo(&self, client: &reqwest::Client, token: &Token + ) -> Result { match self.config().userinfo_endpoint { Some(ref url) => { discovery::secure(&url)?; @@ -386,34 +397,30 @@ pub struct Options { #[derive(Deserialize, Validate)] pub struct Userinfo { pub sub: String, - pub name: Option, - pub given_name: Option, - pub family_name: Option, - pub middle_name: Option, - pub nickname: Option, - pub preferred_username: Option, - #[serde(with = "url_serde")] - pub profile: Option, - #[serde(with = "url_serde")] - pub picture: Option, - #[serde(with = "url_serde")] - pub website: Option, - #[validate(email)] - pub email: Option, - pub email_verified: Option, + #[serde(default)] pub name: Option, + #[serde(default)] pub given_name: Option, + #[serde(default)] pub family_name: Option, + #[serde(default)] pub middle_name: Option, + #[serde(default)] pub nickname: Option, + #[serde(default)] pub preferred_username: Option, + #[serde(default)] #[serde(with = "url_serde")] pub profile: Option, + #[serde(default)] #[serde(with = "url_serde")] pub picture: Option, + #[serde(default)] #[serde(with = "url_serde")] pub website: Option, + #[serde(default)] #[validate(email)] pub email: Option, + #[serde(default)] pub email_verified: Option, // Isn't required to be just male or female - pub gender: Option, + #[serde(default)] pub gender: Option, // ISO 9601:2004 YYYY-MM-DD or YYYY. Would be nice to serialize to chrono::Date. - pub birthdate: Option, + #[serde(default)] pub birthdate: Option, // Region/City codes. Should also have a more concrete serializer form. - pub zoneinfo: Option, + #[serde(default)] pub zoneinfo: Option, // Usually RFC5646 langcode-countrycode, maybe with a _ sep, could be arbitrary - pub locale: Option, + #[serde(default)] pub locale: Option, // Usually E.164 format number - pub phone_number: Option, - pub phone_number_verified: Option, - pub address: Option
, - pub updated_at: Option, + #[serde(default)] pub phone_number: Option, + #[serde(default)] pub phone_number_verified: Option, + #[serde(default)] pub address: Option
, + #[serde(default)] pub updated_at: Option, } pub enum Display {