jebrosen / rocket_oauth2

OAuth2 for Rocket applications
Apache License 2.0
67 stars 26 forks source link

Discord provider Exchange Failure. #55

Open vablings opened 5 months ago

vablings commented 5 months ago

Follow the example defined in the docs

[default.oauth.discord]
provider = "Discord"
client_id = ""
client_secret = ""
redirect_uri = "http://localhost:8000/auth/discord"
#[get("/login/discord")]
fn discord_login(oauth2: OAuth2<Discord>, cookies: &CookieJar<'_>) -> Redirect {
    oauth2.get_redirect(cookies, &["identify", "email", "connections"]).unwrap()
}

#[get("/auth/discord")]
fn discord_callback(token: TokenResponse<Discord>, cookies: &CookieJar<'_>) -> Redirect
{
    //println!("{:?}", token.access_token());
    //cookies.add_private(
    //    Cookie::build(("token", token.access_token().to_string()))
    //        .same_site(SameSite::Lax)
    //        .build()
    //);
    Redirect::to("/")
}

Will fail for the following despite the state cookie being matched?

GET /auth/discord?code=6S8cD7pykEFAoEfEdniokBeAUXbont&state=d96g8E5mmh3hQZqMrc_0GQ text/html:
   >> Matched: (discord_callback) GET /auth/discord
Error: The OAuth2 state cookie was missing. It may have been blocked by the client?
   >> Request guard `TokenResponse < Discord >` failed: Error { kind: ExchangeFailure, source: Some("The OAuth2 state returned from the server did match the stored state.") }.
   >> Outcome: Error(400 Bad Request)
vablings commented 5 months ago

It seems this is an intermittent issue? I had it working yesterday but now its not working again today.

jebrosen commented 5 months ago

I've seen this before with I think every provider I've tried, also intermittently. One thing you might try is using the Network inspector in a browser to validate whether or not it sends the cookie in the different requests - I did a quick test just now and confirmed that the rocket_oauth2_state cookie was not sent by the browser on the first attempt when using http:// in the redirect, but it was sent on future attempts. I'm not sure exactly why, but I had assumed it was a security measure of sorts that the cookie wasn't sent if it had been created earlier on the same redirect chain. Why it works on later attempts (with the cookie already set), I never figured out.

I don't have a good way to test it at present, but as I remember https:// consistently (and mysteriously?) worked as expected - so this was only a problem during development and not production.