openid-client 0.2.7

OpenID client for Rust
Documentation
use crate::{
    issuer::Issuer,
    types::{ClientMetadata, HttpMethod, IssuerMetadata},
};

use crate::tests::test_http_client::TestHttpReqRes;

#[tokio::test]
async fn posts_the_token_in_a_body_and_returns_none() {
    let http_client = TestHttpReqRes::new("https://op.example.com/token/revoke")
        .assert_request_method(HttpMethod::POST)
        .assert_request_header("content-length", vec!["37".to_string()])
        .assert_request_header(
            "content-type",
            vec!["application/x-www-form-urlencoded".to_string()],
        )
        .assert_request_body("client_id=identifier&token=tokenValue")
        .set_response_content_type_header("application/json")
        .set_response_body(r#"{"endpoint":"response"}"#)
        .build();

    let issuer_metadata = IssuerMetadata {
        revocation_endpoint: Some("https://op.example.com/token/revoke".to_string()),
        ..Default::default()
    };
    let issuer = Issuer::new(issuer_metadata);

    let client_metadata = ClientMetadata {
        client_id: Some("identifier".to_string()),
        token_endpoint_auth_method: Some("none".to_string()),
        ..Default::default()
    };

    let mut client = issuer.client(client_metadata, None, None, None).unwrap();

    let res = client
        .revoke_async(&http_client, "tokenValue", None, None)
        .await
        .unwrap();

    assert!(res.body.is_none());
}

#[tokio::test]
async fn posts_the_token_and_a_hint_in_a_body() {
    let http_client = TestHttpReqRes::new("https://op.example.com/token/revoke")
        .assert_request_method(HttpMethod::POST)
        .assert_request_header("content-length", vec!["66".to_string()])
        .assert_request_header(
            "content-type",
            vec!["application/x-www-form-urlencoded".to_string()],
        )
        .assert_request_body("client_id=identifier&token=tokenValue&token_type_hint=access_token")
        .set_response_content_type_header("application/json")
        .set_response_body(r#"{"endpoint":"response"}"#)
        .build();

    let issuer_metadata = IssuerMetadata {
        revocation_endpoint: Some("https://op.example.com/token/revoke".to_string()),
        ..Default::default()
    };
    let issuer = Issuer::new(issuer_metadata);

    let client_metadata = ClientMetadata {
        client_id: Some("identifier".to_string()),
        token_endpoint_auth_method: Some("none".to_string()),
        ..Default::default()
    };

    let mut client = issuer.client(client_metadata, None, None, None).unwrap();

    let result = client
        .revoke_async(&http_client, "tokenValue", Some("access_token"), None)
        .await;

    assert!(result.is_ok());
}

#[tokio::test]
async fn is_rejected_with_op_error_upon_oidc_error() {
    let http_client = TestHttpReqRes::new("https://op.example.com/token/revoke")
        .assert_request_method(HttpMethod::POST)
        .assert_request_header("content-length", vec!["37".to_string()])
        .assert_request_header(
            "content-type",
            vec!["application/x-www-form-urlencoded".to_string()],
        )
        .assert_request_body("client_id=identifier&token=tokenValue")
        .set_response_content_type_header("application/json")
        .set_response_body(
            r#"{"error":"server_error","error_description":"bad things are happening"}"#,
        )
        .set_response_status_code(500)
        .build();

    let issuer_metadata = IssuerMetadata {
        revocation_endpoint: Some("https://op.example.com/token/revoke".to_string()),
        ..Default::default()
    };
    let issuer = Issuer::new(issuer_metadata);

    let client_metadata = ClientMetadata {
        client_id: Some("identifier".to_string()),
        token_endpoint_auth_method: Some("none".to_string()),
        ..Default::default()
    };

    let mut client = issuer.client(client_metadata, None, None, None).unwrap();

    let err = client
        .revoke_async(&http_client, "tokenValue", None, None)
        .await
        .unwrap_err();

    assert!(err.is_op_error());

    let op_error = err.op_error();

    assert_eq!("server_error", op_error.error.error);
    assert_eq!(
        "bad things are happening",
        op_error.error.error_description.unwrap()
    );
}

#[tokio::test]
async fn is_rejected_with_when_non_200_is_returned() {
    let http_client = TestHttpReqRes::new("https://op.example.com/token/revoke")
        .assert_request_method(HttpMethod::POST)
        .assert_request_header("content-length", vec!["37".to_string()])
        .assert_request_header(
            "content-type",
            vec!["application/x-www-form-urlencoded".to_string()],
        )
        .assert_request_body("client_id=identifier&token=tokenValue")
        .set_response_content_type_header("application/json")
        .set_response_body("Internal Server Error")
        .set_response_status_code(500)
        .build();

    let issuer_metadata = IssuerMetadata {
        revocation_endpoint: Some("https://op.example.com/token/revoke".to_string()),
        ..Default::default()
    };
    let issuer = Issuer::new(issuer_metadata);

    let client_metadata = ClientMetadata {
        client_id: Some("identifier".to_string()),
        token_endpoint_auth_method: Some("none".to_string()),
        ..Default::default()
    };

    let mut client = issuer.client(client_metadata, None, None, None).unwrap();

    let err = client
        .revoke_async(&http_client, "tokenValue", None, None)
        .await
        .unwrap_err();

    assert!(err.is_op_error());

    let op_error = err.op_error();

    assert!(op_error.response.is_some());
    assert_eq!("server_error", op_error.error.error);
    assert_eq!(
        "expected 200 OK, got: 500 Internal Server Error",
        op_error.error.error_description.unwrap()
    );
}

#[tokio::test]
async fn completely_ignores_the_response_even_invalid_or_html_one() {
    let http_client = TestHttpReqRes::new("https://op.example.com/token/revoke")
        .assert_request_method(HttpMethod::POST)
        .assert_request_header("content-length", vec!["37".to_string()])
        .assert_request_header(
            "content-type",
            vec!["application/x-www-form-urlencoded".to_string()],
        )
        .assert_request_body("client_id=identifier&token=tokenValue")
        .set_response_content_type_header("application/json")
        .set_response_body(r#"{"notvalid"}"#)
        .build();

    let issuer_metadata = IssuerMetadata {
        revocation_endpoint: Some("https://op.example.com/token/revoke".to_string()),
        ..Default::default()
    };
    let issuer = Issuer::new(issuer_metadata);

    let client_metadata = ClientMetadata {
        client_id: Some("identifier".to_string()),
        token_endpoint_auth_method: Some("none".to_string()),
        ..Default::default()
    };

    let mut client = issuer.client(client_metadata, None, None, None).unwrap();

    let result = client
        .revoke_async(&http_client, "tokenValue", None, None)
        .await;

    assert!(result.is_ok());
}

#[tokio::test]
async fn handles_empty_bodies() {
    let http_client = TestHttpReqRes::new("https://op.example.com/token/revoke")
        .assert_request_method(HttpMethod::POST)
        .assert_request_header("content-length", vec!["37".to_string()])
        .assert_request_header(
            "content-type",
            vec!["application/x-www-form-urlencoded".to_string()],
        )
        .assert_request_body("client_id=identifier&token=tokenValue")
        .set_response_content_type_header("application/json")
        .build();

    let issuer_metadata = IssuerMetadata {
        revocation_endpoint: Some("https://op.example.com/token/revoke".to_string()),
        ..Default::default()
    };
    let issuer = Issuer::new(issuer_metadata);

    let client_metadata = ClientMetadata {
        client_id: Some("identifier".to_string()),
        token_endpoint_auth_method: Some("none".to_string()),
        ..Default::default()
    };

    let mut client = issuer.client(client_metadata, None, None, None).unwrap();

    let result = client
        .revoke_async(&http_client, "tokenValue", None, None)
        .await;

    assert!(result.is_ok());
}