oauth flow /authorize and /token endpoints#115
oauth flow /authorize and /token endpoints#115Sanket-Singhvi wants to merge 4 commits intopatr-cloud:developfrom
Conversation
| ts-rs = { default-features = false, version = "11" } | ||
| typed-builder = { default-features = false, version = "0.23" } | ||
| url = { default-features = false, version = "2" } | ||
| urlencoding = { default-features = false, version = "2" } |
There was a problem hiding this comment.
serde_qs is already there. Can't we use that?
models/src/error.rs
Outdated
| Self::InvalidResponseType => { | ||
| "The response type provided in the OAuth2.1 authorize request is not supported" | ||
| } | ||
| Self::InvalidGrantType => { | ||
| "The grant type provided in the OAuth2.1 token request is not supported" | ||
| } | ||
| Self::InvalidAuthorizationCode => { | ||
| "The authorization code provided in the OAuth2.1 token request is invalid" | ||
| } |
There was a problem hiding this comment.
OAuthInvalidResponseTypeOAuthInvalidGrantTypeOAuthInvalidAuthorizationCode
models/src/error.rs
Outdated
| @@ -137,6 +144,8 @@ impl ErrorType { | |||
| Self::RoleInUse => StatusCode::CONFLICT, | |||
| Self::RunnerAlreadyConnected => StatusCode::CONFLICT, | |||
| Self::InvalidRunnerMode => StatusCode::FORBIDDEN, | |||
| Self::InvalidGrantType => StatusCode::BAD_REQUEST, | |||
| Self::InvalidAuthorizationCode => StatusCode::BAD_REQUEST, | |||
There was a problem hiding this comment.
Are these validated with the OAuth spec?
| } | ||
| ); | ||
|
|
||
| macros::declare_api_endpoint!( |
| .into_result() | ||
| } | ||
|
|
||
| pub async fn authorize_post( |
| let success = argon2::Argon2::new_with_secret( | ||
| config.password_pepper.as_ref(), | ||
| Algorithm::Argon2id, | ||
| Version::V0x13, | ||
| constants::HASHING_PARAMS, | ||
| ) | ||
| .inspect_err(|err| { | ||
| error!("Error creating Argon2: `{}`", err); | ||
| }) | ||
| .map_err(ErrorType::server_error)? | ||
| .verify_password( | ||
| password.as_bytes(), | ||
| &PasswordHash::new(&user_data.password).map_err(ErrorType::server_error)?, | ||
| ) | ||
| .inspect_err(|err| { | ||
| info!("Error verifying password: `{}`", err); | ||
| }) | ||
| .is_ok(); |
There was a problem hiding this comment.
What's the point of this? The whole reason of OAuth is to not give the password to the client
|
|
||
| // Store the authorization code and its metadata in the redis with an expiration | ||
| // time. | ||
| let key = format!("auth_code:{}", authorization_code); |
There was a problem hiding this comment.
This should be in the redis::keys module
| }) | ||
| .map_err(ErrorType::server_error)?; | ||
|
|
||
| let redirect_uri_str = redirect_uri.as_deref().unwrap_or(""); |
There was a problem hiding this comment.
Again, this should come from the DB ideally
| } | ||
| } else { | ||
| if code_verifier != auth_code_data.code_challenge { | ||
| return Err(ErrorType::InvalidGrantType); |
There was a problem hiding this comment.
Idk if this is the right error here
| } | ||
| } else if grant_type == OAuthTokenGrantType::RefreshToken { | ||
| // Handle refresh token grant type | ||
| let key = format!("refresh_token:{}", refresh_token.unwrap()); |
There was a problem hiding this comment.
keys in a separate module
| "Generated authorization code `{}` for client_id `{}`", | ||
| authorization_code, client_id | ||
| ); | ||
| let metadata = json!({ |
There was a problem hiding this comment.
Make a struct out of this
| use crate::prelude::*; | ||
|
|
||
| #[derive(Serialize)] | ||
| struct RedirectQueryParams { |
There was a problem hiding this comment.
Document what this is
| ErrorType::server_error(e) | ||
| })?; | ||
|
|
||
| let redirect_url = if let Some(uri) = redirect_uri { |
There was a problem hiding this comment.
This should be validated with the DB
| use crate::prelude::*; | ||
|
|
||
| #[derive(Debug, Clone, Serialize, Deserialize)] | ||
| struct AuthCodeData { |
There was a problem hiding this comment.
We already have this na?
api/Cargo.toml
Outdated
| tracing-opentelemetry = { workspace = true, features = ["default"] } | ||
| tracing-subscriber = { workspace = true, features = ["default"] } | ||
| typed-builder = { workspace = true, features = [] } | ||
| urlencoding = { workspace = true, features = [] } |
| /// - PKCE challenge (if any) | ||
| /// | ||
| /// Then backend generates an authorization code and redirects. | ||
| OAuthAuthorizePost, |
| POST "/auth/oauth/authorize", | ||
| request = { | ||
| /// The client ID of the OAuth client | ||
| pub client_id: String, |
There was a problem hiding this comment.
Client secret needs to be there
| format!("registryBlobUploadPart:{}", session_id) | ||
| } | ||
| /// The prefix used for authorization_code for oauth | ||
| pub fn oauth_authorization_code_prefix(authorization_code: &str) -> String { |
There was a problem hiding this comment.
Strong types internally
…e database - Update `authorize` endpoint to validate client secret and redirect URI.
No description provided.