1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-23 11:02:35 +03:00

PKCE support

This commit is contained in:
Quentin Gliech
2021-10-05 14:08:21 +02:00
parent af71adbe7a
commit 8ecdf7c6c8
12 changed files with 168 additions and 57 deletions

View File

@@ -168,7 +168,7 @@ struct Params {
auth: AuthorizationRequest,
#[serde(flatten)]
pkce: Option<pkce::Request>,
pkce: Option<pkce::AuthorizationRequest>,
}
/// Given a list of response types and an optional user-defined response mode,
@@ -349,7 +349,7 @@ async fn get(
.add_code(&mut txn, &code, &params.pkce)
.await
.wrap_error()?;
};
}
// Do we already have a user session for this oauth2 session?
let user_session = oauth2_session.fetch_session(&mut txn).await.wrap_error()?;

View File

@@ -16,6 +16,7 @@ use std::collections::HashSet;
use oauth2_types::{
oidc::Metadata,
pkce::CodeChallengeMethod,
requests::{ClientAuthenticationMethod, GrantType, ResponseMode},
};
use warp::{Filter, Rejection, Reply};
@@ -62,6 +63,13 @@ pub(super) fn filter(
s
});
let code_challenge_methods_supported = Some({
let mut s = HashSet::new();
s.insert(CodeChallengeMethod::Plain);
s.insert(CodeChallengeMethod::S256);
s
});
let metadata = Metadata {
authorization_endpoint: base.join("oauth2/authorize").ok(),
token_endpoint: base.join("oauth2/token").ok(),
@@ -75,7 +83,7 @@ pub(super) fn filter(
response_modes_supported,
grant_types_supported,
token_endpoint_auth_methods_supported,
code_challenge_methods_supported: None,
code_challenge_methods_supported,
};
let cors = warp::cors().allow_any_origin();

View File

@@ -19,7 +19,10 @@ use headers::{CacheControl, Pragma};
use hyper::StatusCode;
use jwt_compact::{Claims, Header, TimeOptions};
use oauth2_types::{
errors::{InvalidGrant, OAuth2Error, OAuth2ErrorCode, UnauthorizedClient},
errors::{
InvalidGrant, InvalidRequest, OAuth2Error, OAuth2ErrorCode, ServerError, UnauthorizedClient,
},
pkce::CodeChallengeMethod,
requests::{
AccessTokenRequest, AccessTokenResponse, AuthorizationCodeGrant, RefreshTokenGrant,
},
@@ -166,6 +169,34 @@ async fn authorization_code_grant(
return error(UnauthorizedClient);
}
match (
code.code_challenge_method.as_ref(),
code.code_challenge.as_ref(),
grant.code_verifier.as_ref(),
) {
(None, None, None) => {}
// We have a challenge but no verifier (or vice-versa)? Bad request.
(Some(_), Some(_), None) | (None, None, Some(_)) => return error(InvalidRequest),
(Some(0 /* Plain */), Some(code_challenge), Some(code_verifier)) => {
if !CodeChallengeMethod::Plain.verify(code_challenge, code_verifier) {
return error(InvalidRequest);
}
}
(Some(1 /* S256 */), Some(code_challenge), Some(code_verifier)) => {
if !CodeChallengeMethod::S256.verify(code_challenge, code_verifier) {
return error(InvalidRequest);
}
}
// We have something else?
// That's a DB inconcistancy, we should bail out
_ => {
// TODO: are we sure we want to handle errors like that?
tracing::error!("Invalid state from the database");
return error(ServerError); // Somthing bad happened in the database
}
};
// TODO: verify PKCE
let ttl = Duration::minutes(5);
let (access_token, refresh_token) = {