auth0 0.3.0

Auth0 API library
Documentation
use crate::authentication::Api;
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
use reqwest::RequestBuilder;
pub use serde::{Deserialize, Serialize};

pub mod authorization_code_flow;
pub mod authorization_code_flow_with_pkce;
pub mod client_credentials_flow;
pub mod device_authorization_flow;
pub mod refresh_token;
pub mod resource_owner_password;
pub mod token_exchange_for_native_social;

pub trait GetToken {
    fn authorization_code_flow(
        &self,
        request: authorization_code_flow::RequestParameters,
    ) -> RequestBuilder;

    fn authorization_code_flow_with_pkce(
        &self,
        request: authorization_code_flow_with_pkce::RequestParameters,
    ) -> RequestBuilder;

    fn client_credentials_flow(
        &self,
        request: client_credentials_flow::RequestParameters,
    ) -> RequestBuilder;

    fn resource_owner_password(
        &self,
        request: resource_owner_password::RequestParameters,
    ) -> RequestBuilder;

    fn device_authorization_flow(
        &self,
        request: device_authorization_flow::RequestParameters,
    ) -> RequestBuilder;

    fn refresh_token(&self, request: refresh_token::RequestParameters) -> RequestBuilder;

    fn token_exchange_for_native_social(
        &self,
        request: token_exchange_for_native_social::RequestParameters,
    ) -> RequestBuilder;
}

impl GetToken for Api {
    fn authorization_code_flow(
        &self,
        request: authorization_code_flow::RequestParameters,
    ) -> RequestBuilder {
        let endpoint = String::from("/oauth/token");
        let url = self.base_url.join(&endpoint).unwrap();

        self.client.post(url).form(&request)
    }

    fn authorization_code_flow_with_pkce(
        &self,
        request: authorization_code_flow_with_pkce::RequestParameters,
    ) -> RequestBuilder {
        let endpoint = String::from("/oauth/token");
        let url = self.base_url.join(&endpoint).unwrap();

        self.client.post(url).form(&request)
    }

    fn client_credentials_flow(
        &self,
        request: client_credentials_flow::RequestParameters,
    ) -> RequestBuilder {
        let endpoint = String::from("/oauth/token");
        let url = self.base_url.join(&endpoint).unwrap();

        self.client.post(url).form(&request)
    }

    fn resource_owner_password(
        &self,
        request: resource_owner_password::RequestParameters,
    ) -> RequestBuilder {
        let endpoint = String::from("/oauth/token");
        let url = self.base_url.join(&endpoint).unwrap();

        if request.auth0_forwarded_for.is_some() {
            let mut headers = HeaderMap::new();
            let header_key = String::from("auth0-forwarded-for");
            let header_value = &request.auth0_forwarded_for.as_ref().unwrap();
            headers.insert(
                HeaderName::from_bytes(header_key.as_bytes()).unwrap(),
                HeaderValue::from_bytes(header_value.as_bytes()).unwrap(),
            );
            self.client.post(url).headers(headers).form(&request)
        } else {
            self.client.post(url).form(&request)
        }
    }

    fn device_authorization_flow(
        &self,
        request: device_authorization_flow::RequestParameters,
    ) -> RequestBuilder {
        let endpoint = String::from("/oauth/token");
        let url = self.base_url.join(&endpoint).unwrap();

        self.client.post(url).form(&request)
    }

    fn refresh_token(&self, request: refresh_token::RequestParameters) -> RequestBuilder {
        let endpoint = String::from("/oauth/token");
        let url = self.base_url.join(&endpoint).unwrap();

        self.client.post(url).form(&request)
    }

