Skip to content

Commit 1678d25

Browse files
committed
use upstream data
1 parent 86eb623 commit 1678d25

File tree

2 files changed

+42
-11
lines changed

2 files changed

+42
-11
lines changed

crates/handlers/src/upstream_oauth2/link.rs

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,6 @@ pub(crate) enum FormData {
209209
accept_terms: Option<String>,
210210
},
211211
Link,
212-
Associate {
213-
#[serde(default)]
214-
username: Option<String>,
215-
},
216212
}
217213

218214
impl ToFormState for FormData {
@@ -653,10 +649,46 @@ pub(crate) async fn post(
653649
session
654650
}
655651

656-
(None, None, FormData::Associate { username }) => {
657-
//user already exists, but it is not linked, neither connected
658-
//proceed by associating the link and connect the user
652+
(None, None, FormData::Link) => {
653+
// User already exists, but it is not linked, neither logged in
654+
// Proceed by associating the link to the user and log in the user
655+
// Upstream_session is used to re-render the username as it is the only source of truth
656+
657+
let id_token = upstream_session.id_token().map(Jwt::try_from).transpose()?;
659658

659+
let provider = repo
660+
.upstream_oauth_provider()
661+
.lookup(link.provider_id)
662+
.await?
663+
.ok_or(RouteError::ProviderNotFound(link.provider_id))?;
664+
665+
// Let's import the username from the localpart claim
666+
let env = environment();
667+
668+
let mut context = AttributeMappingContext::new();
669+
if let Some(id_token) = id_token {
670+
let (_, payload) = id_token.into_parts();
671+
context = context.with_id_token_claims(payload);
672+
}
673+
if let Some(extra_callback_parameters) = upstream_session.extra_callback_parameters() {
674+
context = context.with_extra_callback_parameters(extra_callback_parameters.clone());
675+
}
676+
if let Some(userinfo) = upstream_session.userinfo() {
677+
context = context.with_userinfo_claims(userinfo.clone());
678+
}
679+
let context = context.build();
680+
681+
682+
//Claims import must be `require` or `force` at this stage
683+
let template = provider
684+
.claims_imports
685+
.localpart
686+
.template
687+
.as_deref()
688+
.unwrap_or(DEFAULT_LOCALPART_TEMPLATE);
689+
690+
let username = render_attribute_template(&env, template, &context, true)?;
691+
660692
let maybe_user = repo.user().find_by_username(&username.unwrap()).await?;
661693

662694
if maybe_user.is_some() {
@@ -706,6 +738,7 @@ pub(crate) async fn post(
706738
let env = environment();
707739

708740
let mut context = AttributeMappingContext::new();
741+
709742
if let Some(id_token) = id_token {
710743
let (_, payload) = id_token.into_parts();
711744
context = context.with_id_token_claims(payload);
@@ -1250,8 +1283,7 @@ mod tests {
12501283
let request = Request::post(&*mas_router::UpstreamOAuth2Link::new(link.id).path()).form(
12511284
serde_json::json!({
12521285
"csrf": csrf_token,
1253-
"action": "associate",
1254-
"username" : user.username.clone()
1286+
"action": "link"
12551287
}),
12561288
);
12571289
let request = cookies.with_cookies(request);

templates/pages/upstream_oauth2/login_link.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ <h1 class="title">{{ _("mas.upstream_oauth2.login_link.heading") }}</h1>
2323

2424
<form method="POST" class="cpd-form-root">
2525
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
26-
<input type="hidden" name="action" value="associate" />
27-
<input type="hidden" name="username" value="{{ linked_user.username }}" />
26+
<input type="hidden" name="action" value="link" />
2827

2928
{{ button.button(text=_("mas.upstream_oauth2.login_link.action")) }}
3029
</form>

0 commit comments

Comments
 (0)