Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More example code? #4

Closed
troelsarvin opened this issue Apr 18, 2022 · 2 comments
Closed

More example code? #4

troelsarvin opened this issue Apr 18, 2022 · 2 comments

Comments

@troelsarvin
Copy link

I'm trying to use axum-auth in an Axum handler like this:

async fn root_handler(
    ww: Extension<WorkstateWrapper>,
    AuthBasic((user_id, password)): AuthBasic
) -> Result<Html<String>, StatusCode> {
...

But as there is no authentication header yet, I simply end up with a

400 Bad Request: "`Authorization` header is missing

I'm looking for some way to test if the authorization header exists, and if not, send an 401 response along with a WWW-Authenticate header. Should the test somehow happen before the handler is called by the Router? - If so: How?

Can some more example code be added which shows how to use axum-auth in a slightly more real-world scenario?

@Owez
Copy link
Owner

Owez commented Apr 19, 2022

I think the objective you're trying to accomplish is out of the scope of this crate. It might be best to copy the basic auth handler from this library and edit it into doing custom parsing. Mockup pseudocode of what this might look like (untested, probably won't work):

pub struct AuthBasicExists(bool);

#[async_trait]
impl<B> FromRequest<B> for AuthBasicExists
where
    B: Send,
{
    type Rejection = (StatusCode, &'static str);

    async fn from_request(req: &mut RequestParts<B>) -> std::result::Result<Self, Self::Rejection> {
        let authorisation = req.headers().get(AUTHORIZATION)
        if let Some(authorisation) = authorisation {
            // continue with the original code
            let authorisation = authorisation.to_str()
            .map_err(|_| {
                (
                    StatusCode::BAD_REQUEST,
                    "`Authorization` header contains invalid characters",
                )
            })?;

            // Check that its a well-formed basic auth then decode and return
            let split = authorisation.split_once(' ');
            match split {
                Some((name, contents)) if name == "Basic" => {
                    // decode and instead of returning credentials, just return if they exist
                    decode_basic(contents)?;
                    Ok(Self(true))
                },
                _ => Err((
                    StatusCode::BAD_REQUEST,
                    "`Authorization` header must be for basic authentication",
                )),
            }
        } else {
            Ok(Self(false)) // return if its not there
        }
    }
}

Then you can use it inside of your function:

async fn root_handler(
    ww: Extension<WorkstateWrapper>,
    AuthBasicExists(exists): AuthBasicExists
) -> Result<Html<String>, StatusCode> {
...

Hope this helps!

@troelsarvin
Copy link
Author

OK, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants