Skip to content
Snippets Groups Projects
oauth.rs 4.37 KiB
Newer Older
/* Copyright 2021 Dominik George <dominik.george@teckids.org>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use crate::config::{
    get_or_error,
    get_optional
};

use config::Config;

use oauth2::{
    AuthUrl,
    ClientId,
    ClientSecret,
    RequestTokenError,
    ResourceOwnerUsername,
    ResourceOwnerPassword,
    Scope,
    TokenUrl
};
use oauth2::basic::{
    BasicClient,
    BasicTokenResponse
};
use oauth2::reqwest::http_client;

fn full_key(prefix: &str, key: &str) -> String {
    let parts = vec![prefix.to_string(), key.to_string()];
    let full_key = parts.join(".");
    return full_key;
}

fn get_client<E: Copy>(conf: Config, prefix: &str, error_value: E) -> Result<BasicClient, E> {
    let client_id = ClientId::new(get_or_error(&conf, &full_key(prefix, "client_secret"), error_value)?);
    let client_secret = match get_optional(&conf, &full_key(prefix, "client_secret")) {
        Some(v) => Some(ClientSecret::new(v)),
        None => None,
    };
    let auth_url = match AuthUrl::new(get_or_error(&conf, &full_key(prefix, "auth_url"), error_value)?) {
        Ok(u) => u,
        _ => {
            error!("Could not parse authorization URL");
            return Err(error_value);
        },
    };
    let token_url = match get_optional(&conf, &full_key(prefix, "token_url")) {
        Some(v) => match TokenUrl::new(v) {
            Ok(u) => Some(u),
            Err(_) => {
                error!("Could not parse token URL");
                return Err(error_value);
            }
        },
        None => None,
    };

    let client = BasicClient::new(client_id, client_secret, auth_url, token_url);
    return Ok(client);
}

pub fn get_access_token<E: Copy>(conf: Config, prefix: &str, error_value: E, unauth_value: E) -> Result<BasicTokenResponse, E> {
    let scopes: Vec<&str> = get_or_error(&conf, &full_key(prefix, "scopes"), error_value)?;

    let client = get_client(conf, prefix, error_value)?;
    let mut request = client.exchange_client_credentials();
    for scope in scopes {
        request = request.add_scope(Scope::new(scope.to_string()));
    }

    let result = request.request(http_client);
    match result {
            Ok(t) => Ok(t),
            Err(e) => match e {
                RequestTokenError::ServerResponse(t) => {
                    error!("Authorization server returned error: {}", t);
                    return Err(unauth_value);
                },
                _ => {
                    error!("Error fetchin access token: {}", e);
                    return Err(error_value);
                },
            },
        }
}

pub fn get_access_token_password<E: Copy>(conf: Config, prefix: &str, username: String, password: String, error_value: E, unauth_value: E) -> Result<String, E> {
    let scopes: Vec<&str> = get_or_error(&conf, &full_key(prefix, "scopes"), error_value)?;

    let res_username = ResourceOwnerUsername::new(username);
    let res_password = ResourceOwnerPassword::new(password);

    let client = get_client(conf, prefix, error_value)?;
    let mut request = client.exchange_password(&res_username, &res_password);
    for scope in scopes {
        request = request.add_scope(Scope::new(scope.to_string()));
    }

    let result = request.request(http_client);
    match result {
            Ok(t) => Ok("".to_string()),
            Err(e) => match e {
                RequestTokenError::ServerResponse(t) => {
                    error!("Authorization server returned error: {}", t);
                    return Err(unauth_value);
                },
                _ => {
                    error!("Error fetchin access token: {}", e);
                    return Err(error_value);
                },
            },
        }
}

fn do_json_request<E: Copy>(conf: Config, url: String, error_value: E, unauth_value: E) -> Result<String, E> {
    let token = get_access_token(conf, "nss", error_value, unauth_value)?;
    Ok("".to_string())
}