All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rust-server.example-server-auth.mustache Maven / Gradle / Ivy

There is a newer version: 7.9.0
Show newest version
use swagger::{
    ApiError,
    auth::{Basic, Bearer},
    Has,
    XSpanIdString};
use {{{externCrateName}}}::{AuthenticationApi, Claims};
use crate::server::Server;
use jsonwebtoken::{decode, errors as JwtError, decode_header, DecodingKey, TokenData, Validation};
use swagger::auth::Authorization;
use log::{error, debug};

// NOTE: Set environment variable RUST_LOG to the name of the executable (or "cargo run") to activate console logging for all loglevels.
//     See https://docs.rs/env_logger/latest/env_logger/  for more details


/// Get a dummy claim with full permissions (all scopes) for testing purposes
fn full_permission_claim() -> Claims {
    // In this example code all available Scopes are added, so the current Bearer Token gets fully authorization.
    Claims {
        sub: "[email protected]".to_owned(),
        company: "ACME".to_owned(),
        iss: "mini-bank-IDP".to_owned(),
        aud: "org.acme.Resource_Server".to_string(),
        // added a very long expiry time
        exp: 10000000000,
        scopes:
        {{#hasAuthScopes}}
          [
            {{#authMethods}}
              {{#scopes}}
                    "{{{scope}}}",
              {{/scopes}}
            {{/authMethods}}
          ].join::<&str>(", ")
        {{/hasAuthScopes}}
        {{^hasAuthScopes}}
          "".to_owned()
        {{/hasAuthScopes}}
    }
}



/// Extract the data from a Bearer token using the provided Key (secret) and using the HS512-algorithm in this example.
fn extract_token_data(token: &str, key: &[u8]) -> Result, JwtError::Error> {

    // Ensure that you set the correct algorithm and correct key.
    // See https://github.com/Keats/jsonwebtoken for more information.
    let header = decode_header(token)?;
    let validation = {
        let mut validation = Validation::new(header.alg);
        validation.set_audience(&["org.acme.Resource_Server"]);
        validation.validate_exp = true;
        validation
    };

    let token_data = decode::(
        &token,
        &DecodingKey::from_secret(key),
        &validation,
    )?;

    Ok(token_data)
}

/// Build a swagger-Authorization based on the claims (Assuming claims have been extracted from a validated token)
fn build_authorization(claims: Claims) -> Authorization {
    let mut scopes = std::collections::BTreeSet::::new();
    claims
        .scopes
        .split(",")
        .map(|s| s.trim())
        .for_each(|s| {let _ = scopes.insert(s.to_string()); });
    let scopes = swagger::auth::Scopes::Some(scopes);

    Authorization{
        subject: claims.sub,
        scopes,
        issuer: Some(claims.iss)}
}

fn get_jwt_error_string(error: JwtError::Error) -> String {
    match error.kind() {
        JwtError::ErrorKind::InvalidSignature => "Incorrect token signature".to_owned(),
        JwtError::ErrorKind::InvalidAlgorithm => "The Algorithm is not correct".to_owned(),
        JwtError::ErrorKind::ExpiredSignature => "The token has expired".to_owned(),
        JwtError::ErrorKind::Base64(e) => format!("Base64 decode failed: {e}"),
        JwtError::ErrorKind::Json(e) => format!("JSON decoding: {e}"),
        JwtError::ErrorKind::Utf8(e) => format!("Invalid UTF-8: {e}"),
        _ => error.to_string()
    }
}


impl AuthenticationApi for Server where C: Has + Send + Sync {

    /// Implementation of the method to map a Bearer-token to an Authorization
    fn bearer_authorization(&self, bearer: &Bearer) -> Result {
        debug!("\tAuthorizationApi: Received Bearer-token, {bearer:#?}");

        match extract_token_data(&bearer.token, b"secret") {
            Ok(auth_data) => {
                debug!("\tUnpack auth_data as: {auth_data:#?}");
                let authorization = build_authorization(auth_data.claims);
                Ok(authorization)
            },
            Err(err) => {
                let msg = get_jwt_error_string(err);
                error!("Failed to unpack Bearer-token: {msg}");
                Err(ApiError(msg))
            }
        }
    }

    /// Implementation of the method to map an api-key to an Authorization
    fn apikey_authorization(&self, api_key: &str) -> Result {
        debug!("\tAuthorizationApi: Received api-key, {api_key:#?}");

        // TODO: insert the logic to map received apikey to the set of claims
        let claims = full_permission_claim();

        // and build an authorization out of it
        Ok(build_authorization(claims))
    }

    /// Implementation of the method to map a basic authentication (username and password) to an Authorization
    fn basic_authorization(&self, basic: &Basic) -> Result {
        debug!("\tAuthorizationApi: Received Basic-token, {basic:#?}");

        // TODO: insert the logic to map received apikey to the set of claims
        let claims = full_permission_claim();

        // and build an authorization out of it
        Ok(build_authorization(claims))
    }

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy