First complete impl without warns
This commit is contained in:
parent
08d7765644
commit
6b69d34ac8
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -71,6 +71,6 @@ pub enum Expiry {
|
|||
#[derive(Debug)]
|
||||
pub enum Userinfo {
|
||||
NoUrl,
|
||||
MismatchIssuer,
|
||||
MismatchSubject,
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
17
src/token.rs
17
src/token.rs
|
@ -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)?;
|
||||
|
|
Loading…
Reference in New Issue