    fn token_exchange_for_native_social(
        &self,
        request: token_exchange_for_native_social::RequestParameters,
    ) -> RequestBuilder {
        let endpoint = String::from("/oauth/token");
        let url = self.base_url.join(&endpoint).unwrap();

        if request.auth0_forwarded_for.is_some() {
            let mut headers = HeaderMap::new();
            let header_key = String::from("auth0-forwarded-for");
            let header_value = &request.auth0_forwarded_for.as_ref().unwrap();
            headers.insert(
                HeaderName::from_bytes(header_key.as_bytes()).unwrap(),
                HeaderValue::from_bytes(header_value.as_bytes()).unwrap(),
            );
            self.client.post(url).headers(headers).form(&request)
        } else {
            self.client.post(url).form(&request)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::authentication::*;

    #[test]
    fn authorization_code_flow_build_request() {
        let base_url = Url::parse("https://YOUR_DOMAIN").unwrap();
        let authentication = AuthenicationMethod::OAuth2Token(String::from("some_awesome_token"));
        let get_token = Api::init(base_url, authentication);
        let parameters = get_token::authorization_code_flow::RequestParameters {
            grant_type: String::from("some_awesome_grant"),
            client_id: String::from("some_awesome_client_id"),
            client_secret: String::from("some_awesome_client_secret"),
            code: String::from("some_awesome_code"),
            redirect_uri: None,
        };
        let request = get_token
            .authorization_code_flow(parameters)
            .build()
            .unwrap();
        let test_url = String::from("https://your_domain/oauth/token");
        let test_body = String::from(
            "grant_type=some_awesome_grant&\
            client_id=some_awesome_client_id&\
            client_secret=some_awesome_client_secret&\
            code=some_awesome_code",
        );
        assert_eq!(request.method().as_str(), reqwest::Method::POST);
        assert_eq!(request.url().as_str(), test_url);
        assert_eq!(request.headers().len(), 1);
        assert_eq!(
            request.body().unwrap().as_bytes().unwrap(),
            test_body.as_bytes(),
        );
    }

    #[test]
    fn authorization_code_flow_with_pkce_build_request() {
        let base_url = Url::parse("https://YOUR_DOMAIN").unwrap();
        let authentication = AuthenicationMethod::OAuth2Token(String::from("some_awesome_token"));
        let get_token = Api::init(base_url, authentication);
        let parameters = get_token::authorization_code_flow_with_pkce::RequestParameters {
            grant_type: String::from("some_awesome_grant"),
            client_id: String::from("some_awesome_client_id"),
            code: String::from("some_awesome_code"),
            code_verifier: String::from("some_awesome_code_verifier"),
            redirect_uri: None,
        };
        let request = get_token
            .authorization_code_flow_with_pkce(parameters)
            .build()
            .unwrap();
        let test_url = String::from("https://your_domain/oauth/token");
        let test_body = String::from(
            "grant_type=some_awesome_grant&\
            client_id=some_awesome_client_id&\
            code=some_awesome_code&\
            code_verifier=some_awesome_code_verifier",
        );
        assert_eq!(request.method().as_str(), reqwest::Method::POST);
        assert_eq!(request.url().as_str(), test_url);
        assert_eq!(request.headers().len(), 1);
        assert_eq!(
            request.body().unwrap().as_bytes().unwrap(),
            test_body.as_bytes(),
        );
    }

    #[test]
    fn client_credentials_flow_build_request() {
        let base_url = Url::parse("https://YOUR_DOMAIN").unwrap();
        let authentication = AuthenicationMethod::OAuth2Token(String::from("some_awesome_token"));
        let get_token = Api::init(base_url, authentication);
        let parameters = get_token::client_credentials_flow::RequestParameters {
            grant_type: String::from("some_awesome_grant_type"),
            client_id: String::from("some_awesome_client_id"),
            client_secret: String::from("some_awesome_client_secret"),
            audience: String::from("some_awesome_audience_api"),
        };
        let request = get_token
            .client_credentials_flow(parameters)
            .build()
            .unwrap();
        let test_url = String::from("https://your_domain/oauth/token");
        let test_body = String::from(
            "grant_type=some_awesome_grant_type&\
            client_id=some_awesome_client_id&\
            client_secret=some_awesome_client_secret&\
            audience=some_awesome_audience_api",
        );
        assert_eq!(request.method().as_str(), reqwest::Method::POST);
        assert_eq!(request.url().as_str(), test_url);
        assert_eq!(request.headers().len(), 1);
        assert_eq!(
            request.body().unwrap().as_bytes().unwrap(),
            test_body.as_bytes(),
        );
    }

    #[test]
    fn resource_owner_password_build_request() {
        let base_url = Url::parse("https://YOUR_DOMAIN").unwrap();
        let authentication = AuthenicationMethod::OAuth2Token(String::from("some_awesome_token"));
        let get_token = Api::init(base_url, authentication);
        let parameters = get_token::resource_owner_password::RequestParameters {
            grant_type: String::from("some_awesome_grant_type"),
            client_id: String::from("some_awesome_client_id"),
            client_secret: None,
            audience: None,
            username: String::from("some_awesome_username"),
            password: String::from("some_awesome_password"),
            scope: None,
            realm: None,
            auth0_forwarded_for: Some(String::from("some_ip_address")),
        };
        let request = get_token
            .resource_owner_password(parameters)
            .build()
            .unwrap();
        let test_url = String::from("https://your_domain/oauth/token");
        let test_body = String::from(
            "grant_type=some_awesome_grant_type&\
            client_id=some_awesome_client_id&\
            username=some_awesome_username&\
            password=some_awesome_password&\
            auth0_forwarded_for=some_ip_address",
        );
        assert_eq!(request.method().as_str(), reqwest::Method::POST);
        assert_eq!(request.url().as_str(), test_url);
        assert_eq!(request.headers().len(), 2);
        assert_eq!(
            request.body().unwrap().as_bytes().unwrap(),
            test_body.as_bytes(),
        );
    }

    #[test]
    fn device_authorization_flow_build_request() {
        let base_url = Url::parse("https://YOUR_DOMAIN").unwrap();
        let authentication = AuthenicationMethod::OAuth2Token(String::from("some_awesome_token"));
        let get_token = Api::init(base_url, authentication);
        let parameters = get_token::device_authorization_flow::RequestParameters {
            grant_type: String::from("some_awesome_grant_type"),
            client_id: String::from("some_awesome_client_id"),
            device_code: String::from("some_awesome_device_code"),
        };
        let request = get_token
            .device_authorization_flow(parameters)
            .build()
            .unwrap();
        let test_url = String::from("https://your_domain/oauth/token");
        let test_body = String::from(
            "grant_type=some_awesome_grant_type&\
            client_id=some_awesome_client_id&\
            device_code=some_awesome_device_code",
        );
        assert_eq!(request.method().as_str(), reqwest::Method::POST);
        assert_eq!(request.url().as_str(), test_url);
        assert_eq!(request.headers().len(), 1);
        assert_eq!(
            request.body().unwrap().as_bytes().unwrap(),
            test_body.as_bytes(),
        );
    }

    #[test]
    fn refresh_token_build_request() {
        let base_url = Url::parse("https://YOUR_DOMAIN").unwrap();
        let authentication = AuthenicationMethod::OAuth2Token(String::from("some_awesome_token"));
        let get_token = Api::init(base_url, authentication);
        let parameters = get_token::refresh_token::RequestParameters {
            grant_type: String::from("some_awesome_grant_type"),
            client_id: String::from("some_awesome_client_id"),
            client_secret: None,
            refresh_token: String::from("some_awesome_refresh_token"),
            scope: None,
        };
        let request = get_token.refresh_token(parameters).build().unwrap();
        let test_url = String::from("https://your_domain/oauth/token");
        let test_body = String::from(
            "grant_type=some_awesome_grant_type&\
            client_id=some_awesome_client_id&\
            refresh_token=some_awesome_refresh_token",
        );
        assert_eq!(request.method().as_str(), reqwest::Method::POST);
        assert_eq!(request.url().as_str(), test_url);
        assert_eq!(request.headers().len(), 1);
        assert_eq!(
            request.body().unwrap().as_bytes().unwrap(),
            test_body.as_bytes(),
        );
    }

    #[test]
    fn token_exchange_build_request() {
        let base_url = Url::parse("https://YOUR_DOMAIN").unwrap();
        let authentication = AuthenicationMethod::OAuth2Token(String::from("some_awesome_token"));
        let get_token = Api::init(base_url, authentication);
        let parameters = get_token::token_exchange_for_native_social::RequestParameters {
            grant_type: String::from("some_awesome_grant_type"),
            subject_token: String::from("some_awesome_subject_token"),
            subject_token_type: String::from("some_awesome_subject_token_type"),
            client_id: String::from("some_awesome_client_id"),
            audience: None,
            scope: None,
            auth0_forwarded_for: None,
        };
        let request = get_token
            .token_exchange_for_native_social(parameters)
            .build()
            .unwrap();
        let test_url = String::from("https://your_domain/oauth/token");
        let test_body = String::from(
            "grant_type=some_awesome_grant_type&\
            subject_token=some_awesome_subject_token&\
            subject_token_type=some_awesome_subject_token_type&\
            client_id=some_awesome_client_id",
        );
        assert_eq!(request.method().as_str(), reqwest::Method::POST);
        assert_eq!(request.url().as_str(), test_url);
        assert_eq!(request.headers().len(), 1);
        assert_eq!(
            request.body().unwrap().as_bytes().unwrap(),
            test_body.as_bytes(),
        );
    }
}