1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-31 09:24:31 +03:00

Support the email scope

This commit is contained in:
Quentin Gliech
2022-02-25 16:19:38 +01:00
parent cad6d54ddb
commit beef393bc8
3 changed files with 40 additions and 18 deletions

View File

@ -27,6 +27,7 @@ use mas_warp_utils::filters::{self, url_builder::UrlBuilder};
use oauth2_types::{ use oauth2_types::{
oidc::{ClaimType, Metadata, SubjectType}, oidc::{ClaimType, Metadata, SubjectType},
requests::{Display, GrantType, ResponseMode}, requests::{Display, GrantType, ResponseMode},
scope,
}; };
use warp::{filters::BoxedFilter, Filter, Reply}; use warp::{filters::BoxedFilter, Filter, Reply};
@ -72,7 +73,8 @@ pub(super) fn filter(
let scopes_supported = Some({ let scopes_supported = Some({
let mut s = HashSet::new(); let mut s = HashSet::new();
s.insert("openid".to_string()); s.insert(scope::OPENID.to_string());
s.insert(scope::EMAIL.to_string());
s s
}); });

View File

@ -22,10 +22,7 @@ use hyper::StatusCode;
use mas_config::{ClientConfig, ClientsConfig, HttpConfig}; use mas_config::{ClientConfig, ClientsConfig, HttpConfig};
use mas_data_model::{AuthorizationGrantStage, TokenType}; use mas_data_model::{AuthorizationGrantStage, TokenType};
use mas_iana::{jose::JsonWebSignatureAlg, oauth::OAuthClientAuthenticationMethod}; use mas_iana::{jose::JsonWebSignatureAlg, oauth::OAuthClientAuthenticationMethod};
use mas_jose::{ use mas_jose::{claims, DecodedJsonWebToken, SigningKeystore, StaticKeystore};
claims::{AT_HASH, AUD, AUTH_TIME, C_HASH, EXP, IAT, ISS, NONCE, SUB},
DecodedJsonWebToken, SigningKeystore, StaticKeystore,
};
use mas_storage::{ use mas_storage::{
oauth2::{ oauth2::{
access_token::{add_access_token, revoke_access_token}, access_token::{add_access_token, revoke_access_token},
@ -50,7 +47,7 @@ use oauth2_types::{
requests::{ requests::{
AccessTokenRequest, AccessTokenResponse, AuthorizationCodeGrant, RefreshTokenGrant, AccessTokenRequest, AccessTokenResponse, AuthorizationCodeGrant, RefreshTokenGrant,
}, },
scope::OPENID, scope,
}; };
use rand::thread_rng; use rand::thread_rng;
use serde::Serialize; use serde::Serialize;
@ -284,34 +281,41 @@ async fn authorization_code_grant(
.await .await
.wrap_error()?; .wrap_error()?;
let id_token = if session.scope.contains(&OPENID) { let id_token = if session.scope.contains(&scope::OPENID) {
let mut claims = HashMap::new(); let mut claims = HashMap::new();
let now = Utc::now(); let now = Utc::now();
ISS.insert(&mut claims, issuer.to_string()).wrap_error()?; claims::ISS
SUB.insert(&mut claims, &browser_session.user.sub) .insert(&mut claims, issuer.to_string())
.wrap_error()?; .wrap_error()?;
AUD.insert(&mut claims, client.client_id.clone()) claims::SUB
.insert(&mut claims, &browser_session.user.sub)
.wrap_error()?; .wrap_error()?;
IAT.insert(&mut claims, now).wrap_error()?; claims::AUD
EXP.insert(&mut claims, now + Duration::hours(1)) .insert(&mut claims, client.client_id.clone())
.wrap_error()?;
claims::IAT.insert(&mut claims, now).wrap_error()?;
claims::EXP
.insert(&mut claims, now + Duration::hours(1))
.wrap_error()?; .wrap_error()?;
if let Some(ref nonce) = authz_grant.nonce { if let Some(ref nonce) = authz_grant.nonce {
NONCE.insert(&mut claims, nonce.clone()).wrap_error()?; claims::NONCE
.insert(&mut claims, nonce.clone())
.wrap_error()?;
} }
if let Some(ref last_authentication) = browser_session.last_authentication { if let Some(ref last_authentication) = browser_session.last_authentication {
AUTH_TIME claims::AUTH_TIME
.insert(&mut claims, last_authentication.created_at) .insert(&mut claims, last_authentication.created_at)
.wrap_error()?; .wrap_error()?;
} }
AT_HASH claims::AT_HASH
.insert( .insert(
&mut claims, &mut claims,
hash(Sha256::new(), &access_token_str).wrap_error()?, hash(Sha256::new(), &access_token_str).wrap_error()?,
) )
.wrap_error()?; .wrap_error()?;
C_HASH claims::C_HASH
.insert(&mut claims, hash(Sha256::new(), &grant.code).wrap_error()?) .insert(&mut claims, hash(Sha256::new(), &grant.code).wrap_error()?)
.wrap_error()?; .wrap_error()?;

View File

@ -18,14 +18,19 @@ use mas_warp_utils::filters::{
self, self,
authenticate::{authentication, recover_unauthorized}, authenticate::{authentication, recover_unauthorized},
}; };
use oauth2_types::scope;
use serde::Serialize; use serde::Serialize;
use serde_with::skip_serializing_none;
use sqlx::PgPool; use sqlx::PgPool;
use warp::{filters::BoxedFilter, Filter, Rejection, Reply}; use warp::{filters::BoxedFilter, Filter, Rejection, Reply};
#[derive(Serialize)] #[derive(Serialize)]
#[skip_serializing_none]
struct UserInfo { struct UserInfo {
sub: String, sub: String,
username: String, username: String,
email: Option<String>,
email_verified: Option<bool>,
} }
pub(super) fn filter(pool: &PgPool) -> BoxedFilter<(Box<dyn Reply>,)> { pub(super) fn filter(pool: &PgPool) -> BoxedFilter<(Box<dyn Reply>,)> {
@ -48,8 +53,19 @@ async fn userinfo(
session: Session<PostgresqlBackend>, session: Session<PostgresqlBackend>,
) -> Result<Box<dyn Reply>, Rejection> { ) -> Result<Box<dyn Reply>, Rejection> {
let user = session.browser_session.user; let user = session.browser_session.user;
Ok(Box::new(warp::reply::json(&UserInfo { let mut res = UserInfo {
sub: user.sub, sub: user.sub,
username: user.username, username: user.username,
}))) email: None,
email_verified: None,
};
if session.scope.contains(&scope::EMAIL) {
if let Some(email) = user.primary_email {
res.email_verified = Some(email.confirmed_at.is_some());
res.email = Some(email.email);
}
}
Ok(Box::new(warp::reply::json(&res)))
} }