-
Hi, I implemented the Authorization Code Flow with Proof Key for Code Exchange (PKCE) with hydra, but I'm little bit annoying about a difference between hydra and the other authorization server behavior. Is the |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
No, it is not mandatory? If thats not it, could you provide some more information on your setup, version, error logs, config ect.? |
Beta Was this translation helpful? Give feedback.
-
Quick update: Indeed More explanations: After you answer, I dig deeply on my implementation and I figure out my OAuth client was not well configured. [package]
name = "test_pkce"
version = "0.1.0"
authors = ["Mat <[email protected]>"]
edition = "2018"
[dependencies]
reqwest = { version = "0.11", features = ["blocking", "json"] }
tokio = { version = "1", features = ["full"] }
headless_chrome = "0.1.1"
regex = "1"
querystring = "1.1.0"
pkce= "0.1.1"
serde = "1.0.123"
serde_json = "1.0" use headless_chrome::{browser::default_executable, Browser, LaunchOptionsBuilder};
use pkce;
use querystring;
use regex::Regex;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use serde_json::to_string_pretty;
use std::collections::HashMap;
use std::str;
use std::time::Duration;
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Token {
pub access_token: String,
pub expires_in: i64,
pub id_token: String,
pub scope: String,
pub token_type: String,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let code_verify = pkce::code_verifier(128);
let code_verifier = str::from_utf8(&code_verify).unwrap();
let code_challenge = pkce::code_challenge(&code_verify);
let client_id = "CLIENT_ID_TO_CHANGE";
let state = "RANDOM_STATE_TO_CHANGE";
let redirect_uri = "REDIRECT_URL_TO_SET";
let url = format!(
"OAUTH_SERVER_HOST_TO_CHANGE/oauth2/auth?{}",
querystring::stringify(vec![
("response_type", "code"),
("code_challenge", &code_challenge),
("code_challenge_method", "S256"),
("client_id", client_id),
("redirect_uri", redirect_uri),
("scope", "openid offline"),
("state", state),
])
);
println!("\n> Going to {:#?}", url);
let browser = Browser::new(
LaunchOptionsBuilder::default()
.path(Some(default_executable().unwrap()))
.headless(false)
.build()
.unwrap(),
)?;
let tab = browser.wait_for_initial_tab()?;
tab.navigate_to(&url)?;
tab.wait_for_element_with_custom_timeout("SELECTOR_TO_WAIT_TO_KNOW_WHEN_WE_ARE_ON_REDIRECT_URL", Duration::from_secs(100))?;
let url_with_code = tab.get_url();
let re = Regex::new(r"^.*?\?code=(?P<code>.*?)&scope.*?$").unwrap();
let code = re
.captures(&url_with_code)
.unwrap()
.name("code")
.unwrap()
.as_str();
println!("\n> Finding code {}", code);
let http_client = Client::new();
let mut params = HashMap::new();
let grant_type = "authorization_code";
params.insert("grant_type", grant_type);
params.insert("client_id", client_id);
params.insert("code_verifier", code_verifier);
params.insert("code", code);
params.insert("redirect_uri", redirect_uri);
println!("\n> Calling token endpoint with");
println!(" grant_type: {}", grant_type);
println!(" client_id: {}", client_id);
println!(" code_verifier: {}", code_verifier);
println!(" code: {}", code);
println!(" redirect_uri: {}", redirect_uri);
let resp: Token = http_client
.post("OAUTH_SERVER_HOST_TO_CHANGE/oauth2/token")
.form(¶ms)
.send()
.await?
.json()
.await?;
println!(
"
========================================
Token endpoint response
========================================"
);
print!("{}", to_string_pretty(&resp).unwrap());
Ok(())
} |
Beta Was this translation helpful? Give feedback.
Quick update: Indeed
client_secret
is not mandatory for this kind of grant flow. I explain here the solution for tracing.More explanations: After you answer, I dig deeply on my implementation and I figure out my OAuth client was not well configured.
Indeed, to use an Authorization Code Flow with Proof Key for Code Exchange (PKCE) you have to set
token_endpoint_auth_method
tonone
.I had a second issue on my implementation about the SHA256 then base64 transformation to generate the
code_verifier
. The majority of online tool to generate this value produced malformed value.I share with you a working example written in Rust: