First complete impl without warns

This commit is contained in:
Matthew Scheirer 2017-09-16 21:28:55 -04:00
parent 08d7765644
commit 6b69d34ac8
5 changed files with 39 additions and 27 deletions

View File

@ -4,7 +4,8 @@ use biscuit::jwk::{AlgorithmParameters, JWKSet};
use biscuit::jws::{Compact, Secret};
use chrono::{Duration, Utc};
use inth_oauth2;
use reqwest::{self, Url};
use inth_oauth2::token::Token as _t;
use reqwest::{self, header, Url};
use url_serde;
use validator::Validate;
@ -12,7 +13,7 @@ use std::collections::HashSet;
use discovery::{self, Config, Discovered};
use error::{self, Decode, Error, Expiry, Mismatch, Missing, Validation};
use token::{Claims, Expiring, Token};
use token::{Claims, Token};
type IdToken = Compact<Claims, Empty>;
@ -165,7 +166,7 @@ impl Client {
pub fn request_token(&self,
client: &reqwest::Client,
auth_code: &str,
) -> Result<Token<Expiring>, error::Oauth> {
) -> Result<Token, error::Oauth> {
self.oauth.request_token(client, auth_code)
}
@ -218,7 +219,7 @@ impl Client {
/// Given an auth_code and auth options, request the token, decode, and validate it.
pub fn authenticate(&self, auth_code: &str, options: &Options
) -> Result<Token<Expiring>, Error> {
) -> Result<Token, Error> {
let client = reqwest::Client::new()?;
let mut token = self.request_token(&client, auth_code)?;
self.decode_token(&mut token.id_token)?;
@ -347,13 +348,22 @@ impl Client {
Ok(())
}
pub fn request_userinfo(&self, client: &reqwest::Client, token: &Token<Expiring>) -> Result<Userinfo, Error> {
pub fn request_userinfo(&self, client: &reqwest::Client, token: &Token) -> Result<Userinfo, Error> {
match self.config().userinfo_endpoint {
Some(ref url) => {
discovery::secure(&url)?;
if url.origin() != self.config().issuer.origin() {
return Err(error::Userinfo::MismatchIssuer.into());
}
unimplemented!()
let claims = token.id_token.payload()?;
let auth_code = token.access_token().to_string();
let mut resp = client.get(url.clone())?
.header(header::Authorization(header::Bearer { token: auth_code })).send()?;
let info: Userinfo = resp.json()?;
if claims.sub != info.sub {
return Err(error::Userinfo::MismatchSubject.into())
}
Ok(info)
}
None => Err(error::Userinfo::NoUrl.into())
}

View File

@ -1,12 +1,21 @@
use biscuit::Empty;
use biscuit::jwk::JWKSet;
use inth_oauth2::provider::Provider;
use inth_oauth2::token::Expiring;
use reqwest::{Client, Url};
use url_serde;
use validator::Validate;
use error::Error;
use token::{Expiring, Token};
use token::Token;
pub(crate) fn secure(url: &Url) -> Result<(), Error> {
if url.scheme() != "https" {
Err(Error::Insecure)
} else {
Ok(())
}
}
#[derive(Deserialize, Serialize)]
pub struct Config {
@ -114,7 +123,7 @@ pub struct Discovered {
impl Provider for Discovered {
type Lifetime = Expiring;
type Token = Token<Expiring>;
type Token = Token;
fn auth_uri(&self) -> &str {
self.config.authorization_endpoint.as_ref()
}
@ -127,10 +136,7 @@ impl Provider for Discovered {
/// Get the discovery config document from the given issuer url. Errors are either a reqwest error
/// or an Insecure if the Url isn't https.
pub fn discover(client: &Client, issuer: Url) -> Result<Config, Error> {
if issuer.scheme() != "https" {
return Err(Error::Insecure)
}
secure(&issuer)?;
let mut resp = client.get(issuer)?.send()?;
resp.json().map_err(Error::from)
}
@ -138,10 +144,7 @@ pub fn discover(client: &Client, issuer: Url) -> Result<Config, Error> {
/// Get the JWK set from the given Url. Errors are either a reqwest error or an Insecure error if
/// the url isn't https.
pub fn jwks(client: &Client, url: Url) -> Result<JWKSet<Empty>, Error> {
if url.scheme() != "https" {
return Err(Error::Insecure)
}
secure(&url)?;
let mut resp = client.get(url)?.send()?;
resp.json().map_err(Error::from)
}

View File

@ -71,6 +71,6 @@ pub enum Expiry {
#[derive(Debug)]
pub enum Userinfo {
NoUrl,
MismatchIssuer,
MismatchSubject,
}

View File

@ -3,6 +3,8 @@ extern crate biscuit;
extern crate chrono;
extern crate inth_oauth2;
extern crate reqwest;
// We never use serde, but serde_derive needs it here
#[allow(unused_extern_crates)]
extern crate serde;
#[macro_use]
extern crate serde_derive;

View File

@ -2,14 +2,11 @@ use base64;
use biscuit::{CompactJson, Empty, SingleOrMultiple};
use biscuit::jws::Compact;
use inth_oauth2::client::response::{FromResponse, ParseError};
use inth_oauth2::token::{self, Bearer, Lifetime};
use inth_oauth2::token::{self, Bearer, Expiring};
use reqwest::Url;
use serde_json::Value;
use url_serde;
/// Rexported lifetime token types from oauth
pub use inth_oauth2::token::{Expiring, Refresh, Static};
type IdToken = Compact<Claims, Empty>;
#[derive(Serialize, Deserialize)]
@ -60,12 +57,12 @@ impl CompactJson for Claims {}
/// An OpenID Connect token. This is the only token allowed by spec.
/// Has an access_token for bearer, and the id_token for authentication.
/// Wraps an oauth bearer token.
pub struct Token<L: Lifetime> {
bearer: Bearer<L>,
pub struct Token {
bearer: Bearer<Expiring>,
pub id_token: IdToken,
}
impl<L: Lifetime> Token<L> {
impl Token {
// Takes a json response object and parses out the id token
// TODO Support extracting a jwe token according to spec. Right now we only support jws tokens.
fn id_token(json: &Value) -> Result<IdToken, ParseError> {
@ -77,19 +74,19 @@ impl<L: Lifetime> Token<L> {
}
}
impl<L: Lifetime> token::Token<L> for Token<L> {
impl token::Token<Expiring> for Token {
fn access_token(&self) -> &str {
self.bearer.access_token()
}
fn scope(&self) -> Option<&str> {
self.bearer.scope()
}
fn lifetime(&self) -> &L {
fn lifetime(&self) -> &Expiring {
self.bearer.lifetime()
}
}
impl<L: Lifetime> FromResponse for Token<L> {
impl FromResponse for Token {
fn from_response(json: &Value) -> Result<Self, ParseError> {
let bearer = Bearer::from_response(json)?;
let id_token = Self::id_token(json)?;